plone.api: plone development best practices revealed
DESCRIPTION
The plone.api is an elegant and simple API, built for humans wishing to develop with Plone. It comes with cookbook-like documentation with step-by-step instructions for doing common development tasks in Plone. Recipes try to assume the user does not have extensive knowledge about Plone internals. The talk will be about the philosophy and rationale behind it, what it offers and how to use it. Since recently plone.api's code conventions and style guide have been adopted by the Framework Team as the Plone Core conventions. We'll go through these recommendations and discuss why they are there and why you should start using them in your own code also. Finally, we'll walk through some bits and pieces of plone.api's internal code, to give you the idea of how modern Plone code should be organized and formatted, as an example of coding conventions mentioned above.TRANSCRIPT
plone.apiPlone development best practices revealed
@nzupan
petek, 04. oktober 13
Everybody stand up please!
petek, 04. oktober 13
petek, 04. oktober 13
self.context
petek, 04. oktober 13
• 2006
• Student workshop
• Plone 2.5
• Life was good!
petek, 04. oktober 13
eestec.net
• Online since 2009
• Switched to Plone 3 during development
• +2500 users
• Several events per month
petek, 04. oktober 13
+2500Electrical
Engineering Students
petek, 04. oktober 13
no. of new contributors:
petek, 04. oktober 13
no. of new contributors:
2
petek, 04. oktober 13
eestec.net
• Online since 2009
• ***Switched to Plone 3 during development***
• +2500 users
• Several events per month
petek, 04. oktober 13
Plone 3Impossible to: - train - write docs for - stay productive - keep devs happy
petek, 04. oktober 13
Plone 4?
petek, 04. oktober 13
From where to import that thing?
petek, 04. oktober 13
Many ways to get the Site root: which
is correct?
petek, 04. oktober 13
Copy/move objects?
target.manage_pasteObjects( source.manage_cutObjects(source_id))
petek, 04. oktober 13
Workflow state?workflow = getToolByName(portal,'portal_workflow'
)workflow.getInfoFor(obj, 'review_state')
petek, 04. oktober 13
petek, 04. oktober 13
plone.api
petek, 04. oktober 13
plone.api• Started at Plone Konf Munich (2012)• Alpha release at Belgian Beer Sprint
(2012)• Beta release at Plone Conference in
Arnhem (2013)• RC at Wine Sprint Munich (2013)• 1.0 this week?
petek, 04. oktober 13
Inspiration
• PEP20• PEP8• Pareto Principle• SQLAlchemy• Requests
petek, 04. oktober 13
From where to import that thing?
petek, 04. oktober 13
from plone import api
petek, 04. oktober 13
Many ways to get the Site root: which
is correct?
petek, 04. oktober 13
api.portal.get()
petek, 04. oktober 13
Copy/move objects?
target.manage_pasteObjects( source.manage_cutObjects(source_id))
petek, 04. oktober 13
portal = api.portal.get()contact = portal['about']['contact']
api.content.move( source=contact, target=portal,)
petek, 04. oktober 13
Workflow state?workflow = getToolByName(portal,'portal_workflow'
)workflow.getInfoFor(obj, 'review_state')
petek, 04. oktober 13
api.content.get_state(obj=portal['about']
)
api.content.transition(obj=portal['about'], transition='publish',
)
petek, 04. oktober 13
It’s documented!
petek, 04. oktober 13
It’s documented
• Document first• Narrative documentation• Advanced usage documentation• Good code comments
petek, 04. oktober 13
petek, 04. oktober 13
petek, 04. oktober 13
It’s documented
• Document first• Narrative documentation• Advanced usage documentation• Good code comments
petek, 04. oktober 13
petek, 04. oktober 13
It’s tested!
petek, 04. oktober 13
It’s tested
• ~99% test coverage• Narrative documentation included• Continuous Integration
petek, 04. oktober 13
petek, 04. oktober 13
Import and Usage style
from plone import api
portal = api.portal.get()
user = api.user.create(username='bob')
api.content.move(
source=portal['blog'],
id='old-blog',
)petek, 04. oktober 13
• get()• get_navigation_root()• get_tool()• get_localized_time()• send_email()• show_message()• get_registry_record()
api.portal
petek, 04. oktober 13
api.content
• create()• get()• delete()• copy()• move()• rename()
• get_uuid()• get_view()• get_state()• transition()
petek, 04. oktober 13
api.user
• create()• get()• get_users()• get_current()• delete()
• is_anonymous()• get_roles()• get_permissions()• grant_roles()• revoke_roles()
petek, 04. oktober 13
api.group
• create()• get()• get_groups()• delete()
• add_user()• remove_user()• get_roles()• get_permissions()• grant_roles()• revoke_roles()
petek, 04. oktober 13
api.env
• adopt_roles() • adopt_user()
petek, 04. oktober 13
In the wild
• tutorial.todoapp• 150k objects / +1000 users production
site• hands up?
petek, 04. oktober 13
Latest Additions
• Various bug fixes• api.env.adopt_user() & api.env.adopt_roles()• Coding style guide!
petek, 04. oktober 13
api.env.adopt_roles
petek, 04. oktober 13
api.env.adopt_user
petek, 04. oktober 13
The Style Guide(included in Plone 5 core)
petek, 04. oktober 13
The Style Guide
• PEP 8• PEP 257• Rope project• Google Style Guide• Pylons Coding Style• Tim Pope on Git commit messages
petek, 04. oktober 13
Line Length
• 80 chars• # noqa if you need to break it• configure your editor!
petek, 04. oktober 13
Breaking Lines
• 1. Break into next line with one additional indent block
petek, 04. oktober 13
Breaking Lines
• 2. If this still doesn’t fit the 80-char limit, break into multiple lines
petek, 04. oktober 13
Docstrings
petek, 04. oktober 13
unittest2
• http://www.voidspace.org.uk/python/articles/unittest2.shtml
• fail* -> use assert* instead
• assertEquals -> assertEqual is the one true way
petek, 04. oktober 13
unittest2
• Deprecated:
failUnlessEqual, failIfEqual, failUnlessAlmostEqual, failIfAlmostEqual, failUnless,failUnlessRaises and failIf
petek, 04. oktober 13
unittest2
• assertGreater / assertLess / assertGreaterEqual / assertLessEqual
• assertRegexpMatches(text, regexp)
• assertIn(value, sequence)
• assertIs(first, second)
• assertIsNone
petek, 04. oktober 13
unittest2
• assertIsInstance / assertNotIsInstance
• assertDictContainsSubset(subset, full)
• assertSequenceEqual(actual, expected)
• assertItemsEqual(actual, expected)
petek, 04. oktober 13
unittest2
petek, 04. oktober 13
unittest2
• assertMultiLineEqual
• assertSetEqual
• assertDictEqual
• assertListEqual
• assertTupleEqual
petek, 04. oktober 13
unittest2
petek, 04. oktober 13
String Formatting
• Prefer new-style format()• Use numbering to support Python 2.6
petek, 04. oktober 13
Imports
petek, 04. oktober 13
Tracking Changes
petek, 04. oktober 13
Versioning Scheme
petek, 04. oktober 13
Commit Messages
petek, 04. oktober 13
Many More
• String quoting• Git workflow & branching model• Release process
petek, 04. oktober 13
Bonus Slide: plone.dotfiles
petek, 04. oktober 13
Coming up
petek, 04. oktober 13
api.env
• api.env.debug_mode()
• api.env.test_mode()
• api.env.plone_version()
• api.env.zope_version()
petek, 04. oktober 13
api.system
• Run upgrades
• Cleanup broken objects, utilities, interfaces ...
• Mount things
• Make sysadmins happy!
petek, 04. oktober 13
JSON WebServices
• Probably packaged as plone.jsonapi
• One-to-one mapping to plone.api methods
• @@jsonapi view
• Standardized JavaScript writing!
petek, 04. oktober 13
BONUS SLIDE!
petek, 04. oktober 13
Post-Conference sprint
• Implement remaining plone.api methods
• Get the test coverage even higher!
• Native speakers’ love to our docs
• Let’s get 1.0 release out there!
petek, 04. oktober 13
Open Tasks
• Deprecate plone.api on RTD
• Sphinx warnings should break the build
• plone.recipe.codeanalysis
• Coveralls.io
• Various bugs
• Proof-reading documentation
petek, 04. oktober 13
Open Tasks
• Changelog decision:
• CHANGES.rst or docs/CHANGES.rst
• “CHANGELOG” or “Changelog” or “CHANGES” or “Changes” for heading
petek, 04. oktober 13
Open Tasks
• Permission checks decision:
• apply them?
• go around them?
• let the user decide with “strict=True”?
petek, 04. oktober 13
Open Tasks
• THE BIG ONE: usage scope
• use in core? performance issues ...
• use in add-ons? might creep into core
• only allow usage in integration code?
petek, 04. oktober 13
Thanks!&
See you at the sprint
http://github.com/plone/plone.api
petek, 04. oktober 13