[Distutils] DRAFT PEP 396 - module version number

Éric Araujo merwok at netwok.org
Fri Mar 25 03:52:14 CET 2011


Hi Barry,

Thanks for writing this PEP.  I’m +1 on the general idea, but not on all
sections.  I agree with all text that I haven’t quoted; quoted parts are
commented with my reservations, suggested amendments and typo fixes.

Martin and Alexis are directly cc’d because I have asked them to confirm
or reply to two things that I wasn’t sure about.

> `distutils2` [1]_) may be adapted to use the conventions defined here.
Nit: I never rely on docutils/sphinx default role (using a bare `text`
without explicit :role:), cause I never remember what it is, and the
produced text may not be what you thought it would.

> Alice is writing a new module, called ``alice.py``, which she wants to
> share with other Python developers.  ``alice.py`` is a simple module
> and lives in one file.
You should call the module alice and the file alice.py to eliminate
weirdness.  (Ditto for other examples throughout the PEP.)

> Bob learns about the Cheeseshop [2]_, and adds some
> simple packaging using classic distutils so that he can upload *The
> Bob Package* to the Cheeseshop.
I know that the referenced PEP 345 call these things “software
packages”, but let’s try to use consistent terminology.  See threads
starting at
http://mail.python.org/pipermail/distutils-sig/2011-March/017438.html
and http://mail.python.org/pipermail/distutils-sig/2011-March/017450.html .

> Carole maintains several namespace packages, each of which are
> independently developed and distributed.
I am not sure we should advertise setuptools namespace packages, given
that standardization is under way (PEP 382).  On one hand it would be
childish not to acknowledge that setuptools is widely used, on the other
hand in this particular time and place I think we should wait for
official namespace packages to be implemented and talk about those.
That said, even if the mechanism changes, the packaging-related parts
won’t, so the story is useful.  Make that +0 after all.

> at *sdist* tarball build time.
Do non-UNIX people understand “tarball”?  You could remove it or replace
it with “archive”.

> David maintains a package in the standard library, and also produces
> standalone versions for other versions of Python.
Thoughtful hat tip :)

> Often, version numbers
> can be retrieved from a module programmatically, by importing the
> module and inspecting an attribute.  Classic Python distutils
> ``setup()`` functions [3]_ describe a ``version`` argument where the
> package's version number can be specified.
See above for package vs. distribution terminology.

This makes me think: It is obvious to us that Python packages are a type
of Python modules, but the PEP could mention that near the beginning, to
make clear that your PEP is relevant to any kind of module, whatever its
physical incarnation.

> of an ``__version__`` module attribute by independent module
s/an/a/

> Another example of version information is the sqlite3 [5]_ library
the sqlite3 module

> This informational PEP codifies established practice, and recommends
> standard ways of describing module version numbers, along with some
> use cases for when -- and when *not* -- to include them.  Its adoption
> is purely voluntary, but other tools in the Python universe may
> support the standards defined herein.
You say “other tools“ without having referred to tools before, I find it
confusing (I’m not a native speaker, however).  The text could mention
here that official tools will have opt-in support for the PEP:

  Its adoption is purely voluntary; the packaging tools in the standard
  library will provide optional support for the standards defined herein
  (see section XX), and other tools in the Python universe may comply
  too.

> #. On a case-by-case basis, standard library modules which are also
>    distributed as standalone packages for other Python versions MAY
Problematic “packages” again.  What about this: “which are also released
in standalone form for other Python versions”?

> #. For modules which are also packages, the top level module namespace
>    SHOULD include the ``__version__`` attribute.
Just a remark: I don’t remember ever reading the term “top-level module
namespace”.  It’s not hard to understand, but it might be helpful to
some readers if you add “(i.e. the :file:`{somepackage}/__init__.py`
file)”.  (The brackets will cause the enclosed text to be marked up as
replaceable text, just a nicety.)

> #. For modules which live inside a namespace package, the sub-package
>    name SHOULD include the ``__version__`` attribute.
I think this works with both setuptools and PEP 382 namespace packages,
which is nice (see above questioning).

> The namespace module itself SHOULD NOT include its own
> ``__version__`` attribute.
I guess this makes sense for setuptools namespace packages, but from my
understanding of PEP 382, it is possible to have a Python package that
is a namespace package and has submodules.  (I hope Martin will correct
me if needed.)  This thing (“portion” in PEP 382 lingo) should be
allowed to declare a version IMO.

> #. The ``__version__`` attribute's value SHOULD be a simple string.
What’s a non-simple string?  This may be only me, but here I think you
tried to be simple and had the opposite effect.  I’d just use the simple
“a string” or the precise “a string (str object in 3.x)”.

> #. The ``version`` attribute in a classic distutils ``setup.py`` file,
>    or the ``Version`` metadata field in a PEP 345 [7]_ SHOULD be
>    derived from the ``__version__`` field, or vice versa.
“In a PEP 345” what? :) file, I guess.

I think this part should either take a position, that is choose one way
instead of vaguely telling about two ways, or be removed, given that the
section Deriving has the same info.

> They also need to be specified in either the classic distutils
> ``setup()`` function, as the ``version`` attribute in a ``setup.py``,
> or in the distutils2 ``setup.cfg`` file's ``version`` keyword,
I’d say the setup.py has a version argument and the setup.cfg has a
version key.

> they need to get into the PEP 345 package metadata, preferably at
> *sdist* package build-time.
s/package metadata/metadata/; s/*sdist* package/*sdist*/

> In the PEP author's experience however, this can fail in some cases,
> such as when the module uses automatic Python 3 conversion via the
> ``2to3`` program.
Just to make this 100% explicit, you could add “because the setup.py
script is executed by Python 3 before the elle module has been converted”.

> In that case, it's not much more difficult to write a little code
> to parse the ``__version__`` from the file rather than
The function could be simplified (use re.search, hard-code the re), but
that’s very minor.

> Because the distutils2 style ``setup.cfg`` is declarative, we can't
> run any code to extract the ``__version__`` attribute, either via
> import or via parsing.  This PEP suggests a special key be allowed for
> the ``version`` field in a ``setup.cfg`` file to indicate "get the
> version from this file".
With my distutils2 hat on, I recommend a KISS approach similar to what’s
done for the long description: just define another key in the setup.cfg
specification:

  [metadata]
  version-from-file: elle.py

> An alternative is to only define the version number in setup.cfg and
> use the ``pkgutil`` module [8]_ to make it available
> programmatically.  E.g. in ``elle.py``::
> 
>     from distutils2._backport import pkgutil
>     __version__ = pkgutil.get_distribution('elle').metadata['version']
One of the main complaint against setuptools is that having to change
your application code because of the packaging tool used was not a good
idea.  Having to use require instead of import or resource_whatever
instead of open (or get_data, the most sadly underused function in the
stdlib) because you use setuptools instead of distutils was a bad thing.

As stated in the PEP, having a __version__ attribute in the module is
common, so my opinion is that making the packaging tool use that info is
the Right Thing™, and having the dependency in the reverse sense is
wrong.  I don’t see a problem with having harmless duplication in the
*installed* system, once in  elle.__version__ and once in the pkgutil
metadata database.

(FWIW, I personally think that it’s not crazy to have the version number
duplicated in the module, setup script, changelog, Sphinx conf.py file
and so on; other people like Ronny don’t even want to have the version
number in one file, but make their build process use the VCS tag.  I
think this PEP addresses a useful middle ground.)

> Static egg info
Is that the distutils 2.5+ generated metadata?  You may want to read PEP
376 and update the terminology to “dist-info metadata” <0.2 wink>.

> For example, a package's metadata can be made available via a simple
> HTTP GET operation on a URL within the package's presence on the
> Cheeseshop.
First, insert usual remark about “package” here; second, I think
discussing PyPI is out of scope here.  The rationale that “the metadata
will be available for introspection even when the code is not installed“
is already strong enough.

> .. [1] Distutils2 documentation
>    (http://distutils2.notmyidea.org/)
Alexis, is this still the good link to use?

Regards


More information about the Distutils-SIG mailing list