_**Utility to find an available package name in the PyPI repository and optionally 'register' it.**_
[![PyPI][pypi-image]][pypi-url]
[![Downloads][downloads-image]][downloads-url]
[![Status][status-image]][pypi-url]
[![Python Version][python-version-image]][pypi-url]
[![tests][tests-image]][tests-url]
[![Codecov][codecov-image]][codecov-url]
[![CodeQl][codeql-image]][codeql-url]
[![Docker][docker-image]][docker-url]
[![pre-commit.ci status][pre-commit.ci-image]][pre-commit.ci-url]
[![readthedocs][readthedocs-image]][readthedocs-url]
[![CodeFactor][codefactor-image]][codefactor-url]
[![Codeclimate][codeclimate-image]][codeclimate-url]
[![Imports: isort][isort-image]][isort-url]
[![Code style: black][black-image]][black-url]
[![Checked with mypy][mypy-image]][mypy-url]
[![security: bandit][bandit-image]][bandit-url]
[![Commitizen friendly][commitizen-image]][commitizen-url]
[![Conventional Commits][conventional-commits-image]][conventional-commits-url]
[![DeepSource][deepsource-image]][deepsource-url]
[![license][license-image]][license-url]
[![pydough][pydough-image]][pydough-url]
<!-- [![OpenSSFScorecard][openssf-image]][openssf-url] -->
As a pseudo replacement for pip search, pynamer will quickly ascertain if a project name is 'available' in PyPI.
![](assets/pynamer1.png)
# Contents
- [tl;dr](#TLDR)
- [Introduction](#Introduction)
- [Quick Start](#Quick-Start)
- [Prerequisites](#Prerequisites)
- [Installation](#Installation)
- [Basic Usage](#Basic-Usage)
- [Usage](#Usage)
- [Specifying multiple names](#Specifying-multiple-names)
- [Using an input file](#Using-an-input-file)
- [Saving the results to a file](#Saving-the-results-to-a-file)
- [Display GitHub statistics](#Display-GitHub-statistics)
- [Register the name with PyPI](#Register-the-name-with-PyPI)
- [Verbose output](#Verbose-output)
- [Regenerate the PyPI simple Repository Index](#Regenerate-the-PyPI-simple-Repository-Index)
- [The oddities](#The-Oddities)
- [Limitations](#Limitations)
- [Documentation](#Documentation)
- [Read the Docs](https://pynamer.readthedocs.io/en/latest/)
- [API](https://pynamer.readthedocs.io/en/latest/autoapi/pynamer/pynamer/index.html)
- [Wiki](https://github.com/Stephen-RA-King/pynamer/wiki)
- [Planned Future improvements](#Planned-Future-improvements)
## Introduction
### Project Rationale
Some of you may have reached the point where you want to publish a package in the PyPI python repository.
The first step of which is to choose a unique name. Here lies the problem.
A recent look at the PyPI repository revealed there were over 453,769 projects, so many names have already been taken.
pip leaps to the rescue with its search utility... or does it?
```python
pip search zaphod
```
```bash
ERROR: XMLRPC request failed [code: -32500]
RuntimeError: PyPI no longer supports 'pip search' (or XML-RPC search).
Please use https://pypi.org/search (via a browser) instead.
See https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.
```
A quick search will show the internet replete with articles explaining the situation:
- [The Register: Why Python's pip search isn't working](https://www.theregister.com/2021/05/25/pypi_search_error/)
- [Python.org discussion: Pip search is still broken](https://discuss.python.org/t/pip-search-is-still-broken/18680)
OK so I go to the PyPI website and do a search for 'zaphod' as suggested by pip and 7 results are displayed none of which have the package name 'zaphod'
![](assets/pypi_zaphod.png)
Fantastic! I now think unbelievably that I have a unique name for a project that I can use.
So, I go ahead and code my new project, along with all the test files, documentation and meta data.
I diligently debug and commit and push to git and github so I have a history.
Finally the project is good enough to release and publish as an installable package on PyPI.
Here goes....
```bash
~ $ python -m twine upload --config-file .pypirc dist/*
Uploading distributions to https://upload.pypi.org/legacy/
Uploading zaphod-0.0.0-py3-none-any.whl
100% ---------------------------------------- 3.8/3.8 kB • 00:00 • ?
WARNING Error during upload. Retry with the --verbose option for more details.
ERROR HTTPError: 403 Forbidden from https://upload.pypi.org/legacy/
The user 'stephenking' isn't allowed to upload to project 'zaphod'. See https://pypi.org/help/#project-name for more information.
```
AARGH!
What just happened?
Yes unbelievably the project already exists and yes unbelievably PyPI's own search
did not find the project.
Enter Pynamer. Pynamer does not rely on a single method of finding a PyPI package:
#### TLDR
Pynamer uses the following methods to ascertain whether a package already exists on PyPI:
- A simple request to the project url on PyPI.
- Uses the PyPI "simple" repository - a text-based listing of all the packages available on PyPI.
- Uses PyPI's own search 'API' and scrapes the results.
Pynamer provides a way to optionally 'register' a name on PyPI by building a minimalistic package and uploading
## Quick Start
---
### Prerequisites
---
- [x] Python >= 3.9.
The following are optional but required for 'registering' a project name on PyPI
- [x] An account on PyPI (and generate a PyPI API token).
- [x] A [**.pypirc**](https://packaging.python.org/en/latest/specifications/pypirc/) file containing your PyPI API token.
or
- [x] Configure [Twine environment variables](https://twine.readthedocs.io/en/latest/#environment-variables).
Your .pypirc file should contain the following and be on your PATH:
```file
[distutils]
index-servers =
pypi
[pypi]
repository = https://upload.pypi.org/legacy/
username = __token__
password = your_API_token_here
```
### Installation
Pynamer can be installed into any python environment using pip:
```bash
~ $ pip install pynamer
```
However, optimal installation can be achieved using [**pipx**][pipx-url]:
```bash
~ $ pipx install pynamer
```
### Basic Usage
#### A package name that is not available
```bash
~ $ pynamer pynball
```
![](assets/usage_pynball.png)
#### A package name that is available
```bash
~ $ pynamer allitnil
```
![](assets/usage_available.png)
Holy smoke batman! You've managed to identify a unique name.
Yes, even though the odds were against you (given there are over 450,000+ registered projects), you did it!
Even though the name has nothing in common with your project, or may not even be a real word... you did it!
Congratulations!
# Usage
---
Display the help menu with the `-h` argument
```bash
~ $ pynamer -h
```
```bash
usage: pynamer [-h] [-r] [-v] [-g] [-m] [-s] [-w] [-f FILENAME] [-o FILENAME] [--version] [projects ...]
Determine if project name is available on pypi with the option to 'register' it for future use if available
positional arguments:
projects Optional - one or more project names
optional arguments:
-h, --help show this help message and exit
-r, --register register the name on PyPi if the name is available
-v, --verbose display information about similar projects
-g, --generate generate a new PyPI index file
-m, --meta input new meta data when registering (Author and email address)
-s, --stats display GitHub stats if available
-w, --webbrowser open the project on PyPI in a webbrowser
-f FILENAME file containing a list of project names to analyze
-o FILENAME file to save the test results
--version display version number
```
## Specifying multiple names
You can specify as many names as you like from the command line e.g.
```bash
~ $ pynamer ganymede europa callisto
```
## Using an input file
You can use the `-f` argument to specify a file containing the a names of projects to analyze.
You specify a space separated sequence of as many names as you like on as many lines as you like. e.g.
'projects' file
```file
ganymede europa
IO callisto
```
Then specify the `-f` argument
```bash
~ $ pynamer -f projects
```
You can use the input file with names from the command line. The names will be aggregated. e.g.
```bash
~ $ pynamer ersa pandia leda metis -f projects
```
## Saving the results to a file
You can specify a file to write the result to by using the `-o` argument. e.g.
```bash
~ $ pynamer ersa pandia leda -o results
```
This will write a file e.g.
results
```file
Result from pynamer PyPI utility 2023-05-02
-------------------------------------------
test 1 - Basic url lookup on PyPI
test 2 - Search of PyPIs simple index
test 3 - Search using an request to PyPIs search 'API'.
Project name Test1 Test2 Test 3 Conclusion
-------------------------------------------------------------------
ersa Found Found Found Not Available
pandia Not Found Not Found Found Not Available
leda Not Found Not Found Not Found Available
```
Again you can use a combination of names from the command line and input file.
## Display GitHub statistics
You can optionally display some of the most pertinent GitHub statistics if available by using the `-s` argument.
The statistics will be displayed in the the details section of test 1. e.g.
```bash
~ $ pynamer black -s
```
![](assets/usage_stats.png)
## Register the package name with PyPI
You can optionally 'register' the name on PyPI by using the `-r` argument.
If the project name is found to be available and you have a valid 'pypirc' file is found, a minimalistic project will be built and uploaded
to PyPI.
The first time you use the 'registration' procedure you will be prompted to enter your name and email address. These are required.
You can also optionally choose to change the version and description.
![](assets/usage_register_first.png)
This information will be retained and you will not be prompted to enter this information again. However, you can regenerate
this meta data by using the `-m` argument along with the `-r` argument. You can just enter on the options you dont want to change.
![](assets/usage_register_meta.png)
```bash
~ $ pynamer agrajag -r
```
![](assets/usage_register.png)
## Verbose output
With the `-v` argument you can display the first page of all other project matched by PyPIs search API - ordered by relevance.
The algorithm that PyPI uses to select these in unknown but seems to be a mixture of names and other
projects written by the same author.
```bash
~ $ pynamer pynamer -v
```
![](assets/usage_verbose.png)
## Regenerate the PyPI simple Repository Index
As one of its tests Pynamer makes use of a list of package names scraped from its simple index site.
The PyPI Simple Index is a plain text file that lists the names of all the packages available on PyPI.
It is a simplified version of the PyPI index that makes it easier for users to browse and download packages.
The PyPI Simple Index is used by a variety of tools and libraries to download and install packages from PyPI. For example, the pip package manager, which is used to install and manage Python packages, uses the PyPI Simple Index to find packages.
The Index is updated every few hours.
Using the `-g` argument can be used to regenerate the local file contents.
```bash
~ $ pynamer -g
```
![](assets/usage_generate.png)
See planned future improvements
## The Oddities
The reason I wrote this application in the first place...
```bash
~ $ pynamer zaphod
```
![](assets/usage_zaphod.png)
Even worse ...
```bash
~ $ pynamer zem
```
![](assets/usage_zem.png)
## Limitations
There will be occasions where all the tests pass, the name appears to be available but the upload to PyPI still fails.
This can be several reasons for this:
- You are trying to use an internally "reserved" keyword for PyPI.
- The name you are using is too similar to an existing project name and you get the following error message:
```bash
...
Error during upload. Retry with the --verbose option for more details.
HTTPError: 400 Bad Request from https://test.pypi.org/legacy/
The name 'yourpackage' is too similar to an existing project. See https://test.pypi.org/help/#project-name for more information-
```
Using a name similar to to an existing package name is a security issue.
Malicious players will try to create project names that are frequently mistyped for large popular projects, thereby facilitating installation of a malicious project.
e.g. replacing "L" / "l" with the number 1 or "o" / "O" with 0. The Software utilized by PyPI can be found on GitHub: [warehouse](https://github.com/pypi/warehouse).
## Using the Docker Image
Pull the latest image from the Hub.
```bash
~ $ docker pull sraking/pynamer
```
Run the image.
```bash
~ $ docker run -it sraking/pynamer /bin/bash
```
Use the command line as normal in the container.
```bash
root@4d315992ca28:/app# pynamer
usage: pynamer [-h] [-r] [-v] [-g] [-m] [-s] [-w] [-f FILENAME] [-o FILENAME] [--version] [projects ...]
Determine if project name is available on pypi with the option to 'register' it for future use if available
...
```
## Documentation
---
[**Read the Docs**](https://pynamer.readthedocs.io/en/latest/)
- [**Credits**](https://pynamer.readthedocs.io/en/latest/example.html)
- [**Changelog**](https://pynamer.readthedocs.io/en/latest/changelog.html)
- [**API Reference**](https://pynamer.readthedocs.io/en/latest/autoapi/index.html)
[**Wiki**](https://github.com/Stephen-RA-King/pynamer/wiki)
## Planned Future improvements
- Improve performance of the regeneration of the PyPI simple Repository Index, so this can be run in the background automatically.
## Meta
---
[![Linkedin](assets/linkedin.png)](https://www.linkedin.com/in/sr-king)
[![](assets/github.png)](https://github.com/Stephen-RA-King)
[![PyPI repository](assets/pypi.png)](https://pypi.org/project/pynamer)
[![Docker](assets/docker.png)](https://hub.docker.com/r/sraking/pynamer)
[![](assets/www.png)](https://stephen-ra-king.github.io/justpython/)
[![](assets/email.png)](mailto:sking.github@gmail.com)
Author: Stephen King ([sking.github@gmail.com](mailto:sking.github@gmail.com))
Distributed under the MIT license. See [![][license-image]][license-url] for more information.
Created with Cookiecutter template: [![pydough][pydough-image]][pydough-url] version 1.2.2
Digital object identifier: [![DOI](https://zenodo.org/badge/631029310.svg)](https://zenodo.org/badge/latestdoi/631029310)
<!-- Markdown link & img dfn's -->
[bandit-image]: https://img.shields.io/badge/security-bandit-yellow.svg
[bandit-url]: https://github.com/PyCQA/bandit
[black-image]: https://img.shields.io/badge/code%20style-black-000000.svg
[black-url]: https://github.com/psf/black
[codeclimate-image]: https://api.codeclimate.com/v1/badges/b95fb617fbcd469ccfc3/maintainability
[codeclimate-url]: https://codeclimate.com/github/Stephen-RA-King/pynamer/maintainability
[codeclimate-url]: https://codeclimate.com/github/Stephen-RA-King/pynamer/maintainability
[codecov-image]: https://codecov.io/gh/Stephen-RA-King/pynamer/branch/main/graph/badge.svg
[codecov-url]: https://app.codecov.io/gh/Stephen-RA-King/pynamer
[codefactor-image]: https://www.codefactor.io/repository/github/Stephen-RA-King/pynamer/badge
[codefactor-url]: https://www.codefactor.io/repository/github/Stephen-RA-King/pynamer
[codeql-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/github-code-scanning/codeql/badge.svg
[codeql-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/github-code-scanning/codeql
[commitizen-image]: https://img.shields.io/badge/commitizen-friendly-brightgreen.svg
[commitizen-url]: http://commitizen.github.io/cz-cli/
[conventional-commits-image]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square
[conventional-commits-url]: https://conventionalcommits.org
[deepsource-image]: https://app.deepsource.com/gh/Stephen-RA-King/pynamer.svg/?label=active+issues&show_trend=true&token=SGo-Vr17NUYVQaEWkU9rBb6Y
[deepsource-url]: https://app.deepsource.com/gh/Stephen-RA-King/pynamer/?ref=repository-badge
[docker-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/docker-image.yml/badge.svg
[docker-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/docker-image.yml
[downloads-image]: https://static.pepy.tech/personalized-badge/pynamer?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads
[downloads-url]: https://pepy.tech/project/pynamer
[format-image]: https://img.shields.io/pypi/format/pynamer
[isort-image]: https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336
[isort-url]: https://github.com/pycqa/isort/
[lgtm-alerts-image]: https://img.shields.io/lgtm/alerts/g/Stephen-RA-King/pynamer.svg?logo=lgtm&logoWidth=18
[lgtm-alerts-url]: https://lgtm.com/projects/g/Stephen-RA-King/pynamer/alerts/
[lgtm-quality-image]: https://img.shields.io/lgtm/grade/python/g/Stephen-RA-King/pynamer.svg?logo=lgtm&logoWidth=18
[lgtm-quality-url]: https://lgtm.com/projects/g/Stephen-RA-King/pynamer/context:python
[license-image]: https://img.shields.io/pypi/l/pynamer
[license-url]: https://github.com/Stephen-RA-King/pynamer/blob/main/LICENSE
[mypy-image]: http://www.mypy-lang.org/static/mypy_badge.svg
[mypy-url]: http://mypy-lang.org/
[openssf-image]: https://api.securityscorecards.dev/projects/github.com/Stephen-RA-King/pynamer/badge
[openssf-url]: https://api.securityscorecards.dev/projects/github.com/Stephen-RA-King/pynamer
[pipx-url]: https://pypa.github.io/pipx/
[pre-commit-image]: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white
[pre-commit-url]: https://github.com/pre-commit/pre-commit
[pre-commit.ci-image]: https://results.pre-commit.ci/badge/github/Stephen-RA-King/pynamer/main.svg
[pre-commit.ci-url]: https://results.pre-commit.ci/latest/github/Stephen-RA-King/pynamer/main
[pydough-image]: https://img.shields.io/badge/pydough-2023-orange
[pydough-url]: https://github.com/Stephen-RA-King/pydough
[pypi-image]: https://img.shields.io/pypi/v/pynamer.svg
[pypi-url]: https://pypi.org/project/pynamer/
[python-version-image]: https://img.shields.io/pypi/pyversions/pynamer
[readthedocs-image]: https://readthedocs.org/projects/pynamer/badge/?version=latest
[readthedocs-url]: https://pynamer.readthedocs.io/en/latest/?badge=latest
[status-image]: https://img.shields.io/pypi/status/pynamer.svg
[tests-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/tests.yml/badge.svg
[tests-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/tests.yml
[wiki]: https://github.com/Stephen-RA-King/pynamer/wiki
Raw data
{
"_id": null,
"home_page": "https://github.com/Stephen-RA-King/pynamer",
"name": "pynamer",
"maintainer": "Stephen R A King",
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "sking.github@gmail.com",
"keywords": "available-on-pypi,pip-search,packaging,naming,name-generation,names,pypi,packaging,naming-conventions",
"author": "Stephen R A King",
"author_email": "sking.github@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/07/17/4f31855510287f517622f9a106bfc358a473ec62738fffdb6f57be46737e/pynamer-2.1.8.tar.gz",
"platform": "Any",
"description": "_**Utility to find an available package name in the PyPI repository and optionally 'register' it.**_\r\n\r\n[![PyPI][pypi-image]][pypi-url]\r\n[![Downloads][downloads-image]][downloads-url]\r\n[![Status][status-image]][pypi-url]\r\n[![Python Version][python-version-image]][pypi-url]\r\n[![tests][tests-image]][tests-url]\r\n[![Codecov][codecov-image]][codecov-url]\r\n[![CodeQl][codeql-image]][codeql-url]\r\n[![Docker][docker-image]][docker-url]\r\n[![pre-commit.ci status][pre-commit.ci-image]][pre-commit.ci-url]\r\n[![readthedocs][readthedocs-image]][readthedocs-url]\r\n[![CodeFactor][codefactor-image]][codefactor-url]\r\n[![Codeclimate][codeclimate-image]][codeclimate-url]\r\n[![Imports: isort][isort-image]][isort-url]\r\n[![Code style: black][black-image]][black-url]\r\n[![Checked with mypy][mypy-image]][mypy-url]\r\n[![security: bandit][bandit-image]][bandit-url]\r\n[![Commitizen friendly][commitizen-image]][commitizen-url]\r\n[![Conventional Commits][conventional-commits-image]][conventional-commits-url]\r\n[![DeepSource][deepsource-image]][deepsource-url]\r\n[![license][license-image]][license-url]\r\n[![pydough][pydough-image]][pydough-url]\r\n<!-- [![OpenSSFScorecard][openssf-image]][openssf-url] -->\r\n\r\nAs a pseudo replacement for pip search, pynamer will quickly ascertain if a project name is 'available' in PyPI.\r\n\r\n![](assets/pynamer1.png)\r\n\r\n# Contents\r\n\r\n- [tl;dr](#TLDR)\r\n- [Introduction](#Introduction)\r\n- [Quick Start](#Quick-Start)\r\n - [Prerequisites](#Prerequisites)\r\n - [Installation](#Installation)\r\n - [Basic Usage](#Basic-Usage)\r\n- [Usage](#Usage)\r\n - [Specifying multiple names](#Specifying-multiple-names)\r\n - [Using an input file](#Using-an-input-file)\r\n - [Saving the results to a file](#Saving-the-results-to-a-file)\r\n - [Display GitHub statistics](#Display-GitHub-statistics)\r\n - [Register the name with PyPI](#Register-the-name-with-PyPI)\r\n - [Verbose output](#Verbose-output)\r\n - [Regenerate the PyPI simple Repository Index](#Regenerate-the-PyPI-simple-Repository-Index)\r\n- [The oddities](#The-Oddities)\r\n- [Limitations](#Limitations)\r\n- [Documentation](#Documentation)\r\n - [Read the Docs](https://pynamer.readthedocs.io/en/latest/)\r\n - [API](https://pynamer.readthedocs.io/en/latest/autoapi/pynamer/pynamer/index.html)\r\n - [Wiki](https://github.com/Stephen-RA-King/pynamer/wiki)\r\n- [Planned Future improvements](#Planned-Future-improvements)\r\n\r\n## Introduction\r\n\r\n### Project Rationale\r\n\r\nSome of you may have reached the point where you want to publish a package in the PyPI python repository.\r\nThe first step of which is to choose a unique name. Here lies the problem.\r\n\r\nA recent look at the PyPI repository revealed there were over 453,769 projects, so many names have already been taken.\r\n\r\npip leaps to the rescue with its search utility... or does it?\r\n\r\n```python\r\npip search zaphod\r\n```\r\n\r\n```bash\r\nERROR: XMLRPC request failed [code: -32500]\r\nRuntimeError: PyPI no longer supports 'pip search' (or XML-RPC search).\r\nPlease use https://pypi.org/search (via a browser) instead.\r\nSee https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.\r\n```\r\n\r\nA quick search will show the internet replete with articles explaining the situation:\r\n\r\n- [The Register: Why Python's pip search isn't working](https://www.theregister.com/2021/05/25/pypi_search_error/)\r\n- [Python.org discussion: Pip search is still broken](https://discuss.python.org/t/pip-search-is-still-broken/18680)\r\n\r\nOK so I go to the PyPI website and do a search for 'zaphod' as suggested by pip and 7 results are displayed none of which have the package name 'zaphod'\r\n\r\n![](assets/pypi_zaphod.png)\r\n\r\nFantastic! I now think unbelievably that I have a unique name for a project that I can use.\r\nSo, I go ahead and code my new project, along with all the test files, documentation and meta data.\r\nI diligently debug and commit and push to git and github so I have a history.\r\n\r\nFinally the project is good enough to release and publish as an installable package on PyPI.\r\n\r\nHere goes....\r\n\r\n```bash\r\n~ $ python -m twine upload --config-file .pypirc dist/*\r\nUploading distributions to https://upload.pypi.org/legacy/\r\nUploading zaphod-0.0.0-py3-none-any.whl\r\n100% ---------------------------------------- 3.8/3.8 kB \u2022 00:00 \u2022 ?\r\nWARNING Error during upload. Retry with the --verbose option for more details.\r\nERROR HTTPError: 403 Forbidden from https://upload.pypi.org/legacy/\r\n The user 'stephenking' isn't allowed to upload to project 'zaphod'. See https://pypi.org/help/#project-name for more information.\r\n```\r\n\r\nAARGH!\r\n\r\nWhat just happened?\r\n\r\nYes unbelievably the project already exists and yes unbelievably PyPI's own search\r\ndid not find the project.\r\n\r\nEnter Pynamer. Pynamer does not rely on a single method of finding a PyPI package:\r\n\r\n#### TLDR\r\n\r\nPynamer uses the following methods to ascertain whether a package already exists on PyPI:\r\n\r\n- A simple request to the project url on PyPI.\r\n- Uses the PyPI \"simple\" repository - a text-based listing of all the packages available on PyPI.\r\n- Uses PyPI's own search 'API' and scrapes the results.\r\n\r\nPynamer provides a way to optionally 'register' a name on PyPI by building a minimalistic package and uploading\r\n\r\n## Quick Start\r\n\r\n---\r\n\r\n### Prerequisites\r\n\r\n---\r\n\r\n- [x] Python >= 3.9.\r\n\r\nThe following are optional but required for 'registering' a project name on PyPI\r\n\r\n- [x] An account on PyPI (and generate a PyPI API token).\r\n- [x] A [**.pypirc**](https://packaging.python.org/en/latest/specifications/pypirc/) file containing your PyPI API token.\r\n\r\n or\r\n\r\n- [x] Configure [Twine environment variables](https://twine.readthedocs.io/en/latest/#environment-variables).\r\n\r\nYour .pypirc file should contain the following and be on your PATH:\r\n\r\n```file\r\n[distutils]\r\nindex-servers =\r\n pypi\r\n\r\n[pypi]\r\nrepository = https://upload.pypi.org/legacy/\r\nusername = __token__\r\npassword = your_API_token_here\r\n```\r\n\r\n### Installation\r\n\r\nPynamer can be installed into any python environment using pip:\r\n\r\n```bash\r\n~ $ pip install pynamer\r\n```\r\n\r\nHowever, optimal installation can be achieved using [**pipx**][pipx-url]:\r\n\r\n```bash\r\n~ $ pipx install pynamer\r\n```\r\n\r\n### Basic Usage\r\n\r\n#### A package name that is not available\r\n\r\n```bash\r\n~ $ pynamer pynball\r\n```\r\n\r\n![](assets/usage_pynball.png)\r\n\r\n#### A package name that is available\r\n\r\n```bash\r\n~ $ pynamer allitnil\r\n```\r\n\r\n![](assets/usage_available.png)\r\n\r\nHoly smoke batman! You've managed to identify a unique name.\r\n\r\nYes, even though the odds were against you (given there are over 450,000+ registered projects), you did it!\r\n\r\nEven though the name has nothing in common with your project, or may not even be a real word... you did it!\r\n\r\nCongratulations!\r\n\r\n# Usage\r\n\r\n---\r\n\r\nDisplay the help menu with the `-h` argument\r\n\r\n```bash\r\n~ $ pynamer -h\r\n```\r\n\r\n```bash\r\nusage: pynamer [-h] [-r] [-v] [-g] [-m] [-s] [-w] [-f FILENAME] [-o FILENAME] [--version] [projects ...]\r\n\r\nDetermine if project name is available on pypi with the option to 'register' it for future use if available\r\n\r\npositional arguments:\r\n projects Optional - one or more project names\r\n\r\noptional arguments:\r\n -h, --help show this help message and exit\r\n -r, --register register the name on PyPi if the name is available\r\n -v, --verbose display information about similar projects\r\n -g, --generate generate a new PyPI index file\r\n -m, --meta input new meta data when registering (Author and email address)\r\n -s, --stats display GitHub stats if available\r\n -w, --webbrowser open the project on PyPI in a webbrowser\r\n -f FILENAME file containing a list of project names to analyze\r\n -o FILENAME file to save the test results\r\n --version display version number\r\n```\r\n\r\n## Specifying multiple names\r\n\r\nYou can specify as many names as you like from the command line e.g.\r\n\r\n```bash\r\n~ $ pynamer ganymede europa callisto\r\n```\r\n\r\n## Using an input file\r\n\r\nYou can use the `-f` argument to specify a file containing the a names of projects to analyze.\r\nYou specify a space separated sequence of as many names as you like on as many lines as you like. e.g.\r\n\r\n'projects' file\r\n\r\n```file\r\nganymede europa\r\nIO callisto\r\n```\r\n\r\nThen specify the `-f` argument\r\n\r\n```bash\r\n~ $ pynamer -f projects\r\n```\r\n\r\nYou can use the input file with names from the command line. The names will be aggregated. e.g.\r\n\r\n```bash\r\n~ $ pynamer ersa pandia leda metis -f projects\r\n```\r\n\r\n## Saving the results to a file\r\n\r\nYou can specify a file to write the result to by using the `-o` argument. e.g.\r\n\r\n```bash\r\n~ $ pynamer ersa pandia leda -o results\r\n```\r\n\r\nThis will write a file e.g.\r\n\r\nresults\r\n\r\n```file\r\nResult from pynamer PyPI utility 2023-05-02\r\n-------------------------------------------\r\ntest 1 - Basic url lookup on PyPI\r\ntest 2 - Search of PyPIs simple index\r\ntest 3 - Search using an request to PyPIs search 'API'.\r\n\r\nProject name Test1 Test2 Test 3 Conclusion\r\n-------------------------------------------------------------------\r\nersa Found Found Found Not Available\r\npandia Not Found Not Found Found Not Available\r\nleda Not Found Not Found Not Found Available\r\n```\r\n\r\nAgain you can use a combination of names from the command line and input file.\r\n\r\n## Display GitHub statistics\r\n\r\nYou can optionally display some of the most pertinent GitHub statistics if available by using the `-s` argument.\r\nThe statistics will be displayed in the the details section of test 1. e.g.\r\n\r\n```bash\r\n~ $ pynamer black -s\r\n```\r\n\r\n![](assets/usage_stats.png)\r\n\r\n## Register the package name with PyPI\r\n\r\nYou can optionally 'register' the name on PyPI by using the `-r` argument.\r\nIf the project name is found to be available and you have a valid 'pypirc' file is found, a minimalistic project will be built and uploaded\r\nto PyPI.\r\n\r\nThe first time you use the 'registration' procedure you will be prompted to enter your name and email address. These are required.\r\nYou can also optionally choose to change the version and description.\r\n\r\n![](assets/usage_register_first.png)\r\n\r\nThis information will be retained and you will not be prompted to enter this information again. However, you can regenerate\r\nthis meta data by using the `-m` argument along with the `-r` argument. You can just enter on the options you dont want to change.\r\n\r\n![](assets/usage_register_meta.png)\r\n\r\n```bash\r\n~ $ pynamer agrajag -r\r\n```\r\n\r\n![](assets/usage_register.png)\r\n\r\n## Verbose output\r\n\r\nWith the `-v` argument you can display the first page of all other project matched by PyPIs search API - ordered by relevance.\r\nThe algorithm that PyPI uses to select these in unknown but seems to be a mixture of names and other\r\nprojects written by the same author.\r\n\r\n```bash\r\n~ $ pynamer pynamer -v\r\n```\r\n\r\n![](assets/usage_verbose.png)\r\n\r\n## Regenerate the PyPI simple Repository Index\r\n\r\nAs one of its tests Pynamer makes use of a list of package names scraped from its simple index site.\r\n\r\nThe PyPI Simple Index is a plain text file that lists the names of all the packages available on PyPI.\r\n\r\nIt is a simplified version of the PyPI index that makes it easier for users to browse and download packages.\r\n\r\nThe PyPI Simple Index is used by a variety of tools and libraries to download and install packages from PyPI. For example, the pip package manager, which is used to install and manage Python packages, uses the PyPI Simple Index to find packages.\r\nThe Index is updated every few hours.\r\n\r\nUsing the `-g` argument can be used to regenerate the local file contents.\r\n\r\n```bash\r\n~ $ pynamer -g\r\n```\r\n\r\n![](assets/usage_generate.png)\r\n\r\nSee planned future improvements\r\n\r\n## The Oddities\r\n\r\nThe reason I wrote this application in the first place...\r\n\r\n```bash\r\n~ $ pynamer zaphod\r\n```\r\n\r\n![](assets/usage_zaphod.png)\r\n\r\nEven worse ...\r\n\r\n```bash\r\n~ $ pynamer zem\r\n```\r\n\r\n![](assets/usage_zem.png)\r\n\r\n## Limitations\r\n\r\nThere will be occasions where all the tests pass, the name appears to be available but the upload to PyPI still fails.\r\nThis can be several reasons for this:\r\n\r\n- You are trying to use an internally \"reserved\" keyword for PyPI.\r\n- The name you are using is too similar to an existing project name and you get the following error message:\r\n\r\n```bash\r\n...\r\nError during upload. Retry with the --verbose option for more details.\r\nHTTPError: 400 Bad Request from https://test.pypi.org/legacy/\r\nThe name 'yourpackage' is too similar to an existing project. See https://test.pypi.org/help/#project-name for more information-\r\n```\r\n\r\nUsing a name similar to to an existing package name is a security issue.\r\n\r\nMalicious players will try to create project names that are frequently mistyped for large popular projects, thereby facilitating installation of a malicious project.\r\ne.g. replacing \"L\" / \"l\" with the number 1 or \"o\" / \"O\" with 0. The Software utilized by PyPI can be found on GitHub: [warehouse](https://github.com/pypi/warehouse).\r\n\r\n## Using the Docker Image\r\n\r\nPull the latest image from the Hub.\r\n```bash\r\n~ $ docker pull sraking/pynamer\r\n```\r\nRun the image.\r\n```bash\r\n~ $ docker run -it sraking/pynamer /bin/bash\r\n```\r\nUse the command line as normal in the container.\r\n\r\n```bash\r\nroot@4d315992ca28:/app# pynamer\r\nusage: pynamer [-h] [-r] [-v] [-g] [-m] [-s] [-w] [-f FILENAME] [-o FILENAME] [--version] [projects ...]\r\n\r\nDetermine if project name is available on pypi with the option to 'register' it for future use if available\r\n...\r\n```\r\n\r\n\r\n\r\n## Documentation\r\n\r\n---\r\n\r\n[**Read the Docs**](https://pynamer.readthedocs.io/en/latest/)\r\n\r\n- [**Credits**](https://pynamer.readthedocs.io/en/latest/example.html)\r\n- [**Changelog**](https://pynamer.readthedocs.io/en/latest/changelog.html)\r\n- [**API Reference**](https://pynamer.readthedocs.io/en/latest/autoapi/index.html)\r\n\r\n[**Wiki**](https://github.com/Stephen-RA-King/pynamer/wiki)\r\n\r\n## Planned Future improvements\r\n\r\n- Improve performance of the regeneration of the PyPI simple Repository Index, so this can be run in the background automatically.\r\n\r\n## Meta\r\n\r\n---\r\n\r\n[![Linkedin](assets/linkedin.png)](https://www.linkedin.com/in/sr-king)\r\n[![](assets/github.png)](https://github.com/Stephen-RA-King)\r\n[![PyPI repository](assets/pypi.png)](https://pypi.org/project/pynamer)\r\n[![Docker](assets/docker.png)](https://hub.docker.com/r/sraking/pynamer)\r\n[![](assets/www.png)](https://stephen-ra-king.github.io/justpython/)\r\n[![](assets/email.png)](mailto:sking.github@gmail.com)\r\n\r\nAuthor: Stephen King ([sking.github@gmail.com](mailto:sking.github@gmail.com))\r\n\r\nDistributed under the MIT license. See [![][license-image]][license-url] for more information.\r\n\r\nCreated with Cookiecutter template: [![pydough][pydough-image]][pydough-url] version 1.2.2\r\n\r\nDigital object identifier: [![DOI](https://zenodo.org/badge/631029310.svg)](https://zenodo.org/badge/latestdoi/631029310)\r\n\r\n<!-- Markdown link & img dfn's -->\r\n\r\n[bandit-image]: https://img.shields.io/badge/security-bandit-yellow.svg\r\n[bandit-url]: https://github.com/PyCQA/bandit\r\n[black-image]: https://img.shields.io/badge/code%20style-black-000000.svg\r\n[black-url]: https://github.com/psf/black\r\n[codeclimate-image]: https://api.codeclimate.com/v1/badges/b95fb617fbcd469ccfc3/maintainability\r\n[codeclimate-url]: https://codeclimate.com/github/Stephen-RA-King/pynamer/maintainability\r\n[codeclimate-url]: https://codeclimate.com/github/Stephen-RA-King/pynamer/maintainability\r\n[codecov-image]: https://codecov.io/gh/Stephen-RA-King/pynamer/branch/main/graph/badge.svg\r\n[codecov-url]: https://app.codecov.io/gh/Stephen-RA-King/pynamer\r\n[codefactor-image]: https://www.codefactor.io/repository/github/Stephen-RA-King/pynamer/badge\r\n[codefactor-url]: https://www.codefactor.io/repository/github/Stephen-RA-King/pynamer\r\n[codeql-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/github-code-scanning/codeql/badge.svg\r\n[codeql-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/github-code-scanning/codeql\r\n[commitizen-image]: https://img.shields.io/badge/commitizen-friendly-brightgreen.svg\r\n[commitizen-url]: http://commitizen.github.io/cz-cli/\r\n[conventional-commits-image]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg?style=flat-square\r\n[conventional-commits-url]: https://conventionalcommits.org\r\n[deepsource-image]: https://app.deepsource.com/gh/Stephen-RA-King/pynamer.svg/?label=active+issues&show_trend=true&token=SGo-Vr17NUYVQaEWkU9rBb6Y\r\n[deepsource-url]: https://app.deepsource.com/gh/Stephen-RA-King/pynamer/?ref=repository-badge\r\n[docker-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/docker-image.yml/badge.svg\r\n[docker-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/docker-image.yml\r\n[downloads-image]: https://static.pepy.tech/personalized-badge/pynamer?period=total&units=international_system&left_color=black&right_color=blue&left_text=Downloads\r\n[downloads-url]: https://pepy.tech/project/pynamer\r\n[format-image]: https://img.shields.io/pypi/format/pynamer\r\n[isort-image]: https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336\r\n[isort-url]: https://github.com/pycqa/isort/\r\n[lgtm-alerts-image]: https://img.shields.io/lgtm/alerts/g/Stephen-RA-King/pynamer.svg?logo=lgtm&logoWidth=18\r\n[lgtm-alerts-url]: https://lgtm.com/projects/g/Stephen-RA-King/pynamer/alerts/\r\n[lgtm-quality-image]: https://img.shields.io/lgtm/grade/python/g/Stephen-RA-King/pynamer.svg?logo=lgtm&logoWidth=18\r\n[lgtm-quality-url]: https://lgtm.com/projects/g/Stephen-RA-King/pynamer/context:python\r\n[license-image]: https://img.shields.io/pypi/l/pynamer\r\n[license-url]: https://github.com/Stephen-RA-King/pynamer/blob/main/LICENSE\r\n[mypy-image]: http://www.mypy-lang.org/static/mypy_badge.svg\r\n[mypy-url]: http://mypy-lang.org/\r\n[openssf-image]: https://api.securityscorecards.dev/projects/github.com/Stephen-RA-King/pynamer/badge\r\n[openssf-url]: https://api.securityscorecards.dev/projects/github.com/Stephen-RA-King/pynamer\r\n[pipx-url]: https://pypa.github.io/pipx/\r\n[pre-commit-image]: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white\r\n[pre-commit-url]: https://github.com/pre-commit/pre-commit\r\n[pre-commit.ci-image]: https://results.pre-commit.ci/badge/github/Stephen-RA-King/pynamer/main.svg\r\n[pre-commit.ci-url]: https://results.pre-commit.ci/latest/github/Stephen-RA-King/pynamer/main\r\n[pydough-image]: https://img.shields.io/badge/pydough-2023-orange\r\n[pydough-url]: https://github.com/Stephen-RA-King/pydough\r\n[pypi-image]: https://img.shields.io/pypi/v/pynamer.svg\r\n[pypi-url]: https://pypi.org/project/pynamer/\r\n[python-version-image]: https://img.shields.io/pypi/pyversions/pynamer\r\n[readthedocs-image]: https://readthedocs.org/projects/pynamer/badge/?version=latest\r\n[readthedocs-url]: https://pynamer.readthedocs.io/en/latest/?badge=latest\r\n[status-image]: https://img.shields.io/pypi/status/pynamer.svg\r\n[tests-image]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/tests.yml/badge.svg\r\n[tests-url]: https://github.com/Stephen-RA-King/pynamer/actions/workflows/tests.yml\r\n[wiki]: https://github.com/Stephen-RA-King/pynamer/wiki\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Utility to find an available package name in the PyPI repository and register it",
"version": "2.1.8",
"project_urls": {
"Bug Tracker": "https://github.com/Stephen-RA-King/pynamer/issues",
"CI": "https://github.com/Stephen-RA-King/pynamer/actions",
"Documentation": "https://pynamer.readthedocs.io/en/latest/",
"Download": "https://github.com/Stephen-RA-King/pynamer/archive/refs/heads/main.zip",
"Homepage": "https://github.com/Stephen-RA-King/pynamer",
"Release Notes": "https://github.com/Stephen-RA-King/pynamer/releases",
"Source Code": "https://github.com/Stephen-RA-King/pynamer/"
},
"split_keywords": [
"available-on-pypi",
"pip-search",
"packaging",
"naming",
"name-generation",
"names",
"pypi",
"packaging",
"naming-conventions"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "748f8f4bd96467e43d90ce77c9c08abe9fc9c93d236c5fdf20dc34c15d81bbcd",
"md5": "607e7a8c4e5e2f16fc434613ecb4582c",
"sha256": "c9f34776898a9977564f72235f9725e1cff262e7c2c023a9d55abe8b332233ad"
},
"downloads": -1,
"filename": "pynamer-2.1.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "607e7a8c4e5e2f16fc434613ecb4582c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 24757,
"upload_time": "2023-07-01T15:02:09",
"upload_time_iso_8601": "2023-07-01T15:02:09.836543Z",
"url": "https://files.pythonhosted.org/packages/74/8f/8f4bd96467e43d90ce77c9c08abe9fc9c93d236c5fdf20dc34c15d81bbcd/pynamer-2.1.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "07174f31855510287f517622f9a106bfc358a473ec62738fffdb6f57be46737e",
"md5": "4794eeabe322473ed25546ccb4d0fd5d",
"sha256": "f3d4d2948bd6bd9a3b4a695c22b075ed60de33dfec8d5566094161b135b62ee8"
},
"downloads": -1,
"filename": "pynamer-2.1.8.tar.gz",
"has_sig": false,
"md5_digest": "4794eeabe322473ed25546ccb4d0fd5d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 41458,
"upload_time": "2023-07-01T15:02:11",
"upload_time_iso_8601": "2023-07-01T15:02:11.600753Z",
"url": "https://files.pythonhosted.org/packages/07/17/4f31855510287f517622f9a106bfc358a473ec62738fffdb6f57be46737e/pynamer-2.1.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-07-01 15:02:11",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Stephen-RA-King",
"github_project": "pynamer",
"travis_ci": false,
"coveralls": true,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "pynamer"
}