Weblog
Maik Derstappen: Subtemplates in bobtemplates.plone or on the way to plonecli
Talk by Maik Derstappen at the Plone Conference 2017 in Barcelona.
A long time ago, creating a Plone package was as simple as using ZopeSkel and then ZopeSkel sub templates to add for example a new content type. But ZopeSkel is dead.
Plone is using the new mr.bob already for years, with bobtemplates.plone as main template for a new Plone project. But there were only basic templates, no list of templates, no way to add a content type or other things with a sub template, a hard to remember command. So let's fix that!
My vision: give me a tool which helps for:
- creating different projects, like an add-on or a buildout
- extending packages with content types, vocabularies, a theme
- provide best practice skeletons
Something like this:
$ pip instll plonecli $ plonecli -l templates: - addon - content_type - portlet - buildout $ plonecli add content_type
Standalone templates:
- addon: basic Plone addon
- buildout: development/project buildout
- theme_package: full stand-alone theme package, based on Barceloneta, with grunt setup
Sub templates:
- content_type: Dexterity CT with XML or zope.schema
- vocabulary: dynamic vocabulary
- theme: advanced theme, including themesitesetup and themefragments
- more to come: tile, behavior, portlet
I have a fork of mr.bob that can list templates.
On plonecli you could use shorter, more easier to remember commands, and I want autocompletion to make it even easier.
We will sprint on this, so please join.
Hanno Schlichting: Zope on Python 3
Talk by Hanno Schlichting at the Plone Conference 2017 in Barcelona.
I am currently still the release manager for Zope. There is now a actually a release team.
Plone is built up like this:
- Python is the programming language.
- On top of this is the ZODB and the ZCA (Zope Component Architecture)
- Then the ZTK (Zope ToolKit), just a bunch of packages.
- Above it is Zope (2.x/4.x)
- Then CMF
- Then the Plone CMS
Unrelated to Plone:
- Pyramid sits on top of the ZCA.
- Grok sits on top of the ZTK.
The ZTK (like zope.interface and zope.component) was already mostly Python 3 compatible at the moment when we started working on compatibility for Zope. Jason Madden has done a lot and Marius Gedminas, Tres Seaver, a bunch of others.. There is very little development on the ZTK level, mostly just letting it work on newer Python versions.
Alexander Loechel already gave a talk on this conference about porting RestrictedPython.
We no longer call Zope Zope2, but just Zope. This is version 4. Forget about version 3.
ZODB and the ZTK support Python 2.7, 3.4, 3.5, 3.6, PyPy, PyPy3. Status page of Python 3 compatibility for Zope related packages: https://zope3.pov.lt/py3/ More on the ZTK: https://zopetoolkit.readthedocs.io/
Zope 4.0 beta 2 has been released. That means no new major features should be introduced, focusing on bug fixes. Zope supports Python 2.7, 3.4, 3.5, 3.6. There is no support for PyPy or PyPy3. RestrictedPython is a big reason there, because that is currently just not possible on PyPy. For Acquisition you also have to use a C implementation, so no PyPy.
On https://blog.gocept.com you can find some good reports and stories about the Zope porting sprints.
CMF 2.4 beta is released. It targets Zope 4 compatibility. Currently only Python 2.7, but progress is being made on Python 3 support. The Plone community is also busy with that.
Some other changes in Zope 4, not Python 3 related:
- The distribution name was changed from Zope2 to Zope. Zope2 is now a meta distribution, depending only on Zope. This is similar to ZODB3 being renamed to ZODB. Please keep Zope2 as dependency in your own package, unless it really only works on Zope 4.
- Zope now uses WSGI, and there is a separate ZServer project. ZServer was written in the days of Python 1.5, so really old. We wanted to get rid of that and use WSGI instead. But to not completely lose the old code, we made this new ZServer project. The WSGI server only supports HTTP, not for example FTP. Also not WebDav as that was really to hard, although it is built on top of HTTP. Probably ZServer is never going to be ported to Python 3. So with WSGI you use something like waitress or gunicorn or Apache mod_wsgi to call Zope.
There are more optional projects for Zope now:
- ExternalMethod
- PythonScripts
- MailHost
- TemporaryFolder
- Sessions
- SiteErrorLog (instead just use the standard Python logging and the WSGI solutions for logging)
Some of these have been ported to Python 3, some not.
More changes:
- There now is a WSGI based zope.testbrowser. The old test browser was based on mechanize, which was not maintained and not ported, and that was not going to happen.
- There is full IPv6 support in waitress.
- Chameleon page templates is in Zope, without needing five.pt anymore.
- zope.globalrequest is in Zope, without needing five.globalrequest anymore.
- Upcoming minor change: support for unicode object ids under Python 3.
Zope 4 was started five or six years ago. The idea was first to remove lots of things to make it simpler. This has been partially reverted. But you might miss some features.
Future:
- Expect more Zope 4 beta releases over the next monts.
- Expect a final Zope 4 final release when it is done. :-) That will be when we have the feeling it is stable enough and we are only doing small bug fixes. See the issue tracker.
- There are no plans for Zope 4.1 or 5.0 yet. A nicer ZMI (Zope Management Interface) is being worked on, so it does not look like it was made in the eighties.
Remarks from the audience:
- David: Plone on Zope 4 is being worked on, and is making progress. We will further sprint on it this weekend.
- Eric: We will create a branch for Plone 5.2 this weekend, and try to get an alpha out soon.
Johannes Raggam: Resource Registry Demystified
Talk by Johannes Raggam at the Plone Conference 2017 in Barcelona.
The rewrite of the RRs (resource registries) started in 2013 or 2014 and landed in Plone 5.0. I would recommend using Plone 5.1, as various things have been improved there.
With the RR you register and deploy JS and CSS. You can organise dependencies, and optimise resources and number of requests. The resources are grouped into bundles, they are concatenated and minified. Add-ons can easily register their resources. Cache headers are set automatically.
In Plone 4 there were no formally defined dependencies, so that made it hard to manage. You just had a list, and that order was used.
In Plone 5, the RRs are based on plone.registry, RequireJS, LESS and the command line interface of gulp. Instead of LESS, a lot of projects have switched to using SASS now. RequireJS is also less popular. So there is still room for advancement.
The Plone 5 way solves dependency management, but it is complexer and harder to debug. I have had my problems with it, but usually it works quite well, and is a huge improvement over Plone 4.
The js/config.js file in mockup contains configuration on how the javascript in Plone should be built. In Products/CMFPlone/static/plone.js you can see how the plone bundle is defined, and what it requires.
You can still define legacy resources, which work like they did in Plone 4. They are wrapped by some code that temporarily undefines the define and require definitions, otherwise you get errors.
In Products/CMFPlone/static/plone.less all the needed LESS definitions are imported or defined, used for creating our CSS. LESS is very handy for defining for example a text color once and use it in lots of places. [In Plone 4 we did this by using DTML files.]
You can customise and override the plone and plone-loggedin bundles in your code, if you maybe do not need everything that Plone offers by default.
collective.lazysizes has a good example of defining resources and bundles. In its registry.xml it uses condition="have plone-5" to only apply this part on install when the site is Plone 5.
With ./bin/plone-compile-resources -b plone you compile the plone bundle resources. This is also possible TTW, but I recommend the command line tool.
Future
- Use webpack for compiling bundles. Asko Soukka has started with this for Plone. You can already use it, but it is too early for Plone core. There are some things to fix. I would like to not use RequireJS anymore, which would make it easier to use webpack; instead, ReactJS would be better. The legacy resources currently need special configuration, and that is not very expandable.
- PLIP 1955 for RR improvements, but on hold now for lack of time and vision
- PLIP 1653, restructure CMFPlone static resources
Devon Bernard: Lean React - Patterns for High-Performance
Talk by Devon Bernard at the Plone Conference 2017 in Barcelona.
Get a normalised state for your json data. Think about how to structure your data so you don't duplicate data, and you have quick retrieval. For example use the normalizr library.
Use Redux development tools to give you hints or boiler plate for a new test.
Use components. When you use them, make sure they don't block other components: if four other components are not getting shown until a fifth one is ready, that is not a good idea. Give the user the information that is already there. Already show a skeleton on the page of how the component is going to look, so you only need to fill in some extra stuff and the user can already see how the component will look like.
Watch the component life cycle: which part is taking the most time?
Check if repainting is really needed before you do it: maybe a data value gets set but it is the same as the old value. Catch this and save on rendering. Use the Chrome Render Tools.
Use local, non-committed environment files to make differences between local development and production. .env may contain the default values for everyone, committed, and .env.local has your local tweaks, and you let git ignore that.
Use route wrappers to for example ease checking for anonymous or authenticated users, and do some calculations in there, so you don't need to do that in all kinds of places.
Offline first: have some javascript that runs in the background for hijacking netword requests. If you are offline, this should queue the network requests for later. IndexedDB could be more useful here than localstorage.
Use the ESLint command line utility to check the quality of your code, including your fellow developers.
Find me on Twitter: @devonwbernard.
Nathan Van Gheem: Introduction to Python Asyncio
Talk by Nathan Van Gheem at the Plone Conference 2017 in Barcelona.
This is about the Python 3 core asyncio library. "This module provides infrastructure for writing single-threaded concurrent code using coroutines, multiplexing I/O access over sockets and other resources, running network clients and servers, and other related primitives."
The first time I read that I was like: what?
Asynchronous programming using async and await syntax. Any network activity should not block other code, that is the main idea. This is useful because web applications use TCP sockets. It is a way to improve performance and scale web applications. Also think of microservices.
The optimised event loop allows you to handle a larger number of requests per second. You can have long running requests with very little performance impact. With standard Plone that is impossible.
Requirements: Python 3.4.
How are typical web servers designed like Flask, and Django? Each request is tied to a thread, so you are limited to handling number of threads and processes you run. Threads are expensive (GIL, context switching, CPU). If no threads are available, further requests are blocked, waiting for an open thread. Threads are blocked by network traffic, for example to a database server.
With asyncio, requests can be tied to tasks. You can have lots of tasks per thread, and if a task needs to wait for network traffic, it does not hurt you. But be careful: if anywhere in your code you use the requests library instead of asyncio, that will block your network traffic.
We have Futures`. ``asyncio.run_until_complete with ensure_future wraps your asynchronous call in a Future object.
You can have long running Tasks. Tasks, futures and coroutines are very similar, in the beginning you don't need to worry about that.
Gotcha: everything must be async. Async functions need to be run by the event loop. If you run it manually, it will not do anything. If you don't call an async function using await it will never be run either.
asyncio is single threaded: only one event loop can run in a thread at a time. Running multi threaded code in asyncio is unsafe. You can have multiple threads, each having their own event loop. You can get the feel of multiprocessing by using asyncio.gather
With an 'executor' you can make synchronous code asynchronous. Typically it is a thread executor. Try to avoid it, but it is a tool that you can use if needed. See concurrent.futures.
asyncio comes with an amazing subprocess module, so you can await the result of executing a command on the terminal.
The event loop is pluggable, for example tokio.
More and more libraries are popping up using asyncio:
- aiohttp: client and server library
- aioes for elastic search
- asyncpg for postgres
- aioredis
- aiobotocore
- aiosmtpd for smtp
[See https://github.com/aio-libs for more.]
Debugging is more difficult than regulare sequential programs, the pdb is tricky. aioconsole allows you to have a Python prompt with an asyncio loop already setup for you.
guillotina uses asyncio.
In Python 3.7 you have an execution context, which is going to be nice.
Questions and answers:
- You cannot do WSGI with asyncio. But Tornado uses asyncio.
- What was hardest? Wrapping your head around it all.
- Is this only for network calls? Or also useful for disk access? There is an add-on for that. I tried it and then it was kind of a hack.
- Do you have profiler tools, like seeing if code is blocking too long? See an earlier talk. There is `aiomonitor <https://github.com/aio-libs/aiomonitor>`_.
Twitter: @vangheezy