Package: test-project-python
test_project_pythonNOTE: substitute the alias you set forpythonon your local machine for any commands below that callpython. Common aliases includepython,python3,py3,python3.x, orpy3.x(wherexcorresponds to the python minor release version of your installation).This project contains a dummy python project totest how packaging works for pythonusing thesetuptoolsmodulesee the comments in thesetup.pyfile for more references and informationwhen uploading tohttps://test.pypi.org/and/orhttps://pypi.org/references describing basic packaging information:Packaging Python ProjectsPython: Creating a pip installable packageGPG signing - how does that really work with PyPI?Packaging and distributing projectsreferences describing more advanced packaging capabilities:Packaging namespace packagesCreating and discovering pluginsPackaging binary extensionspackaging.python.org landing page:Python Packaging User Guidemaintained byPython Packaging AuthorityThe information included below covers building both animport packageandadistribution package.RequirementsThis package usesf-strings(learn more about f-strings here), so this package requires Python version 3.6+ to run properly.If you do not have Python installed, or have an older version of Python, you can download Python 3.11.2 (the latest stable version as of UTC 2023-03-18) from one of the links below and follow the instructions to set up Python for your machine. If you want to install a different version, visit thePython Downloads pageand select the version you want.Gzipped source tarballXZ compressed source tarballmacOS 64-bit universal2 installerWindows embeddable package (32-bit)Windows embeddable package (64-bit)Windows embeddable package (ARM64)Windows installer (32-bit)Windows installer (64-bit)Windows installer (ARM64)Instructions for downloading Python on other platformsExamplesNOTE that the following commands need to be run from your shell, andnotyour python interpreter!Installing or upgrading thetest_project_pythonpackagepython -m pip install --upgrade test_project_pythonRunning modules defined in thetest_project_pythonpackagepython -m test_project_python.make_nested_py_modules
# now take a look at the directories and modules created by this command

python -m test_project_python.make_nested_py_modules_examples
# now take a look at the directories and modules created by this commandRunning commands defined inentry_points['console_scripts']located in thesetup.pymodulecommand_name
command_name_for_function_in__main__Project StructureThe tree structure included below includes all the contents of thetest_project_pythonproject hosted in the GitHub repository. When you download the package usingpython -m pip install --upgrade test_project_python, you installonlythe contents included under thebuild/libdirectory!Usually, this (the contents under thebuild/libdirectory) is installed inthe/path/to/your/python_version/site-packages/directory on Debian based Linux distributionsthe/path/to/your/python/python_version/lib/python_version/site-packages/directory on macOStheC:\path\to\your\python_version\site-packages\folder on WindowsThe exact location may vary based on which Python installer you used, how you configured your Python installation, and which operating system you are using, so this might not be exactly correct for your package installation (but should be close). To find the exact location of the package installation, open up a Python interpreter and runimporttest_project_pythontest_project_python.__file__Note that some of the files below are configuration/build/binary files auto-generated by running commands to set up the package locally, and are NOT included in the GitHub repository:the (no longer recommended)python setup.py sdistcommands createsdist/test-project-python-0.0.2.post9.tar.gztest_project_python.egg-info(and nested contents)usepython -m buildorpython -m build --no-isolationcommand instead to use thelatestbuild toolsthe (no longer recommended)python setup.py bdist_wheelcommand createsbuild/bdist.OPERATINGSYSTEMNAME-moreoperatingsysteminfodist/test_project_python-0.0.2.post9-py3-none-any.whlbuild/lib/(and nested contents)test_project_python.egg-info(and nested contents)usepython -m buildorpython -m build --no-isolationcommand instead to use thelatestbuild toolsthepython -m buildcommandcreatesdist/test-project-python-0.0.2.post9.tar.gzdist/test_project_python-0.0.2.post9-py3-none-any.whltest_project_python.egg-info(and nested contents)thepython -m pip install .command createsbuild/bdist.OPERATINGSYSTEMNAME-moreoperatingsysteminfobuild/lib/(and nested contents)test_project_python.egg-info(and nested contents)thegpg --detach-sign -a dist/test-project-python-0.0.2.post9.tar.gzcommand createsdist/test-project-python-0.0.2.post9.tar.gz.ascthegpg --detach-sign -a dist/test_project_python-0.0.2.post9-py3-none-any.whlcommand createsdist/test_project_python-0.0.2.post9-py3-none-any.whl.ascAlso note that running python files as modules locally creates a__pycache__directory and.pycfile nested inside the__pycache__directory (which were manually excluded from the structure below) for that corresponding module!note that this.pycfile creation inside the__pycache__directoryonly happens when runningpython3 -m path.to.module.namedoes NOT happen when runningpython3 path/to/module/name.py(structure taken from the output of thetreecommand run from thetest-project/pythondirectory).
├── README.md
├── build
│   ├── bdist.OPERATINGSYSTEMNAME-moreoperatingsysteminfo
│   └── lib
│       ├── package_a
│       │   ├── __init__.py
│       │   ├── module_a.py
│       │   ├── module_b.py
│       │   ├── module_c.py
│       │   ├── module_d.py
│       │   ├── module_e.py
│       │   ├── subpackage_a
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   ├── subpackage_b
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   └── subpackage_c
│       │       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       │       ├── a.py
│       │       ├── b.py
│       │       ├── c.py
│       │       ├── d.py
│       │       └── e.py
│       ├── package_b
│       │   ├── __init__.py
│       │   ├── module_a.py
│       │   ├── module_b.py
│       │   ├── module_c.py
│       │   ├── module_d.py
│       │   ├── module_e.py
│       │   ├── subpackage_a
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   ├── subpackage_b
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   └── subpackage_c
│       │       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       │       ├── a.py
│       │       ├── b.py
│       │       ├── c.py
│       │       ├── d.py
│       │       └── e.py
│       ├── package_c
│       │   ├── __init__.py
│       │   ├── module_a.py
│       │   ├── module_b.py
│       │   ├── module_c.py
│       │   ├── module_d.py
│       │   ├── module_e.py
│       │   ├── subpackage_a
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   ├── subpackage_b
│       │   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│       │   │   ├── a.py
│       │   │   ├── b.py
│       │   │   ├── c.py
│       │   │   ├── d.py
│       │   │   └── e.py
│       │   └── subpackage_c
│       │       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       │       ├── a.py
│       │       ├── b.py
│       │       ├── c.py
│       │       ├── d.py
│       │       └── e.py
│       └── test_project_python
│           ├── __init__.py
│           └── __main__.py
│           └── make_nested_py_modules.py
│           └── make_nested_py_modules_examples.py
├── dist
│   ├── test-project-python-0.0.2.post9.tar.gz
│   ├── test-project-python-0.0.2.post9.tar.gz.asc
│   └── test_project_python-0.0.2.post9-py3-none-any.whl
│   └── test_project_python-0.0.2.post9-py3-none-any.whl.asc
├── make_nested_py_modules.sh
├── package_a
│   ├── __init__.py
│   ├── module_a.py
│   ├── module_b.py
│   ├── module_c.py
│   ├── module_d.py
│   ├── module_e.py
│   ├── subpackage_a
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   ├── subpackage_b
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   └── subpackage_c
│       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       ├── a.py
│       ├── b.py
│       ├── c.py
│       ├── d.py
│       └── e.py
├── package_b
│   ├── __init__.py
│   ├── module_a.py
│   ├── module_b.py
│   ├── module_c.py
│   ├── module_d.py
│   ├── module_e.py
│   ├── subpackage_a
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   ├── subpackage_b
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   └── subpackage_c
│       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       ├── a.py
│       ├── b.py
│       ├── c.py
│       ├── d.py
│       └── e.py
├── package_c
│   ├── __init__.py
│   ├── module_a.py
│   ├── module_b.py
│   ├── module_c.py
│   ├── module_d.py
│   ├── module_e.py
│   ├── subpackage_a
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_a
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   ├── subpackage_b
│   │   ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_b
│   │   ├── a.py
│   │   ├── b.py
│   │   ├── c.py
│   │   ├── d.py
│   │   └── e.py
│   └── subpackage_c
│       ├── __init__.py    # this __init__.py module MUST exist for setuptools to *automatically* detect subpackage_c
│       ├── a.py
│       ├── b.py
│       ├── c.py
│       ├── d.py
│       └── e.py
├── setup.py
└── test_project_python
│   ├── __init__.py
│   ├── __main__.py
│   ├── make_nested_py_modules.py
│   ├── make_nested_py_modules_examples.py
└── test_project_python.egg-info
    ├── PKG-INFO
    ├── SOURCES.txt
    ├── dependency_links.txt
    ├── entry_points.txt
    └── top_level.txtDevelopment requirementsThe following requirements are NOT required to run thetest_project_pythonpackage locally (after installing withpython -m pip install --upgrade test_project_python), but ARE required to follow along with theBuilding a python package for distributionsection below.python -m pip install --upgrade pip build twineThe download link below to GnuPG is NOT required for theBuilding a python package for distributionsection below, but will enable you to sign your package.https://gnupg.org/download/for more details about downloading, installing, and usinggpg(and related tools), see theGPG sectionunder theProgramming language agnostic tools sectionin themain README in the GitHub repositoryVersion tag rules for a python package for distributionThe version tag (specified in theversionargument to thesetuptools.setupfunction insetup.py) must follow the rules outlined inPEP 440 – Version Identification and Dependency Specification. Not doing so will result in an error such as the following (the following snippet used theversionvalue of0.0.2.update1in thesetuptools.setupfunction insetup.py):$ twine upload --repository-url https://test.pypi.org/legacy/ dist/test_project_python-0.0.2.update1-py3-none-any.whl dist/test-project-python-0.0.2.update1.tar.gz dist/test-project-python-0.0.2.update1.tar.gz.asc dist/test_project_python-0.0.2.update1-py3-none-any.whl.asc
Uploading distributions to https://test.pypi.org/legacy/
Enter your username: username
Enter your password:
Uploading test_project_python-0.0.2.update1-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 49.2/49.2 kB • 00:00 • X.Y MB/s
WARNING  Error during upload. Retry with the --verbose option for more details.
ERROR    HTTPError: 400 Bad Request from https://test.pypi.org/legacy/
         '0.0.2.update1' is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and '.', '_' and '-'. See https://packaging.python.org/specifications/core-metadata for more
         information.

### with the --verbose flag ###
$ twine upload --repository-url https://test.pypi.org/legacy/ dist/test_project_python-0.0.2.update1-py3-none-any.whl dist/test-project-python-0.0.2.update1.tar.gz dist/test-project-python-0.0.2.update1.tar.gz.asc dist/test_project_python-0.0.2.update1-py3-none-any.whl.asc --verbose
Uploading distributions to https://test.pypi.org/legacy/
INFO     dist/test_project_python-0.0.2.update1-py3-none-any.whl (22.1 KB)
INFO     Signed with dist/test_project_python-0.0.2.update1-py3-none-any.whl.asc
INFO     dist/test-project-python-0.0.2.update1.tar.gz (15.2 KB)
INFO     Signed with dist/test-project-python-0.0.2.update1.tar.gz.asc
INFO     Querying keyring for username
Enter your username: username
INFO     Querying keyring for password
Enter your password:
INFO     username: username
INFO     password: <hidden>
Uploading test_project_python-0.0.2.update1-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 49.2/49.2 kB • 00:00 • X.Y MB/s
INFO     Response from https://test.pypi.org/legacy/:
         400 '0.0.2.update1' is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and '.', '_' and '-'. See https://packaging.python.org/specifications/core-metadata for more
         information.
INFO     <html>
          <head>
           <title>400 '0.0.2.update1' is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and '.', '_' and '-'. See https://packaging.python.org/specifications/core-metadata for
         more information.</title>
          </head>
          <body>
           <h1>400 '0.0.2.update1' is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and '.', '_' and '-'. See https://packaging.python.org/specifications/core-metadata for more
         information.</h1>
           The server could not comply with the request since it is either malformed or otherwise incorrect.<br/><br/>
         &#x27;0.0.2.update1&#x27; is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and &#x27;.&#x27;, &#x27;_&#x27; and &#x27;-&#x27;. See
         https://packaging.python.org/specifications/core-metadata for more information.


          </body>
         </html>
ERROR    HTTPError: 400 Bad Request from https://test.pypi.org/legacy/
         '0.0.2.update1' is an invalid value for Version. Error: Start and end with a letter or numeral containing only ASCII numeric and '.', '_' and '-'. See https://packaging.python.org/specifications/core-metadata for more
         information.NOTE that Python's versioning rules outlined inPEP 440are different and impose more restrictions than bothgitand GitHub do.for more details about versioning rules and guidelines forgitand GitHub, see theVersion tag rules sectionunder theGeneral Guidelines sectionin themain README in the GitHub repositoryAlso note that Python build tools (such assetuptoolsandbuild) normalize valid semantic version tags to follow a#.#.#.suffix#format, so you'll see a message such as the following when building your package with a command likepython -m buildorpython -m build --no-isolationif your tagdoes follow valid semantic versioningrules, but does not follow the#.#.#.suffix#format (NOTE that this does not apply if your tag format is only#.#.#and does not have a suffix):# valid semantic version tag and no normalization required:
# version='0.0.2-post-8' in `setup` function in setup.py  # no UserWarning message



# all of the following tags use a valid semantic version tag, but require normalization:

# uses a . (dot) or _ (underscore) after the #.#.# part
UserWarning: Normalizing '0.0.2-post-8' to '0.0.2.post8'  # version='0.0.2-post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2.post-8' to '0.0.2.post8'  # version='0.0.2.post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2-post.8' to '0.0.2.post8'  # version='0.0.2-post.8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2_post_8' to '0.0.2.post8'  # version='0.0.2_post_8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2.post_8' to '0.0.2.post8'  # version='0.0.2.post_8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2_post.8' to '0.0.2.post8'  # version='0.0.2_post.8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2_post-8' to '0.0.2.post8'  # version='0.0.2_post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2-post_8' to '0.0.2.post8'  # version='0.0.2-post_8' in `setup` function in setup.py

# no . (dot) after the #.#.# part:
UserWarning: Normalizing '0.0.2post-8' to '0.0.2.post8'   # version='0.0.2post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post-8' to '0.0.2.post8'   # version='0.0.2post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post.8' to '0.0.2.post8'   # version='0.0.2post.8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post_8' to '0.0.2.post8'   # version='0.0.2post_8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post_8' to '0.0.2.post8'   # version='0.0.2post_8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post.8' to '0.0.2.post8'   # version='0.0.2post.8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post-8' to '0.0.2.post8'   # version='0.0.2post-8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post_8' to '0.0.2.post8'   # version='0.0.2post_8' in `setup` function in setup.py
UserWarning: Normalizing '0.0.2post.8' to '0.0.2.post8'   # version='0.0.2post.8' in `setup` function in setup.py

# no . (dot) before the suffix:
UserWarning: Normalizing '0.0.2post8' to '0.0.2.post8'    # version='0.0.2post8'   in `setup` function in setup.py

# . (dot) after the suffix:
UserWarning: Normalizing '0.0.2.post.8' to '0.0.2.post8'  # version='0.0.2.post.8' in `setup` function in setup.pyBuilding a python package for distributionTo build a Python package for distribution for other people, update your package version to the newMAJOR.MINOR.PATCHversion (orMAJOR.MINOR.PATCH.suffixorMAJOR.MINOR.PATCH.suffix#) everywhere in the project. Then, run the following commands from the root of your python project (and make sure yoursetup.pymodule is here) using the commands for the operating system and shell you are using. In thetest_project_pythonproject, this is from the/path/to/test-project/pythondirectory (which is where thesetup.pymodule is located).Preparing the package for distributionUnix terminals such as bash, sh, zsh, ...# https://stackoverflow.com/questions/34928001/distutils-ignores-changes-to-setup-py-when-building-an-extensionpythonsetup.pyclean--all# avoid using cached informationrm-rbuild# python setup.py clean --all **should** remove all contents of build/, but just in caserm-rproject_name.egg-info# **should** be updated automatically with both the setup.py and pip install command below, but just in caserm-rpackage_*example_*# remove script generated packages (test_project_python specific, another project will have a different cleaning process)python-mtest_project_python.make_nested_py_modules# build script generated packages (test_project_python specific, another project will have a different build process)python-mbuild# build packages for distribution (add --no-isolation to avoid virtual environment requirement)python-mpipinstall.# install the package locally# run the sequence again (so run the 7 commands sequentially twice) just in case something somehow remains cachedWindows Command Line (also referred to as CMD, .bat, .cmd, batch script):: NOTE: :: (double colons) is the Windows syntax for writing comments in CMDpython setup.py clean --all&:: avoid using cached informationrmdir/S /Q build&:: python setup.py clean --all **should** remove all contents of build/, but just in casermdir/S /Q project_name.egg-info&:: **should** be updated automatically with both the setup.py and pip install command below, but just in casefor/d%G in ("package_*", "example_*") do rmdir /S /Q "%~dpnG"  &:: remove script generated packages (test_project_python specific, another project will have a different cleaning process)python -m test_project_python.make_nested_py_modules&:: build script generated packages (test_project_python specific, another project will have a different build process)
python -m build&:: build packages for distribution (add --no-isolation to avoid virtual environment requirement)
python -m pip install .&:: install the package locally:: run the sequence again (so run the 7 commands sequentially twice) just in case something somehow remains cachedPowerShell<#PowerShell is very flexible and has multiple aliases for common commands, sofeel free to substitute a different alias if you have one that you prefer.For example, you can use any of the aliases shown from the output of> help Remove-Itemso instead of> Remove-Item -recurse -path the_path_to_folderyou can do> Remove-Item -recurse the_path_to_folder # equivalent> ri    -r the_path_to_folder             # equivalent> rm    -r the_path_to_folder             # equivalent> rmdir -r the_path_to_folder             # equivalent> del   -r the_path_to_folder             # equivalent> erase -r the_path_to_folder             # equivalent> rd    -r the_path_to_folder             # equivalentNOTE that Remove-Item does NOT accept multiplearguments to Remove-Item (and the aliases also do not accept multiple arguments)#>pythonsetup.pyclean--all# avoid using cached informationRemove-Item-recurse-pathbuild# python setup.py clean --all **should** remove all contents of build/, but just in caseRemove-Item-recurse-pathproject_name.egg-info# **should** be updated automatically with both the setup.py and pip install command below, but just in caseRemove-Item-recurse-pathpackage_*# remove script generated packages (test_project_python specific, another project will have a different cleaning process)Remove-Item-recurse-pathexample_*# remove script generated packages (test_project_python specific, another project will have a different cleaning process)python-mtest_project_python.make_nested_py_modules# build script generated packages (test_project_python specific, another project will have a different build process)python-mbuild# build packages for distribution (add --no-isolation to avoid virtual environment requirement)python-mpipinstall.# install the package locally# run the sequence again (so run the 8 commands sequentially twice) just in case something somehow remains cachedSigning the package with GPG (optional)NOTE that your command may begpg2instead ofgpg(depends on how you installed this)also NOTE that the dashes or underscores in thedist/projectname.tar.gzis dependent on how you named things in yoursetup.pymodulemore specifically, the file name depends on thenameargument provided to thesetuptools.setupfunctionif you use underscores for thenamevalue, the file will bedist/project_name-MAJOR.MINOR.PATCH.tar.gz(ordist/project_name-MAJOR.MINOR.PATCH.suffix.tar.gzordist/project_name-MAJOR.MINOR.PATCH.suffix.tar.gz)if you use dashes for thenamevalue, the file will bedist/project-name-MAJOR.MINOR.PATCH.tar.gz(ordist/project-name-MAJOR.MINOR.PATCH.suffix.tar.gzordist/project-name-MAJOR.MINOR.PATCH.suffix#.tar.gz)NOTE that the following commands need to be run from your shell, andnotyour python interpreter!gpg --detach-sign -a dist/project_name-MAJOR.MINOR.PATCH-py3-none-any.whl
gpg --detach-sign -a dist/project-name-MAJOR.MINOR.PATCH.tar.gzUploading the package to the hosting indexUploading a package to a Python packaging index using a tool such astwinerequires having an account on the corresponding index. In other words, to upload totheTest PyPIindex, you need tomake an account thereif you do not already have onethePyPIindex, you need tomake an account thereif you do not already have onea private index, you need to have an account with the hosting organization and sufficient privileges to publish packagesthe exact details will vary, so ask the index maintainers/administrators what is required for the process of uploading and maintaining Python packages on your private indexa self-hosted index such aspypiserver, you need to follow whatever steps the person/organization maintaining the hosted service has established 🙂Also NOTE that if you want to uploadallpackages to an index, you can specifydist/*instead of individually listing each package you want to upload as the examples do below. Keep in mind that you cannot overwrite already existing versions of a package on Test PyPI and PyPI (which isprobablytrue for a private index and self-hosted index as well).NOTE that the following commands need to be run from your shell, andnotyour python interpreter!Uploading the new package tohttps://test.pypi.org/twine upload --repository-url https://test.pypi.org/legacy/ dist/project_name-MAJOR.MINOR.PATCH-py3-none-any.whl dist/project_name-MAJOR.MINOR.PATCH-py3-none-any.whl.asc dist/project-name-MAJOR.MINOR.PATCH.tar.gz dist/project-name-MAJOR.MINOR.PATCH.tar.gz.ascUploading the new package tohttps://pypi.org/doesnotrequire specifying the--repository-urltwine upload dist/project_name-MAJOR.MINOR.PATCH-py3-none-any.whl dist/project_name-MAJOR.MINOR.PATCH-py3-none-any.whl.asc dist/project-name-MAJOR.MINOR.PATCH.tar.gz dist/project-name-MAJOR.MINOR.PATCH.tar.gz.ascNOTE: Uploading to Test PyPI or PyPIdo not require registering your packageusing thesetup.py register(deprecated) command or thetwine registercommand, but a private or a self-hosted index (such aspypiserver] may require some form of registration. Contact the maintainer/administrator of the index for more information. For historical information, read theSupport for legacy register APIthread.To see some suggested best practices associated with distributing Python packages on PyPI, readSharing Your Labor of Love: PyPI Quick and DirtybyHynek Schlawack. This article has lots of useful advice, and indicates invokingpython setup.py sdistandpython setup.py sdist bdist_wheelis no longer recommended (see the linkedWhy you shouldn't invoke setup.py directlyarticle for more information). Instead, you should usepython -m build.ReleasesSee thelatest releasefrom thereleases page