aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES.rst6
-rw-r--r--docs/setuptools.txt18
-rw-r--r--setuptools/dist.py10
-rw-r--r--setuptools/tests/test_dist.py17
4 files changed, 44 insertions, 7 deletions
diff --git a/CHANGES.rst b/CHANGES.rst
index 8c214db3..9d8e2e29 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -178,6 +178,12 @@ v28.7.0
of data files, re-aligning with the expectation of distutils
and addressing #274 and #521.
+v28.7.1
+-------
+
+* #97: Declaring a namespace package implicitly also
+ declares the package.
+
v28.6.1
-------
diff --git a/docs/setuptools.txt b/docs/setuptools.txt
index 2a494fca..10bf7dc4 100644
--- a/docs/setuptools.txt
+++ b/docs/setuptools.txt
@@ -1352,9 +1352,12 @@ Namespace Packages
------------------
Sometimes, a large package is more useful if distributed as a collection of
-smaller eggs. However, Python does not normally allow the contents of a
-package to be retrieved from more than one location. "Namespace packages"
-are a solution for this problem. When you declare a package to be a namespace
+smaller packages. Traditionally, Python did not allow the contents of a
+package to be retrieved from more than one location. "Namespace packages"
+are a solution for this problem, and this feature is provided by
+``pkg_resources`` for Python 3.2 and earlier and natively
+supported by Python 3.3 and later per PEP 420.
+When you declare a package to be a namespace
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.
@@ -1369,7 +1372,7 @@ participates in. For example, the ZopeInterface project might do this::
setup(
# ...
- namespace_packages=['zope']
+ namespace_packages=['zope'],
)
because it contains a ``zope.interface`` package that lives in the ``zope``
@@ -1379,8 +1382,7 @@ 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
-``peak.util`` package will be too.
+``zope.app`` package is a namespace package.
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
@@ -1405,6 +1407,10 @@ 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!
+Packages that only support Python 3.3 and later may omit the ``__init__.py``
+altogether, but the namespace package must still be declared during
+``setup()``.
+
TRANSITIONAL NOTE
~~~~~~~~~~~~~~~~~
diff --git a/setuptools/dist.py b/setuptools/dist.py
index 159464be..60cf6d9d 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -106,9 +106,17 @@ def assert_string_list(dist, attr, value):
def check_nsp(dist, attr, value):
- """Verify that namespace packages are valid"""
+ """
+ Verify that namespace packages are valid and ensure that any
+ namespace packages imply a package.
+ """
ns_packages = value
assert_string_list(dist, attr, ns_packages)
+ dist.packages = dist.packages or []
+ dist.packages.extend(
+ package for package in ns_packages
+ if package not in dist.packages
+ )
for nsp in ns_packages:
if not dist.has_contents_for(nsp):
raise DistutilsSetupError(
diff --git a/setuptools/tests/test_dist.py b/setuptools/tests/test_dist.py
new file mode 100644
index 00000000..aedd2de4
--- /dev/null
+++ b/setuptools/tests/test_dist.py
@@ -0,0 +1,17 @@
+
+
+from setuptools import dist as dist_mod
+
+
+class TestCheckNSP:
+ def test_namespace_package_implies_package(self):
+ """
+ When a namespace package is declared, that declaration
+ implies the package of the same name, so it should
+ ensure that the name appears in the list of packages.
+ """
+ attrs = dict(namespace_packages=['foo'])
+ dist_ob = dist_mod.Distribution(attrs)
+ for attr, value in attrs.items():
+ dist_mod.check_nsp(dist_ob, attr, value)
+ assert 'foo' in dist_ob.packages