Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Markdown
```console
project_name
    ├── LICENSE
    ├── project_name
    │   ├── __init__.py
    │   └── project_name.py
    ├── README.md
    ├── requirements.txt
    ├── pyproject.toml 
    ├── setup.cfg
    ├── setup.py
    └── tests
```
A good practices for creating new package directory structure:
 - All names should be lowercase
 - Names should be underscore-separeted (no hyphens)
 - The project name should be as unique as possible
 - The root directory should mainly store metadata files
 - Source files should be stored in a subdirectory with the same name as the project directory
 - Always pay attention to the inclusion of the LICENSE file

### Package directory contents
#### LICENSE file
```console
├── LICENSE
```
 - It’s important for every package to include a license. This tells users who install package the terms under which they can use it.
#### README.md file
```console
├── README.md
```
 - It can be customised in a way that best describes the project.
 - Normally, the package configuration loads README.md to provide a __long_description__, README.md must be included along with code when generating a source distribution.
#### requirements.txt file
```console
├── requirements.txt
```
 - Allows to store dependency versions for a project that are considered concrete and essential.
 - All necessary dependencies can be collected into requirements.txt with PIP like below:
```console
$ python -m pip freeze > requirements.txt
```
#### pyproject.toml file
```console
 ├── pyproject.toml  
```
 - A build-system independent way to specify project dependencies. It is a way to step away from distutils / setuptools.
 - Tells build tools (like pip and build) what is required to build project.
 - Minimal content:
```toml
[build-system]
requires = [
    "setuptools>=42",
    "wheel"
]
build-backend = "setuptools.build_meta"
```
 - __build-system.requires__ gives a list of packages that are needed to build project package.
 > Listing something here will only make it available during the build, not after it is installed.
 - __build-system.build-backend__ is the name of Python object that will be used to perform the build.
 - This is to omit setup.py and setup.cfg in the future, but is currently not fully supported.
#### Metadata configuration
There are two types of metadata: static and dynamic.

 * Static metadata (setup.cfg): guaranteed to be the same every time. This is simpler, easier to read, and avoids many common errors, like encoding errors.

 * Dynamic metadata (setup.py): possibly non-deterministic. Any items that are dynamic or determined at install-time, as well as extension modules or extensions to setuptools, need to go into setup.py. 
>Static metadata (setup.cfg) should be preferred. Dynamic metadata (setup.py) should be used only as an escape hatch when absolutely necessary. setup.py used to be required, but can be omitted with newer versions of setuptools and pip.

##### setup.cfg file - static metadata
```console
├── setup.cfg
```
 - setup.cfg is the configuration file for setuptools. It tells setuptools about project package (such as the name and version) as well as which code files to include. Eventually much of this configuration should be able to move to pyproject.toml.
 - Minimal content:
```ini
[metadata]
name = project_name
version = 0.0.1
author = Example Author
author_email = author@example.com
description = Sample short description of the package
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/author/project_name
project_urls =
    Bug Tracker = https://github.com/author/project_name/issues
classifiers =
    Programming Language :: Python :: 3
    License :: OSI Approved :: MIT License
    Operating System :: OS Independent

[options]
package_dir =
    = project_name
packages = find:
python_requires = >=3.6

[options.packages.find]
where = project_name
```


UI Expand
expandedtrue
titleOptions
  • name is the distribution name of your package. This can be any name as long as it only contains letters, numbers, _ , and -. It also must not already be taken on pypi.org. Be sure to update this with your username, as this ensures you won’t try to upload a package with the same name as one which already exists.

  • version is the package version. See PEP 440 for more details on versions. You can use file: or attr: directives to read from a file or package attribute.

  • author and author_email are used to identify the author of the package.

  • description is a short, one-sentence summary of the package.

  • long_description is a detailed description of the package. This is shown on the package detail page on the Python Package Index. In this case, the long description is loaded from README.md (which is a common pattern) using the file: directive.

  • long_description_content_type tells the index what type of markup is used for the long description. In this case, it’s Markdown.

  • url is the URL for the homepage of the project. For many projects, this will just be a link to GitHub, GitLab, Bitbucket, or similar code hosting service.

  • project_urls lets you list any number of extra links to show on PyPI. Generally this could be to documentation, issue trackers, etc.

  • classifiers gives the index and PIP some additional metadata about your package. In this case, the package is only compatible with Python 3, is licensed under the MIT license, and is OS-independent. You should always include at least which version(s) of Python your package works on, which license your package is available under, and which operating systems your package will work on. For a complete list of classifiers, see https://pypi.org/classifiers/.

In the options category, we have controls for setuptools itself:

  • package_dir is a mapping of package names and directories. An empty package name represents the “root package” — the directory in the project that contains all Python source files for the package — so in this case the src directory is designated the root package.

  • packages is a list of all Python import packages that should be included in the distribution package. Instead of listing each package manually, we can use the find: directive to automatically discover all packages and subpackages and options.packages.find to specify the package_dir to use. In this case, the list of packages will be example_package as that’s the only package present.

  • python_requires gives the versions of Python supported by your project. Installers like pip will look back through older versions of packages until it finds one that has a matching Python version.