[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