Last active
May 12, 2016 17:38
-
-
Save benoitbryon/2815051 to your computer and use it in GitHub Desktop.
PEP 423: Naming conventions and recipes related to Python packaging
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PEP: 423 | |
Title: Naming conventions and recipes related to packaging | |
Version: $Revision$ | |
Last-Modified: $Date$ | |
Author: Benoît Bryon <benoit@marmelune.net> | |
Discussions-To: <distutils-sig@python.org> | |
Status: Deferred | |
Type: Informational | |
Content-Type: text/x-rst | |
Created: 24-May-2012 | |
Post-History: 5-Jul-2013 | |
Abstract | |
======== | |
This PEP provides conventions, guidelines and recipes on naming | |
things. It covers: | |
* names of Python projects; | |
* names of Python packages or modules being distributed; | |
* namespace packages. | |
**New projects** should follow the `guidelines <#overview>`_ below. | |
**Existing projects** should follow `specific recipes for existing | |
projects <#how-to-apply-naming-guidelines-on-existing-projects>`_. | |
PEP Deferral | |
============ | |
Further consideration of this PEP has been deferred at least until | |
after PEP 426 (package metadata 2.0) and related updates have been | |
resolved. | |
Terminology | |
=========== | |
Terminology reference for this PEP is `packaging terminology in Python | |
documentation`_. | |
Relationship with other PEPs | |
============================ | |
* `PEP 8`_ deals with code style guide, including names of Python | |
packages and modules. It covers syntax of package/modules names. | |
PEP 423 uses PEP 8 for naming packages and modules. It also explains | |
why and how PEP 8 should also apply to project names. | |
* `PEP 426`_ deals with packaging metadata, and defines name argument | |
of the ``packaging.core.setup()`` function. | |
PEP 423 shows how to use packaging metadata in order to solve some | |
naming issues. | |
* `PEP 420`_ deals with namespace packages. It brings support of | |
namespace packages to Python core. Before, namespaces packages were | |
implemented by external libraries. | |
PEP 423 provides guidelines about usage of namespace packages. | |
* `PEP 3108`_ deals with transition between Python 2.x and Python 3.x | |
applied to standard library: some modules to be deleted, some to be | |
renamed. It points out that naming conventions matter and is an | |
example of transition plan. | |
PEP 423 provides guidelines to apply naming conventions to | |
existing projects, including renaming projects. | |
Rationale: issues related to names | |
================================== | |
For a long time, there have been no official reference on the "how to | |
choose names" topic in the Python community. As a consequence, the | |
Python package index (`PyPI`_) contains many naming patterns. | |
The fact is that heterogeneity and lack of conventions cause issues. | |
This section will point out some issues. Then conventions and | |
recipes provided in this PEP will explain how to avoid or fix them. | |
.. note:: Examples were taken on July 2013. | |
Clashes | |
------- | |
Names of projects are unique on `PyPI`_. But names of distributed | |
things (packages, modules) are not. And there are clashes. | |
As an example, "pysendfile" and "django-sendfile" projects both | |
distribute a "sendfile" package. Users cannot use both in an | |
environment. | |
Unrelated namespaces | |
-------------------- | |
When project names are made of nested namespaces, and these | |
namespaces are not strongly related, then there is confusion. | |
As an example, some users ignore "zc.rst2" project, because | |
they think it is specific to "zc". It is not obvious that "zc.rst2" | |
is not specific to "zc" (Zope Corporation) ecosystem. It is | |
a general Python project, just related to docutils' reStructuredText. | |
This issue occurs with branded namespaces, i.e. when top-level | |
namespace is user or organization name and various projects are put | |
into this namespace. That is the case of "zc.rst2". | |
This issue also occurs when namespaces are used for categorization. | |
Inconsistent names | |
------------------ | |
When project and distributed packages do not share a single name, | |
users have to think about names. Typically when thet install project | |
or import package. | |
As an example, which package does "django-pipeline" project | |
distributes? Is it "djangopipeline", "django_pipeline" or "pipeline"? | |
The answer is not obvious and the pattern varies depending on | |
project. Users have to remember or search for the name to use. | |
There is no obvious bijection between project name and | |
package/module name. It means that a user have to remember or guess | |
two names (project and package) whereas one could be enough. | |
As an example, if you read ``import sendfile`` in some code, can you | |
guess the related project name? In this particular case, it could | |
refer to either "django-sendfile" or "pysendfile" projects, because | |
they both distribute "sendfile" package. | |
Inconsistent names lead to clashes. When you register a project name | |
on `PyPI`_, you have no idea about package name clashes, because | |
package names are not predictable. | |
Deep nested hierarchies | |
----------------------- | |
Deep nested namespaces mean deep nested hierarchies. It obfuscates | |
valuable project contents. | |
As an example, with "plone.app.content" you get a deeply nested | |
directory hierarchy: | |
.. code:: text | |
plone/ | |
└── app/ | |
└── command/ | |
└── ... valuable code is here... | |
Whereas, with flat packages like "sphinx", you have valuable | |
code near the top-level directory: | |
.. code:: text | |
sphinx/ | |
└── ... valuable code is here... | |
Overview | |
======== | |
Here is a summarized list of recommendations for you to choose names: | |
* `understand and respect namespace ownership | |
<#understand-and-respect-namespace-ownership>`_. | |
* if your project is related to another project or community, first | |
search for conventions in main project's documentation, then: | |
* `follow specific conventions of project or community | |
<#follow-community-or-related-project-conventions-if-any>`_, if | |
any. | |
* else (there is no specific convention), `follow a standard naming | |
pattern <#use-standard-pattern-for-community-contributions>`_. | |
* make sure names are unique, i.e. avoid duplicates: | |
* `check for name availability`_, | |
* `register names with PyPI`_. | |
Exception is when you explicitely want to distribute alternatives | |
to existing packages or modules. | |
* `Use a single name`_. It implies `a project distributes a single | |
package or module <#multiple-packages-modules-should-be-rare>`_ | |
* `distribute only one package or module at a time | |
<#multiple-packages-modules-should-be-rare>`_, unless you are in | |
a special case. | |
* make it easy to discover and remember your project: | |
* `pick memorable names`_, | |
* `pick meaningful names`_, | |
* `use packaging metadata`_. | |
* `avoid deep nesting`_: | |
* one single level is the recommended way to go. | |
* two levels can be used to point out strict relationships: the | |
second level is specific to the first one. Main use cases are | |
community contributions related to one project, and | |
vendor specific projects. | |
* you should not need more than two levels. Having more than three | |
levels is strongly discouraged. | |
* `follow PEP 8`_ for syntax of package and module names. | |
* if, for some reason, your project does not follow the | |
recommendations above, `document specific naming policy`_. | |
In particular, projects which are receiving community | |
contributions should `organize community contributions`_. | |
* `if still in doubt, ask <#if-in-doubt-ask>`_. | |
If in doubt, ask | |
================ | |
If you feel unsure after reading this document, ask `Python | |
community`_ on IRC or on a mailing list. | |
Understand and respect namespace ownership | |
========================================== | |
On `PyPI`_, all projects are put at index root. There is no owner or | |
user level. PyPI cannot host two projects with the exact same name, | |
even if owners are different. One name relies to one project, which | |
relies to one ownership. | |
.. note:: A project's ownership can be hold by several users. | |
The top-level namespace relates to ownership. | |
As an example, `Django`_ is owned and maintained by the Django | |
Software Fundation. | |
Understand the purpose of namespace before you use it. | |
Do not plug into a namespace you do not own, unless explicitely | |
authorized. `If in doubt, ask`_. | |
As an example, do not plug in "django.contrib" namespace because it | |
is managed by Django's core contributors. | |
Project owners may define exceptions. See `Organize community | |
contributions`_ below. | |
As an example, `flask`_ project explicitely invites contributors to | |
release projects in "flask.ext" namespace. | |
Also, whenever possible, try to consider non-Python projects. | |
As an example, you should not use "apache" as top-level namespace: | |
"Apache" is the name of another (non Python) project. This is more an | |
advice than a strict rule, but it could help identify your project on | |
the internet or prevent some trademark issues. | |
Private projects may use a namespace | |
------------------------------------ | |
For internal/customer projects, feel free to use the company or main | |
project name as the namespace. But keep in mind that, if a project is | |
general purpose (i.e. not specific to your company or to some main | |
project), then one level should be enough. | |
This rule applies to closed-source projects. | |
As an example, if you are creating a "climbing" project that is | |
specific to the "Python Sport" company: you may use | |
"pythonsport.climbing" name, even if it is closed source. | |
Use a single name | |
================= | |
Distribute only one package (or only one module) per project, and use | |
package (or module) name as project name. | |
.. tip:: | |
Think of a single name in ``pip install {package}`` and ``import {package}`` | |
* It avoids possible confusion between project name and distributed | |
package or module name. | |
* It makes the name consistent. | |
* It is explicit: when one sees project name, he guesses | |
package/module name, and vice versa. | |
* It also limits implicit clashes between package/module names. | |
By using a single name, when you register a project name to | |
`PyPI`_, you also perform a basic package/module name availability | |
verification. | |
As an example, `pipeline`_, `python-pipeline`_ and | |
`django-pipeline`_ all distribute a package or module called | |
"pipeline". So installing two of them leads to errors. This issue | |
wouldn't have occurred if these distributions used a single name. | |
* As a bonus, it allows easier setup of the project: you provide the | |
name of the package/module you want to distribute, and you get | |
other names. | |
Example: | |
* Yes: Package name is "kheops" and project name is "kheops". | |
* Yes: Package name is "kheops.history", i.e. | |
``import kheops.history`` and project name is "kheops.history", | |
i.e. ``pip install kheops.history``. | |
* No: Package name is "kheops" and project name is "KheopsPyramid". | |
.. note:: | |
For historical reasons, `PyPI`_ contains many distributions where | |
project and distributed package/module names differ. | |
Multiple packages/modules should be rare | |
---------------------------------------- | |
Technically, Python distributions can provide multiple packages | |
and/or modules. See `setup script reference`_ for details. | |
Some distributions actually do. | |
As an example, `setuptools`_ and `distribute`_ both declare | |
"pkg_resources", "easy_install" and "site" modules in addition to | |
respective "setuptools" and "distribute" packages. | |
Consider this use case as exceptional. In most cases, you do not need | |
this feature and distributing a single package or module is enough. | |
Distinct names should be rare | |
----------------------------- | |
A notable exception to the `Use a single name`_ rule is when you | |
explicitely need distinct names. | |
As an example, the `Pillow`_ project provides an alternative to the | |
original `PIL`_ distribution. Both projects distribute a "PIL" | |
package. | |
Consider this use case as exceptional. In most cases, you don't need | |
this feature and naming the project after the distributed | |
package/module is enough. | |
Follow PEP 8 | |
============ | |
`PEP 8`_ applies to names of Python packages and modules. | |
If you `Use a single name`_, `PEP 8`_ also applies to project names. | |
The exceptions are namespace packages, where dots are required in | |
project name. | |
Notice that the use of hyphens in project names breaks `Use a single | |
name`_ rule. | |
Also, notice that the use of underscores is discouraged. | |
Pick memorable names | |
==================== | |
One important thing about a project name is that it be memorable. | |
As an example, `celery`_ is not a meaningful name. At first, it is | |
not obvious that it deals with message queuing. But it is memorable | |
because it can be used to feed a `RabbitMQ`_ server. | |
Pick meaningful names | |
===================== | |
Ask yourself "how would I describe in one sentence what this name is | |
for?", and then "could anyone have guessed that by looking at the | |
name?". | |
As an example, `DateUtils`_ is a meaningful name. It is obvious that | |
it deals with utilities for dates. | |
When you are using namespaces, try to make each part meaningful. | |
.. note:: | |
Sometimes, you cannot find a name that is both memorable and | |
meaningful. In such a situation, consider "memorable" feature is | |
more important than "meaningful" one. Generally, by choosing a | |
memorable name, you tend to make the name unique, and simplicity | |
is a key of success. Whereas a meaningful name tend to be | |
similar to names of other projects that deal with same concepts, | |
and you tend make the name out of keywords/buzzwords. | |
Use packaging metadata | |
====================== | |
Consider that **project names are unique identifiers on PyPI**, i.e. | |
their primary purpose is to identify, not to classify or describe. | |
**Classifiers and keywords metadata are made for categorization.** | |
Summary and description metadata are meant to describe the project. | |
As an example, there is a "`Framework :: Twisted`_" classifier. Names | |
of projects that have this classifier are quite heterogeneous. They | |
do not follow a particular pattern to claim relation with Twisted. | |
But we get the list using the classifier and that is fine. | |
In order to `Organize community contributions`_, conventions about | |
names and namespaces matter, but conventions about metadata are | |
important too. | |
As an example, we can find Plone portlets in many places: | |
* plone.portlet.* | |
* collective.portlet.* | |
* collective.portlets.* | |
* collective.*.portlets | |
* some vendor-related projects such as "quintagroup.portlet.cumulus" | |
* and even projects where "portlet" pattern doesn't appear in the | |
name. | |
Even if Plone community has conventions, using the name to categorize | |
distributions is inapropriate. It's impossible to get the full list | |
of distributions that provide portlets for Plone by filtering on | |
names. But it would be possible if all these distributions used | |
"Framework :: Plone" classifier and "portlet" keyword. | |
When you release a project on `PyPI`_, you obviously want your | |
project to be visible, and findable. Keep in mind that the name is | |
not the only way to make a project discoverable. If you do care | |
about your project's visibility, take care of package metadata: | |
keywords, classifiers, README... And you may also take care of | |
project's documentation and some stuff not related to packaging, | |
but this is outside the scope of this PEP. | |
Avoid deep nesting | |
================== | |
`The Zen of Python`_ says: | |
Flat is better than nested. | |
A single level is recommended | |
----------------------------- | |
In most cases, one level is enough. So, unless you are in a special | |
situation mentioned below, your project name should be made of a | |
single namespace. | |
Lower levels indicate strict relationship to upper levels | |
--------------------------------------------------------- | |
In nested namespaces, lower levels point out strict relationship to | |
higher ones. It means the second level is specific to the first one. | |
Main use cases are community contributions related to one project | |
and vendor specific (mostly private) projects. | |
Two levels is almost always enough | |
---------------------------------- | |
Do not define everything in deeply nested hierarchies: you will end | |
up with projects and packages like "pythonsport.common.maps.forest". | |
This type of name is both verbose and cumbersome (e.g. if you have | |
many imports from the package). | |
Furthermore, big hierarchies tend to break down over time as the | |
boundaries between different packages blur. | |
The consensus is that two levels of nesting are preferred. | |
For example, we have ``plone.principalsource`` instead of | |
``plone.source.principal`` or something like that. The name is | |
shorter, the package structure is simpler, and there would be very | |
little to gain from having three levels of nesting here. It would be | |
impractical to try to put all "core Plone" sources (a source is kind | |
of vocabulary) into the ``plone.source.*`` namespace, in part because | |
some sources are part of other packages, and in part because sources | |
already exist in other places. Had we made a new namespace, it would | |
be inconsistently used from the start. | |
Yes: "pythonsport.climbing" | |
Yes: "pythonsport.forestmap" | |
No: "pythonsport.maps.forest" | |
Do not use namespace levels for categorization | |
---------------------------------------------- | |
`Use packaging metadata`_ instead. | |
Don't use more than 3 levels | |
---------------------------- | |
Technically, you have the ability to create deeply nested | |
hierarchies. However, it is strongly discouraged. | |
Document specific naming policy | |
=============================== | |
A project that does not follow this PEP's recommendations should | |
mention and explain it in documentation. | |
This rule is the simplest way to make an existing project comply with | |
this PEP, without a rename. | |
Follow community or related project conventions, if any | |
======================================================= | |
Projects or related communities can have specific naming conventions, | |
which may differ from those explained in this document. Specific | |
conventions override this PEP. | |
This rule exists for backward-compatibility purpose: new projects | |
should follow this PEP's conventions. | |
In such a case, `they should declare specific conventions in | |
documentation <#organize-community-contributions>`_. | |
So, if your project belongs to another project or to a community, | |
first look for specific conventions in main project's documentation. | |
If there is no specific conventions, follow the ones declared in this | |
document. | |
As an example, `Plone community`_ releases community contributions in | |
the "collective" namespace package. It differs from the `standard | |
namespace for contributions | |
<#use-standard-pattern-for-community-contributions>`_ proposed here. | |
But since it is documented, there is no ambiguity and you should | |
follow this specific convention. | |
Use standard pattern for community contributions | |
================================================ | |
When no specific rule is defined, use the | |
``{MAINPROJECT}contrib.{PROJECT}`` pattern to store community | |
contributions for any product or framework, where: | |
* ``{MAINPROJECT}`` is the name of the related project. "pyranha" in | |
the example below. | |
* ``{PROJECT}`` is the name of your project. "giantteeth" in the | |
example below. | |
As an example: | |
* you are the author of "pyranha" project. | |
* you didn't defined specific naming conventions for community | |
contributions. | |
* a third-party developer wants to publish a "giantteeth" project | |
related to your "pyranha" project in a community namespace. So he | |
should publish it as "pyranhacontrib.giantteeth". | |
It is the simplest way to `Organize community contributions`_. | |
.. note:: | |
Why ``{MAINPROJECT}contrib.*`` pattern? | |
* ``{MAINPROJECT}c.*`` is not explicit enough. As examples, "zc" | |
belongs to "Zope Corporation" whereas "z3c" belongs to "Zope 3 | |
community". | |
* ``{MAINPROJECT}community`` is too long. | |
* ``{MAINPROJECT}community`` conflicts with existing namespaces | |
such as "iccommunity" or "PyCommunity". | |
* ``{MAINPROJECT}.contrib.*`` is inside {MAINPROJECT} namespace, | |
i.e. it is owned by ${MAINPROJECT} authors. | |
* ``{MAINPROJECT}.contrib.*`` breaks the `Avoid deep nesting`_ | |
rule. | |
* names where ``{MAINPROJECT}`` does not appear are not explicit | |
enough, i.e. nobody can guess they are related to | |
``{MAINPROJECT}``. As an example, it is not obvious that | |
"collective.*" belongs to Plone community. | |
* ``{DIST}contrib.*`` looks like existing ``sphinxcontrib-*`` | |
packages. But ``sphinxcontrib-*`` is actually about Sphinx | |
contrib, so this is not a real conflict... In fact, the | |
"contrib" suffix was inspired by "sphinxcontrib". | |
Organize community contributions | |
================================ | |
This is the counterpart of the `follow community conventions | |
<#follow-community-or-related-project-conventions-if-any>`_ and | |
`standard pattern for contributions | |
<#use-standard-pattern-for-community-contributions>`_ rules. | |
Actions: | |
* Choose a naming convention for community contributions. | |
* If it is not `the default | |
<#use-standard-pattern-for-community-contributions>`_, then | |
document it. | |
* if you use the `default convention | |
<#use-standard-pattern-for-community-contributions>`_, then this | |
document should be enough. Do not reapeat it. You may reference | |
it. | |
* else, tell users about custom conventions in project's | |
"contribute" or "create modules" documentation. | |
* Also recommend the use of additional metadata, such as | |
`classifiers and keywords <#use-packaging-metadata>`_. | |
Example: "pyranha" is your project name and package name. | |
You could tell contributors that: | |
* pyranha-related distributions should use the "pyranha" keyword | |
* pyranha-related distributions providing templates should also use | |
"templates" keyword. | |
* community contributions should be released under "pyranhacontrib" | |
namespace (i.e. use "pyranhacontrib.*" pattern). | |
Register names with PyPI | |
======================== | |
`PyPI`_ is the central place for distributions in Python community. | |
So, it is also the place where to register project and package names. | |
See `Registering with the Package Index`_ for details. | |
Check for name availability | |
=========================== | |
Make sure it project name has not already been registered on `PyPI`_. | |
.. note:: | |
`PyPI`_ is the only official place where to register names. | |
Also make sure the names of distributed packages or modules have not | |
already been registered: | |
* in the `Python Standard Library`_. | |
* inside projects at `PyPI`_. | |
.. note:: | |
The `use a single name`_ rule helps you avoid clashes with package | |
names: if a project name is available, then the package name has | |
good chances to be available too. | |
How to rename a project? | |
======================== | |
Renaming a project is possible, but it should be done with care. | |
Pay particular attention to README and documentation, so that users | |
understand what happened. | |
#. First of all, **do not remove legacy distributions from PyPI**. | |
Because some users may be using them. | |
#. Copy the legacy project, then change names (project and | |
package/module). Pay attention to, at least: | |
* packaging files, | |
* folder name that contains source files, | |
* documentation, including README, | |
* import statements in code. | |
#. Release a new version of the renamed project, then publish it. | |
#. Edit legacy project: | |
* assign ``obsoleted_by`` metadata to new distribution in setup.cfg | |
file. See `PEP 426 about obsoleted_by`_ and `setup.cfg | |
specification`_. | |
* add dependency to new project, | |
* drop everything except packaging stuff, | |
* add the ``Development Status :: 7 - Inactive`` classifier in | |
setup script, | |
* publish a new release. | |
So, users of the legacy package: | |
* can continue using the legacy distributions at a deprecated | |
version, | |
* can upgrade to last version of legacy distribution, which is | |
empty... | |
* ... and automatically download new distribution as a dependency of | |
the legacy one. | |
Users who discover the legacy project see it is inactive. | |
How to apply naming guidelines on existing projects? | |
==================================================== | |
**There is no obligation for existing projects to be renamed**. The | |
choice is left to project authors and maintainers, for obvious | |
reasons. | |
However, project authors are invited to: | |
* at least, state about current naming, if necessary: | |
* explain the reason why the project has this name in documentation, | |
* `document specific naming policy`_. | |
* optionally, `rename existing project or distributed | |
packages/modules <#how-to-rename-a-project>`_. | |
Projects that are meant to receive contributions from community | |
should also `organize community contributions`_. | |
References | |
========== | |
Additional background: | |
* `Martin Aspeli's article about names`_. Some parts of this document | |
are quotes from this article. | |
* `in development official packaging documentation`_. | |
* `The Hitchhiker's Guide to Packaging`_, which has an empty | |
placeholder for "naming specification". | |
References and footnotes: | |
.. _`packaging terminology in Python documentation`: | |
http://docs.python.org/dev/packaging/introduction.html#general-python-terminology | |
.. _`PEP 8`: | |
http://www.python.org/dev/peps/pep-0008/#package-and-module-names | |
.. _`PEP 426`: http://www.python.org/dev/peps/pep-0426/ | |
.. _`PEP 420`: http://www.python.org/dev/peps/pep-0420/ | |
.. _`PEP 3108`: http://www.python.org/dev/peps/pep-3108/ | |
.. _`Python community`: http://www.python.org/community/ | |
.. _`gp.fileupload`: http://pypi.python.org/pypi/gp.fileupload/ | |
.. _`zest.releaser`: http://pypi.python.org/pypi/zest.releaser/ | |
.. _`django`: http://djangoproject.com/ | |
.. _`flask`: http://flask.pocoo.org/ | |
.. _`sphinx`: http://sphinx.pocoo.org | |
.. _`pypi`: http://pypi.python.org | |
.. _`collective.recaptcha`: | |
http://pypi.python.org/pypi/collective.recaptcha/ | |
.. _`pipeline`: http://pypi.python.org/pypi/pipeline/ | |
.. _`python-pipeline`: http://pypi.python.org/pypi/python-pipeline/ | |
.. _`django-pipeline`: http://pypi.python.org/pypi/django-pipeline/ | |
.. _`setup script reference`: | |
http://docs.python.org/dev/packaging/setupscript.html | |
.. _`setuptools`: http://pypi.python.org/pypi/setuptools | |
.. _`distribute`: http://packages.python.org/distribute/ | |
.. _`Pillow`: http://pypi.python.org/pypi/Pillow/ | |
.. _`PIL`: http://pypi.python.org/pypi/PIL/ | |
.. _`celery`: http://pypi.python.org/pypi/celery/ | |
.. _`RabbitMQ`: http://www.rabbitmq.com | |
.. _`DateUtils`: http://pypi.python.org/pypi/DateUtils/ | |
.. _`Framework :: Twisted`: | |
http://pypi.python.org/pypi?:action=browse&show=all&c=525 | |
.. _`The Zen of Python`: http://www.python.org/dev/peps/pep-0020/ | |
.. _`Plone community`: http://plone.org/community/develop | |
.. _`Registering with the Package Index`: | |
http://docs.python.org/dev/packaging/packageindex.html | |
.. _`Python Standard Library`: | |
http://docs.python.org/library/index.html | |
.. _`PEP 426 about obsoleted_by`: | |
http://www.python.org/dev/peps/pep-0426/#obsoleted-by | |
.. _`setup.cfg specification`: | |
http://docs.python.org/dev/packaging/setupcfg.html | |
.. _`Martin Aspeli's article about names`: | |
http://www.martinaspeli.net/articles/the-naming-of-things-package-names-and-namespaces | |
.. _`in development official packaging documentation`: | |
http://docs.python.org/dev/packaging/ | |
.. _`The Hitchhiker's Guide to Packaging`: | |
http://guide.python-distribute.org/specification.html#naming-specification | |
Copyright | |
========= | |
This document has been placed in the public domain. | |
.. | |
Local Variables: | |
mode: indented-text | |
indent-tabs-mode: nil | |
sentence-end-double-space: t | |
fill-column: 70 | |
coding: utf-8 | |
End: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Original document is here: https://bitbucket.org/benoitbryon/cpython/raw/b2ff5053ba90/Doc/packaging/packagenames.rst