2012-06-26 13:25:12 -04:00
|
|
|
|
PEP: 423
|
|
|
|
|
Title: Naming conventions and recipes related to packaging
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
|
|
|
|
Author: Benoit Bryon <benoit@marmelune.net>
|
2012-06-27 12:09:25 -04:00
|
|
|
|
Discussions-To: <distutils-sig@python.org>
|
2013-05-18 03:50:40 -04:00
|
|
|
|
Status: Deferred
|
2012-06-26 13:25:12 -04:00
|
|
|
|
Type: Informational
|
|
|
|
|
Content-Type: text/x-rst
|
|
|
|
|
Created: 24-May-2012
|
2017-03-24 17:11:33 -04:00
|
|
|
|
Post-History:
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
This document deals with:
|
|
|
|
|
|
|
|
|
|
* names of Python projects,
|
|
|
|
|
* names of Python packages or modules being distributed,
|
|
|
|
|
* namespace packages.
|
|
|
|
|
|
|
|
|
|
It provides guidelines and recipes for distribution authors:
|
|
|
|
|
|
|
|
|
|
* new projects should follow the `guidelines <#overview>`_ below.
|
|
|
|
|
|
|
|
|
|
* existing projects should be aware of these guidelines and can follow
|
|
|
|
|
`specific recipes for existing projects
|
|
|
|
|
<#how-to-apply-naming-guidelines-on-existing-projects>`_.
|
|
|
|
|
|
2013-05-18 03:50:40 -04:00
|
|
|
|
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.
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
Terminology
|
|
|
|
|
===========
|
|
|
|
|
|
|
|
|
|
Reference 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 345`_ deals with packaging metadata, and defines name argument
|
|
|
|
|
of the ``packaging.core.setup()`` function.
|
|
|
|
|
|
|
|
|
|
* `PEP 420`_ deals with namespace packages. It brings support of
|
|
|
|
|
namespace packages to Python core. Before, namespaces packages were
|
|
|
|
|
implemented by external libraries.
|
|
|
|
|
|
|
|
|
|
* `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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Overview
|
|
|
|
|
========
|
|
|
|
|
|
|
|
|
|
Here is a summarized list of guidelines you should follow to choose
|
|
|
|
|
names:
|
|
|
|
|
|
|
|
|
|
* `understand and respect namespace ownership <#respect-ownership>`_.
|
|
|
|
|
|
|
|
|
|
* if your project is related to another project or community:
|
|
|
|
|
|
|
|
|
|
* search for conventions in main project's documentation, because
|
|
|
|
|
`projects should organize community contributions
|
|
|
|
|
<#organize-community-contributions>`_.
|
|
|
|
|
|
|
|
|
|
* `follow specific project or related community conventions
|
|
|
|
|
<#follow-community-or-related-project-conventions-if-any>`_, if any.
|
|
|
|
|
|
|
|
|
|
* if there is no convention, `follow a standard naming pattern
|
|
|
|
|
<#use-standard-pattern-for-community-contributions>`_.
|
|
|
|
|
|
|
|
|
|
* make sure your project name is unique, i.e. avoid duplicates:
|
|
|
|
|
|
|
|
|
|
* `use top-level namespace for ownership
|
|
|
|
|
<#top-level-namespace-relates-to-code-ownership>`_,
|
|
|
|
|
* `check for name availability
|
|
|
|
|
<#how-to-check-for-name-availability>`_,
|
|
|
|
|
* `register names with PyPI`_.
|
|
|
|
|
|
|
|
|
|
* make sure distributed packages and modules names are unique, unless
|
2016-07-14 10:16:06 -04:00
|
|
|
|
you explicitly want to distribute alternatives to existing packages
|
2012-06-26 13:25:12 -04:00
|
|
|
|
or modules. `Using the same value for package/module name and
|
|
|
|
|
project name <#use-a-single-name>`_ is the recommended way to
|
|
|
|
|
achieve this.
|
|
|
|
|
|
|
|
|
|
* `distribute only one package or module at a time
|
|
|
|
|
<#multiple-packages-modules-should-be-rare>`_, unless you know what
|
|
|
|
|
you are doing. It makes it possible to apply the "`use a single
|
|
|
|
|
name`_" rule, and thus make names consistent.
|
|
|
|
|
|
|
|
|
|
* make it easy to discover and remember your project:
|
2017-03-24 17:11:33 -04:00
|
|
|
|
|
2012-06-26 13:25:12 -04:00
|
|
|
|
* `use as much memorable names as possible
|
|
|
|
|
<#pick-memorable-names>`_,
|
|
|
|
|
* `use as much meaningful names as possible
|
|
|
|
|
<#pick-meaningful-names>`_,
|
|
|
|
|
* `use other packaging metadata <#use-packaging-metadata>`_.
|
|
|
|
|
|
|
|
|
|
* `avoid deep nesting`_. Flat things are easier to use and remember
|
|
|
|
|
than nested ones:
|
2017-03-24 17:11:33 -04:00
|
|
|
|
|
2012-06-26 13:25:12 -04:00
|
|
|
|
* one or two namespace levels are recommended, because they are
|
|
|
|
|
almost always enough.
|
|
|
|
|
* even if not recommended, three levels are, de facto, a common
|
|
|
|
|
case.
|
|
|
|
|
* in most cases, you should not need more than three levels.
|
|
|
|
|
|
|
|
|
|
* `follow PEP 8
|
|
|
|
|
<#follow-pep-8-for-syntax-of-package-and-module-names>`_ for syntax
|
|
|
|
|
of package and module names.
|
|
|
|
|
|
|
|
|
|
* if you followed specific conventions, or if your project is intended
|
|
|
|
|
to receive contributions from the community, `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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Top-level namespace relates to code ownership
|
|
|
|
|
=============================================
|
|
|
|
|
|
|
|
|
|
This helps avoid clashes between project names.
|
|
|
|
|
|
|
|
|
|
Ownership could be:
|
|
|
|
|
|
|
|
|
|
* an individual.
|
|
|
|
|
Example: `gp.fileupload`_ is owned and maintained by Gael
|
|
|
|
|
Pasgrimaud.
|
|
|
|
|
|
|
|
|
|
* an organization.
|
|
|
|
|
Examples:
|
2017-03-24 17:11:33 -04:00
|
|
|
|
|
2012-06-26 13:25:12 -04:00
|
|
|
|
* `zest.releaser`_ is owned and maintained by Zest Software.
|
|
|
|
|
* `Django`_ is owned and maintained by the Django Software
|
2019-07-03 14:20:45 -04:00
|
|
|
|
Foundation.
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
* a group or community.
|
|
|
|
|
Example: `sphinx`_ is maintained by developers of the Sphinx
|
|
|
|
|
project, not only by its author, Georg Brandl.
|
|
|
|
|
|
|
|
|
|
* a group or community related to another package.
|
|
|
|
|
Example: `collective.recaptcha`_ is owned by its author: David
|
|
|
|
|
Glick, Groundwire. But the "collective" namespace is owned by Plone
|
|
|
|
|
community.
|
|
|
|
|
|
|
|
|
|
Respect ownership
|
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
|
|
Understand the purpose of namespace before you use it.
|
|
|
|
|
|
2016-07-14 10:16:06 -04:00
|
|
|
|
Don't plug into a namespace you don't own, unless explicitly
|
2012-06-26 13:25:12 -04:00
|
|
|
|
authorized.
|
|
|
|
|
|
|
|
|
|
`If in doubt, ask`_.
|
|
|
|
|
|
|
|
|
|
As an example, don't plug in "django.contrib" namespace because it is
|
|
|
|
|
managed by Django's core contributors.
|
|
|
|
|
|
|
|
|
|
Exceptions can be defined by project authors. See `Organize community
|
|
|
|
|
contributions`_ below.
|
|
|
|
|
|
|
|
|
|
Also, this rule applies to non-Python projects.
|
|
|
|
|
|
|
|
|
|
As an example, don't use "apache" as top-level namespace: "Apache" is
|
|
|
|
|
the name of an existing project (in the case of "Apache", it is also a
|
|
|
|
|
trademark).
|
|
|
|
|
|
|
|
|
|
Private (including closed-source) projects use a namespace
|
|
|
|
|
----------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
... because private projects are owned by somebody. So apply the
|
|
|
|
|
`ownership rule <#top-level-namespace-relates-to-code-ownership>`_.
|
|
|
|
|
|
|
|
|
|
For internal/customer projects, use your company name as the
|
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
|
|
This rule applies to closed-source projects.
|
|
|
|
|
|
|
|
|
|
As an example, if you are creating a "climbing" project for the
|
|
|
|
|
"Python Sport" company: use "pythonsport.climbing" name, even if it is
|
|
|
|
|
closed source.
|
|
|
|
|
|
|
|
|
|
Individual projects use a namespace
|
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
|
|
... because they are owned by individuals. So apply the
|
|
|
|
|
`ownership rule <#top-level-namespace-relates-to-code-ownership>`_.
|
|
|
|
|
|
|
|
|
|
There is no shame in releasing a project as open source even if it has
|
|
|
|
|
an "internal" or "individual" name.
|
|
|
|
|
|
|
|
|
|
If the project comes to a point where the author wants to change
|
|
|
|
|
ownership (i.e. the project no longer belongs to an individual), keep
|
|
|
|
|
in mind `it is easy to rename the project
|
|
|
|
|
<#how-to-rename-a-project>`_.
|
|
|
|
|
|
|
|
|
|
Community-owned projects can avoid namespace packages
|
|
|
|
|
-----------------------------------------------------
|
|
|
|
|
|
|
|
|
|
If your project is generic enough (i.e. it is not a contrib to another
|
|
|
|
|
product or framework), you can avoid namespace packages. The base
|
|
|
|
|
condition is generally that your project is owned by a group (i.e. the
|
|
|
|
|
development team) which is dedicated to this project.
|
|
|
|
|
|
|
|
|
|
Only use a "shared" namespace if you really intend the code to be
|
|
|
|
|
community owned.
|
|
|
|
|
|
|
|
|
|
As an example, `sphinx`_ project belongs to the Sphinx development
|
|
|
|
|
team. There is no need to have some "sphinx" namespace package with
|
|
|
|
|
only one "sphinx.sphinx" project inside.
|
|
|
|
|
|
|
|
|
|
In doubt, use an individual/organization namespace
|
|
|
|
|
--------------------------------------------------
|
|
|
|
|
|
|
|
|
|
If your project is really experimental, best choice is to use an
|
|
|
|
|
individual or organization namespace:
|
|
|
|
|
|
|
|
|
|
* it allows projects to be released early.
|
|
|
|
|
|
|
|
|
|
* it won't block a name if the project is abandoned.
|
|
|
|
|
|
|
|
|
|
* it doesn't block future changes. When a project becomes mature and
|
|
|
|
|
there is no reason to keep individual ownership, `it remains
|
|
|
|
|
possible to rename the project <#how-to-rename-a-project>`_.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Use a single name
|
|
|
|
|
=================
|
|
|
|
|
|
|
|
|
|
Distribute only one package (or only one module) per project, and use
|
|
|
|
|
package (or module) name as project name.
|
|
|
|
|
|
|
|
|
|
* 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.
|
|
|
|
|
|
|
|
|
|
Yes:
|
|
|
|
|
|
|
|
|
|
* Package name: "kheops.pyramid",
|
|
|
|
|
i.e. ``import kheops.pyramid``
|
|
|
|
|
|
|
|
|
|
* Project name: "kheops.pyramid",
|
|
|
|
|
i.e. ``pip install kheops.pyramid``
|
|
|
|
|
|
|
|
|
|
No:
|
|
|
|
|
|
|
|
|
|
* Package name: "kheops"
|
|
|
|
|
* Project name: "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`_ are both declaring
|
|
|
|
|
"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 don't need
|
|
|
|
|
this feature. So a distribution should provide only one package or
|
|
|
|
|
module at a time.
|
|
|
|
|
|
|
|
|
|
Distinct names should be rare
|
|
|
|
|
-----------------------------
|
|
|
|
|
|
|
|
|
|
A notable exception to the `Use a single name`_ rule is when you
|
2016-07-14 10:16:06 -04:00
|
|
|
|
explicitly need distinct names.
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
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. So a distributed package name should be equal to project
|
|
|
|
|
name.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Follow PEP 8 for syntax of package and module names
|
|
|
|
|
===================================================
|
|
|
|
|
|
|
|
|
|
`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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
|
|
|
|
partly 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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Use packaging metadata
|
|
|
|
|
======================
|
|
|
|
|
|
|
|
|
|
Consider project names as unique identifiers on PyPI:
|
|
|
|
|
|
|
|
|
|
* it is important that these identifiers remain human-readable.
|
|
|
|
|
* it is even better when these identifiers are meaningful.
|
|
|
|
|
* but the primary purpose of identifiers is not to classify or
|
|
|
|
|
describe projects.
|
|
|
|
|
|
|
|
|
|
**Classifiers and keywords metadata are made for categorization of
|
|
|
|
|
distributions.** Summary and description metadata are meant to
|
|
|
|
|
describe the project.
|
|
|
|
|
|
|
|
|
|
As an example, there is a "`Framework :: Twisted`_" classifier. Even
|
|
|
|
|
if names are quite heterogeneous (they don't follow a particular
|
|
|
|
|
pattern), we get the list.
|
|
|
|
|
|
|
|
|
|
In order to `Organize community contributions`_, conventions about
|
|
|
|
|
names and namespaces matter, but conventions about metadata should be
|
|
|
|
|
even more important.
|
|
|
|
|
|
|
|
|
|
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
|
2016-07-11 11:14:08 -04:00
|
|
|
|
distributions is inappropriate. It's impossible to get the full list of
|
2012-06-26 13:25:12 -04:00
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Avoid deep nesting
|
|
|
|
|
==================
|
|
|
|
|
|
|
|
|
|
`The Zen of Python`_ says "Flat is better than nested".
|
|
|
|
|
|
|
|
|
|
Two levels is almost always enough
|
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
|
|
Don't 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: "pyranha"
|
|
|
|
|
|
|
|
|
|
Yes: "pythonsport.climbing"
|
|
|
|
|
|
|
|
|
|
Yes: "pythonsport.forestmap"
|
|
|
|
|
|
|
|
|
|
No: "pythonsport.maps.forest"
|
|
|
|
|
|
|
|
|
|
Use only one level for ownership
|
|
|
|
|
--------------------------------
|
|
|
|
|
|
|
|
|
|
Don't use 3 levels to set individual/organization ownership in
|
|
|
|
|
a community namespace.
|
|
|
|
|
|
|
|
|
|
As an example, let's consider:
|
|
|
|
|
|
2019-07-30 14:58:49 -04:00
|
|
|
|
* you are plugging into a community namespace, such as "collective".
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
* and you want to add a more restrictive "ownership" level, to avoid
|
|
|
|
|
clashes inside the community.
|
|
|
|
|
|
|
|
|
|
In such a case, **you'd better use the most restrictive ownership
|
|
|
|
|
level as first level.**
|
|
|
|
|
|
|
|
|
|
As an example, where "collective" is a major community namespace that
|
|
|
|
|
"gergovie" belongs to, and "vercingetorix" it the name of "gergovie"
|
|
|
|
|
author:
|
|
|
|
|
|
|
|
|
|
No: "collective.vercingetorix.gergovie"
|
|
|
|
|
|
|
|
|
|
Yes: "vercingetorix.gergovie"
|
|
|
|
|
|
|
|
|
|
Don't use namespace levels for categorization
|
|
|
|
|
---------------------------------------------
|
|
|
|
|
|
|
|
|
|
`Use packaging metadata`_ instead.
|
|
|
|
|
|
|
|
|
|
Don't use more than 3 levels
|
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
|
|
Technically, you can create deeply nested hierarchies. However, in
|
|
|
|
|
most cases, you shouldn't need it.
|
|
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
Even communities where namespaces are standard don't use more than
|
|
|
|
|
3 levels.
|
|
|
|
|
|
|
|
|
|
Conventions for communities or related projects
|
|
|
|
|
===============================================
|
|
|
|
|
|
|
|
|
|
Follow community or related project conventions, if any
|
|
|
|
|
-------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
Projects or related communities can have specific conventions, which
|
|
|
|
|
may differ from those explained in this document.
|
|
|
|
|
|
|
|
|
|
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 own the "pyranha"
|
|
|
|
|
namespace.
|
|
|
|
|
|
|
|
|
|
* 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. It breaks the
|
|
|
|
|
`Top-level namespace relates to code ownership`_ rule.
|
|
|
|
|
|
|
|
|
|
* ``${MAINPROJECT}.contrib.*`` breaks the `Avoid deep nesting`_
|
|
|
|
|
rule.
|
|
|
|
|
|
|
|
|
|
* names where ``${MAINPROJECT}`` doesn't 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. Don't 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>`_.
|
|
|
|
|
|
|
|
|
|
About convention choices:
|
|
|
|
|
|
|
|
|
|
* New projects should choose the `default contrib pattern
|
|
|
|
|
<#use-standard-pattern-for-community-contributions>`_.
|
|
|
|
|
|
|
|
|
|
* Existing projects with community contributions should start with
|
|
|
|
|
custom conventions. Then they can `Promote migrations`_.
|
|
|
|
|
|
|
|
|
|
It means that existing community conventions don't have to be
|
2016-07-14 10:16:06 -04:00
|
|
|
|
changed. But, at least, they should be explicitly documented.
|
2012-06-26 13:25:12 -04:00
|
|
|
|
|
|
|
|
|
Example: "pyranha" is your project name and package name.
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Recipes
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
The following recipes will help you follow the guidelines and
|
|
|
|
|
conventions above.
|
|
|
|
|
|
|
|
|
|
How to check for name availability?
|
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
|
|
Before you choose a project name, make sure it hasn't already been
|
|
|
|
|
registered in the following locations:
|
|
|
|
|
|
|
|
|
|
* `PyPI`_
|
|
|
|
|
* that's all. PyPI is the only official place.
|
|
|
|
|
|
|
|
|
|
As an example, you could also check in various locations such as
|
|
|
|
|
popular code hosting services, but keep in mind that PyPI is the only
|
|
|
|
|
place you can **register** for names in Python community.
|
|
|
|
|
|
|
|
|
|
That's why it is important you `register names with PyPI`_.
|
|
|
|
|
|
|
|
|
|
Also make sure the names of distributed packages or modules haven't
|
|
|
|
|
already been registered:
|
|
|
|
|
|
|
|
|
|
* in the `Python Standard Library`_.
|
|
|
|
|
|
|
|
|
|
* inside projects at `PyPI`. There is currently no helper for that.
|
|
|
|
|
Notice that the more projects follow the `use a single name`_ rule,
|
|
|
|
|
the easier is the verification.
|
|
|
|
|
|
|
|
|
|
* you may `ask the community <#if-in-doubt-ask>`_.
|
|
|
|
|
|
|
|
|
|
The `use a single name`_ rule also 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 keep in mind that it will cause
|
|
|
|
|
some confusions. So, 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.
|
|
|
|
|
|
|
|
|
|
#. Assign ``Obsoletes-Dist`` metadata to new distribution in setup.cfg
|
|
|
|
|
file. See `PEP 345 about Obsolete-Dist`_ and `setup.cfg
|
|
|
|
|
specification`_.
|
|
|
|
|
|
|
|
|
|
#. Release a new version of the renamed project, then publish it.
|
|
|
|
|
|
|
|
|
|
#. Edit legacy project:
|
|
|
|
|
|
|
|
|
|
* 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.
|
|
|
|
|
|
|
|
|
|
Improved handling of renamed projects on PyPI
|
|
|
|
|
'''''''''''''''''''''''''''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
If many projects follow `Renaming howto <#how-to-rename-a-project>`_
|
|
|
|
|
recipe, then many legacy distributions will have the following
|
|
|
|
|
characteristics:
|
|
|
|
|
|
|
|
|
|
* ``Development Status :: 7 - Inactive`` classifier.
|
|
|
|
|
* latest version is empty, except packaging stuff.
|
2016-07-11 11:14:08 -04:00
|
|
|
|
* latest version "redirects" to another distribution. E.g. it has a
|
2012-06-26 13:25:12 -04:00
|
|
|
|
single dependency on the renamed project.
|
|
|
|
|
* referenced as ``Obsoletes-Dist`` in a newer distribution.
|
|
|
|
|
|
|
|
|
|
So it will be possible to detect renamed projects and improve
|
|
|
|
|
readability on PyPI. So that users can focus on active distributions.
|
|
|
|
|
But this feature is not required now. There is no urge. It won't be
|
|
|
|
|
covered in this document.
|
|
|
|
|
|
|
|
|
|
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 mainteners for obvious reasons.
|
|
|
|
|
|
|
|
|
|
However, project authors are invited to:
|
|
|
|
|
|
|
|
|
|
* at least, `state about current naming`_.
|
|
|
|
|
* then `plan and promote migration <#promote-migrations>`_.
|
|
|
|
|
* optionally actually `rename existing project or distributed
|
|
|
|
|
packages/modules <#how-to-rename-a-project>`_.
|
|
|
|
|
|
|
|
|
|
State about current naming
|
|
|
|
|
''''''''''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
The important thing, at first, is that you state about current
|
|
|
|
|
choices:
|
|
|
|
|
|
|
|
|
|
* Ask yourself "why did I choose the current name?", then document it.
|
|
|
|
|
* If there are differences with the guidelines provided in this
|
|
|
|
|
document, you should tell your users.
|
|
|
|
|
* If possible, create issues in the project's bugtracker, at least for
|
|
|
|
|
record. Then you are free to resolve them later, or maybe mark them
|
|
|
|
|
as "wontfix".
|
|
|
|
|
|
|
|
|
|
Projects that are meant to receive contributions from community should
|
|
|
|
|
also `organize community contributions`_.
|
|
|
|
|
|
|
|
|
|
Promote migrations
|
|
|
|
|
''''''''''''''''''
|
|
|
|
|
|
|
|
|
|
Every Python developer should migrate whenever possible, or promote
|
|
|
|
|
the migrations in their respective communities.
|
|
|
|
|
|
|
|
|
|
Apply these guidelines on your projects, then the community will see
|
|
|
|
|
it is safe.
|
|
|
|
|
|
|
|
|
|
In particular, "leaders" such as authors of popular projects are
|
2016-07-11 11:14:08 -04:00
|
|
|
|
influential, they have power and, thus, responsibility over
|
2012-06-26 13:25:12 -04:00
|
|
|
|
communities.
|
|
|
|
|
|
|
|
|
|
Apply these guidelines on popular projects, then communities will
|
|
|
|
|
adopt the conventions too.
|
|
|
|
|
|
|
|
|
|
**Projects should promote migrations when they release a new (major)
|
|
|
|
|
version**, particularly `if this version introduces support for
|
|
|
|
|
Python 3.x, new standard library's packaging or namespace packages
|
|
|
|
|
<#opportunity>`_.
|
|
|
|
|
|
|
|
|
|
Opportunity
|
|
|
|
|
'''''''''''
|
|
|
|
|
|
|
|
|
|
As of Python 3.3 being developed:
|
|
|
|
|
|
|
|
|
|
* many projects are not Python 3.x compatible. It includes "big"
|
|
|
|
|
products or frameworks. It means that many projects will have to do
|
|
|
|
|
a migration to support Python 3.x.
|
|
|
|
|
|
|
|
|
|
* packaging (aka distutils2) is on the starting blocks. When it is
|
|
|
|
|
released, projects will be invited to migrate and use new packaging.
|
|
|
|
|
|
|
|
|
|
* `PEP 420`_ brings official support of namespace packages to Python.
|
|
|
|
|
|
|
|
|
|
It means that most active projects should be about to migrate in the
|
|
|
|
|
next year(s) to support Python 3.x, new packaging or new namespace
|
|
|
|
|
packages.
|
|
|
|
|
|
|
|
|
|
Such an opportunity is unique and won't come again soon!
|
|
|
|
|
So let's introduce and promote naming conventions as soon as possible
|
|
|
|
|
(i.e. **now**).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 345`: http://www.python.org/dev/peps/pep-0345/
|
|
|
|
|
.. _`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/
|
|
|
|
|
.. _`sphinx`: http://sphinx.pocoo.org
|
|
|
|
|
.. _`pypi`: http://pypi.python.org
|
|
|
|
|
.. _`collective.recaptcha`:
|
|
|
|
|
http://pypi.python.org/pypi/collective.recaptcha/
|
2017-03-24 17:11:33 -04:00
|
|
|
|
.. _`pipeline`: http://pypi.python.org/pypi/pipeline/
|
2012-06-26 13:25:12 -04:00
|
|
|
|
.. _`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`:
|
2015-12-18 12:42:08 -05:00
|
|
|
|
https://docs.python.org/3/distutils/packageindex.html
|
2012-06-26 13:25:12 -04:00
|
|
|
|
.. _`Python Standard Library`:
|
|
|
|
|
http://docs.python.org/library/index.html
|
|
|
|
|
.. _`PEP 345 about Obsolete-Dist`:
|
|
|
|
|
http://www.python.org/dev/peps/pep-0345/#obsoletes-dist-multiple-use
|
|
|
|
|
.. _`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:
|