[Python-checkins] commit of r41479 - in sandbox/trunk/setuptools: . setuptools/command
phillip.eby@python.org
phillip.eby at python.org
Fri Nov 18 18:29:47 CET 2005
Author: phillip.eby
Date: Fri Nov 18 18:29:47 2005
New Revision: 41479
Modified:
sandbox/trunk/setuptools/setuptools.txt
sandbox/trunk/setuptools/setuptools/command/build_py.py
Log:
Added warning for namespace packages with missing ``declare_namespace()``,
updated docs for new policy/implementation, and explain the reasons
for the change and what to do about it.
Modified: sandbox/trunk/setuptools/setuptools.txt
==============================================================================
--- sandbox/trunk/setuptools/setuptools.txt (original)
+++ sandbox/trunk/setuptools/setuptools.txt Fri Nov 18 18:29:47 2005
@@ -1046,17 +1046,14 @@
package, it means that the package has no meaningful contents in its
``__init__.py``, and that it is merely a container for modules and subpackages.
-The ``pkg_resources`` runtime will automatically ensure that the contents of
-namespace packages that are spread over multiple eggs or directories are
-combined into a single virtual package.
+The ``pkg_resources`` runtime will then automatically ensure that the contents
+of namespace packages that are spread over multiple eggs or directories are
+combined into a single "virtual" package.
The ``namespace_packages`` argument to ``setup()`` lets you declare your
project's namespace packages, so that they will be included in your project's
-metadata. Then, the runtime will automatically detect this when it adds the
-distribution to ``sys.path``, and ensure that the packages are properly merged.
-
-The argument should list the namespace packages that the egg participates in.
-For example, the ZopeInterface project might do this::
+metadata. The argument should list the namespace packages that the egg
+participates in. For example, the ZopeInterface project might do this::
setup(
# ...
@@ -1065,7 +1062,9 @@
because it contains a ``zope.interface`` package that lives in the ``zope``
namespace package. Similarly, a project for a standalone ``zope.publisher``
-would also declare the ``zope`` namespace package.
+would also declare the ``zope`` namespace package. When these projects are
+installed and used, Python will see them both as part of a "virtual" ``zope``
+package, even though they will be installed in different locations.
Namespace packages don't have to be top-level packages. For example, Zope 3's
``zope.app`` package is a namespace package, and in the future PEAK's
@@ -1074,22 +1073,50 @@
Note, by the way, that your project's source tree must include the namespace
packages' ``__init__.py`` files (and the ``__init__.py`` of any parent
packages), in a normal Python package layout. These ``__init__.py`` files
-should not contain any code or data, because only *one* egg's ``__init__.py``
-files will be used to construct the parent packages in memory at runtime, and
-there is no guarantee which egg will be used.
-
-For example, if both ``zope.interface`` and ``zope.publisher`` have been
-installed from separate distributions, it is unspecified which of the two
-distributions' ``zope/__init__.py`` files will be used to create the ``zope``
-package in memory. Therefore, it is better not to have any code or data in
-a namespace package's ``__init__`` module, so as to prevent any complications.
-
-(This is one reason the concept is called a "namespace package": it is a
-package that exists *only* to provide a namespace under which other modules or
-packages are gathered. In Java, for example, namespace packages are often used
-just to avoid naming collisions between different projects, using package names
-like ``org.apache`` as a namespace for packages that are part of apache.org
-projects.)
+*must* contain the line::
+
+ __import__('pkg_resources').declare_namespace(__name__)
+
+This code ensures that the namespace package machinery is operating and that
+the current package is registered as a namespace package.
+
+You can include other code and data in a namespace package's ``__init__.py``,
+but it's generally not a great idea because the loading order of each
+project's namespace packages is not guaranteed, and thus the actual contents
+of the parent package at runtime may vary from one machine to another. While
+it's true that you won't have such conflicts if only one project defines the
+contents of a particular namespace package's ``__init__.py``, it's less error-
+prone to just leave ``__init__.py`` empty except for the declaration line.
+
+(Note that this non-deterministic ordering also means that you must include
+the declaration line in the ``__init__.py`` of *every* project that has
+contents for the namespace package in question, in order to ensure that the
+namespace will be declared regardless of which project's copy of
+``__init__.py`` is loaded first. If the first loaded ``__init__.py`` doesn't
+declare it, it will never *be* declared, because no other copies will ever be
+loaded!)
+
+
+TRANSITIONAL NOTE
+~~~~~~~~~~~~~~~~~
+
+Setuptools 0.6a automatically calls ``declare_namespace()`` for you at runtime,
+but the 0.7a versions will *not*. This is because the automatic declaration
+feature has some negative side effects, such as needing to import all namespace
+packages during the initialization of the ``pkg_resources`` runtime, and also
+the need for ``pkg_resources`` to be explicitly imported before any namespace
+packages work at all. Beginning with the 0.7a releases, you'll be responsible
+for including your own declaration lines, and the automatic declaration feature
+will be dropped to get rid of the negative side effects.
+
+During the remainder of the 0.6 development cycle, therefore, setuptools will
+warn you about missing ``declare_namespace()`` calls in your ``__init__.py``
+files, and you should correct these as soon as possible before setuptools 0.7a1
+is released. Namespace packages without declaration lines will not work
+correctly once a user has upgraded to setuptools 0.7a1, so it's important that
+you make this change now in order to avoid having your code break in the field.
+Our apologies for the inconvenience, and thank you for your patience.
+
Tagging and "Daily Build" or "Snapshot" Releases
@@ -2128,6 +2155,8 @@
* Fixed ``--tag-svn-revision`` not working when run from a source
distribution.
+ * Added warning for namespace packages with missing ``declare_namespace()``
+
0.6a8
* Fixed some problems building extensions when Pyrex was installed, especially
with Python 2.4 and/or packages using SWIG.
Modified: sandbox/trunk/setuptools/setuptools/command/build_py.py
==============================================================================
--- sandbox/trunk/setuptools/setuptools/command/build_py.py (original)
+++ sandbox/trunk/setuptools/setuptools/command/build_py.py Fri Nov 18 18:29:47 2005
@@ -121,3 +121,44 @@
+ def check_package(self, package, package_dir):
+ """Check namespace packages' __init__ for declare_namespace"""
+ try:
+ return self.packages_checked[package]
+ except KeyError:
+ pass
+
+ init_py = _build_py.check_package(self, package, package_dir)
+ self.packages_checked[package] = init_py
+
+ if not init_py or not self.distribution.namespace_packages:
+ return init_py
+
+ for pkg in self.distribution.namespace_packages:
+ if pkg==package or pkg.startswith(package+'.'):
+ break
+ else:
+ return init_py
+
+ f = open(init_py,'rU')
+ if 'declare_namespace' not in f.read():
+ from distutils import log
+ log.warn(
+ "WARNING: %s is a namespace package, but its __init__.py does\n"
+ "not declare_namespace(); setuptools 0.7 will REQUIRE this!\n"
+ '(See the setuptools manual under "Namespace Packages" for '
+ "details.)\n", package
+ )
+ f.close()
+ return init_py
+
+ def initialize_options(self):
+ self.packages_checked={}
+ _build_py.initialize_options(self)
+
+
+
+
+
+
+
More information about the Python-checkins
mailing list