Package: zest.pocompile
IntroductionThis package compiles po files.
It contains azest.releaserentrypoint and a stand-alone command line tool.GoalYou want to release a package that has alocalesdir
(orlocale, or something else as long as it has aLC_MESSAGESfolder somewhere in it)
with translations in.pofiles.
You want to include the compiled.mofiles in your release as well,
but you do not want to keep those in a revision control system (like git) as they are binary and can be easily recreated.
That is good.
This package helps with that.Want.mofiles?  Add aMANIFEST.infile.When you usepython setup.py sdistto create a source distribution, Python doesnotautomatically include all files.
It might look at the information of the revision control system (RCS), but that may or may not work.
This depends on your RCS, your Python version, setuptools, or extra packages likesetuptools-git.Since the compiled.mofiles are best not stored in git (or any other RCS), you need to give a hint on which files to include.
You do this by adding aMANIFEST.infile.
Let’s say your package has roughly these contents (not all files are shown):your.package/setup.py
your.package/your/package/locales/nl/LC_MESSAGES/domain.poThen you need aMANIFEST.infile like this:recursive-include your *Or with a bigger example:recursive-include your *
recursive-include docs *
include *
global-exclude *.pycI will explain the lines one by one for clarity.
And yes: I (Maurits) now simply go to this page on PyPI if I want to have an example of a properMANIFEST.infile.
So this documentation is now getting slightly larger than strictly needed. :-)recursive-includeyour *This tells distutils to recursively include all (*) files and directories within theyourdirectory.
Try it: create a directory structure like the above example with a propersetup.py,
copy thedomain.pofile todomain.moas a silly test,
runpython setup.py sdistand check that the.mofile ends up in the created distribution.recursive-includedocs *Include files in thedocsdirectory.
If this directory does not exist, you will get a warning, so you may want to remove it then, but leaving it there does not hurt.include *Include unrecognized files in the root directory.
Oterwise by default only standard files likeREADME.txt,setup.py, andsetup.cfgare included.
So for example aCHANGES.txtfile must be explicitly included (here with*).global-exclude*.pycThis avoids unnecessarily adding compiled python files in the release.
When these are not there, for example after a fresh checkout, you will get a harmless warning:nopreviously-includedfiles matching'*.pyc'found anywhere in distribution.For more info on creating a source distribution and how to useMANIFEST.insee thePython distutils documentationor thesetuptools documentation.With this part working, the only thing thiszest.pocompilepackage needs to do, is to actually find all.pofiles and compile them to.mofiles.
It simply looks for directories that are namedLC_MESSAGESand compiles all.pofiles found in there.Command line toolWhen youpip install zest.pocompileyou get a command line toolpocompile.
When you run it, this walks the current directory, finds all po translation files in a properly formed locales directory, and compiles them into.mofiles.
You can also give it a list of directories as arguments instead.
Run it with the--helpoption to get some help.In the above example, if you are in theyour.packagedirectory and runpocompileit will create this file:your.package/your/package/locales/nl/LC_MESSAGES/domain.mozest.releaser entry pointYou do not needzest.releaserfor a proper functioning ofzest.pocompile.
But if you use the two together, in combination with a properMANIFEST.infile, releasing a source distribution with compiled.mofiles is made easy.Therelease(orfullrelease) command ofzest.releasercreates a (git or other) tag and checks out this tag.
Then it creates a source distribution (sdist) and possibly a wheel (bdist_wheel) and uploads it to PyPI.
Whenzest.pocompileis added to the mix, it compiles the.pofiles immediately after checking out the tag.
This is right in time for creating the distributions, which should now contain the.mofiles.You may want the full release to fail early whenzest.pocompileis not available.
Since version 1.6.0 this is possible by editing thesetup.cfgof the package where you want this, and add the following section:[zest.releaser]
prereleaser.before =
    zest.pocompile.availableCreditsThis package has been cobbled together by Maurits van Rees.It depends on thepython-gettextpackage,.
This itself suggests using theBabelpackage.
But it does exactly what we need and its releases are stored on PyPI, so we ignore that suggestion.The main functions are taken from thebuild_mocommand ofcollective.releaser.Thanks!To DoAdd tests.Changelog2.0.0 (2023-09-11)Make final release.  Nothing changed since the last alpha.  [maurits]2.0.0a1 (2023-07-13)Require Python 3.8+ and switch to native namespace packages.
This is needed becausezest.releaser9.0.0a1 does the same.
[maurits]1.6.0 (2022-09-13)Addzest.pocompile.available.
You can use this to let the full release of a package fail early whenzest.pocompileis not available.
Edit itssetup.cfg, and add a[zest.releaser]section with valueprereleaser.before = zest.pocompile.available[maurits]1.5.0 (2020-01-29)Claim Python 2 and 3 compatibility.
Seems to work fine.
[maurits]1.4 (2013-07-05)Moved tohttps://github.com/zestsoftware/zest.pocompile.
[maurits]1.3 (2011-12-16)Fixed the example MANIFEST.in.
[maurits]1.2 (2011-12-16)Added a larger example of a MANIFEST.in file in the readme.  Also
add a MANIFEST.in in zest.pocompile itself, so the CHANGES.txt is
included in the source distribution.
[maurits]1.1 (2011-12-15)Look for.pofiles in anyLC_MESSAGESdirectory.  It no
longer matters if this is contained in a language directory within alocalesorlocaledirectory, as they could also have names
likeplonelocalesorlocales_for_version_2_only.  Note that
in Plone.pofiles can also be in an i18n directory, but those
should not be compiled; this does not have aLC_MESSAGESdirectory, so we automatically skip it.
[maurits]1.0 (2010-10-19)Initial release