{ "info": { "author": "Matt Bullock", "author_email": "matt.s.b.42@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Natural Language :: English", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Topic :: System :: Software Distribution", "Topic :: Utilities" ], "description": "###########\npypi-parker\n###########\n\n.. image:: https://img.shields.io/pypi/v/pypi-parker.svg\n :target: https://pypi.python.org/pypi/pypi-parker\n :alt: Latest Version\n\n.. image:: https://readthedocs.org/projects/pypi-parker/badge/\n :target: https://pypi-parker.readthedocs.io/en/stable/\n :alt: Documentation Status\n\n.. image:: https://travis-ci.org/mattsb42/pypi-parker.svg?branch=master\n :target: https://travis-ci.org/mattsb42/pypi-parker\n\n``pypi-parker`` lets you easily park package names on PyPI to protect users of your packages\nfrom typosquatting.\n\n`Typosquatting`_ is a problem: in general, but also on PyPI. There are efforts being taken\nby pypa to `protect core library names`_, but this does not (and really cannot and probably\nshould not attempt to) help individual package owners. For example, ``reqeusts`` rather than\n``requests``, or ``crytpography`` rather than ``cryptography``. Because of the self-serve\nnature of PyPI, individual package owners are left to their own devices to protect their users.\nThis is not inherently a problem: in my opinion this is a reasonable balance to keep the barrier\nto entry for publishing PyPI package low. However, tooling should exist to make it easy for\npackage owners to protect their users. That is what ``pypi-parker`` sets out to do.\n\nObjectives\n**********\n* Self-serve is a good thing. Let's not try and get rid of that. Work with it instead.\n* Package owners should be able to easily protect users of their packages from malicious typosquatting.\n* It should be easy for package owners to introduce ``pypi-parker`` into their existing package builds.\n* Parked packages should:\n\n * fail fast and not `do anything else`_\n * be self documenting, both in metadata and in source\n * contain functionally complete ``setup.py`` files to allow whitelisted external validators to work\n\n * The `readme_renderer`_ validator is run on each generated package before building.\n\nWhat does it do?\n****************\n``pypi-parker`` provides a custom distutils command ``park`` that interprets a provided config\nfile to generate empty Python package source distributables. These packages will always throw\nan ImportError when someone tries to install them. You can customize the ImportError message\nto help guide users to the correct package.\n\nUsing the Config File\n=====================\n``pypi-parker`` uses a `configparser`_ config file to determine what packages to generate and what metadata\nto include with each.\n\nThere are two special sections: ``names`` and ``DEFAULT``.\n\n* ``DEFAULT`` : Values in ``DEFAULT`` are used if that key is not present in a package-specific section.\n* ``names`` : Keys in ``names`` are interpretted as package names that should all use only the values in ``DEFAULT``.\n\nUnless otherwise indicated, all key/value pairs loaded for each package are loaded directly\ninto the ``setup`` call for that generated package.\n\nSpecial Packages\n----------------\n\nIf you want to specify custom values for specific packages, you can add additional sections\nfor those packages. For any sections found aside from ``DEFAULT`` and ``names``, the section\nname is used as the package name.\n\nSpecial Section Keys\n--------------------\n\n* ``description_keys`` : This line-delimited value is used with ``str.format`` to build the\n final ``description`` value.\n* ``classifiers`` : If multiple lines are provided for this value, and each line will be treated\n as a separate entry.\n* ``description`` :\n\n * This value cannot contain multiple lines.\n * This value is also used for the ``ImportError`` message in the generated ``setup.py``.\n\nDefault Values\n==============\n* **config file name** : ``park.cfg``\n* **classifiers** : ``Development Status :: 7 - Inactive``\n* **description** : ``parked using pypi-parker``\n* **long_description** :\n\n .. code-block:: text\n\n This package has been parked either for future use or to protect against typo misdirection.\n If you believe that it has been parked in error, please contact the package owner.\n\nExample\n-------\n\n**park.cfg**\n\n.. code-block:: ini\n\n [DEFAULT]\n author: mattsb42\n\n [my-package-name]\n url: https://github.com/mattsb42/my-package-name\n description: This package is parked by {author}. See {url} for more information.\n description_keys:\n author\n url\n classifiers:\n Development Status :: 7 - Inactive\n Operating System :: OS Independent\n Topic :: Utilities\n\n**Generated setup.py**\n\n.. code-block:: python\n\n from setuptools import setup\n\n args = ' '.join(sys.argv).strip()\n if not any(args.endswith(suffix) for suffix in ['setup.py sdist', 'setup.py check -r -s']):\n raise ImportError('This package is parked by mattsb42. See https://github.com/mattsb42/my-package-name for more information.')\n\n setup(\n author='mattsb42',\n url='https://github.com/mattsb42/my-package-name',\n description='This package is parked by mattsb42. See https://github.com/mattsb42/my-package-name for more information.',\n classifiers=[\n 'Development Status :: 7 - Inactive',\n 'Operating System :: OS Independent',\n 'Topic :: Utilities'\n ]\n )\n\n**Install attempt**\n\n.. code-block:: sh\n\n $ pip install my-package-name\n Processing my-package-name\n Complete output from command python setup.py egg_info:\n Traceback (most recent call last):\n File \"\", line 1, in \n File \"/tmp/pip-oma2zoy6-build/setup.py\", line 6, in \n raise ImportError('This package is parked by mattsb42. See https://github.com/mattsb42/my-package-name for more information.',)\n ImportError: This package is parked by mattsb42. See https://github.com/mattsb42/my-package-name for more information.\n\n ----------------------------------------\n Command \"python setup.py egg_info\" failed with error code 1 in /tmp/pip-oma2zoy6-build/\n\nOk, how do I use it?\n********************\n\n1. Install ``pypi-parker`` wherever you will be running your builds.\n\n .. code-block:: sh\n\n pip install pypi-parker\n\n2. Define the package names you want to target in your config file.\n3. Call ``setup.py`` with the ``park`` command.\n\n .. code-block:: sh\n\n python setup.py park\n\n * If you want to use a custom config file, specify it with the ``park-config`` argument.\n\n .. code-block:: sh\n\n python setup.py park --park-config={filename}\n\n4. Upload the resulting contents of ``dist`` to your package index of choice.\n\n**Example tox configuration**\n\n.. code-block:: ini\n\n [testenv:park]\n basepython = python3.6\n deps =\n setuptools\n pypi-parker\n commands = python setup.py park\n\n.. _configparser: https://docs.python.org/3/library/configparser.html\n.. _do anything else: http://incolumitas.com/2016/06/08/typosquatting-package-managers/\n.. _readme_renderer: https://github.com/pypa/readme_renderer\n.. _Typosquatting: https://en.wikipedia.org/wiki/Typosquatting\n.. _protect core library names: https://github.com/pypa/warehouse/issues/2151\n\n\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mattsb42/pypi-parker", "keywords": "pypi warehouse distutils typosquating", "license": "Apache License 2.0", "maintainer": "", "maintainer_email": "", "name": "pypi-parker", "package_url": "https://pypi.org/project/pypi-parker/", "platform": "", "project_url": "https://pypi.org/project/pypi-parker/", "project_urls": { "Homepage": "https://github.com/mattsb42/pypi-parker" }, "release_url": "https://pypi.org/project/pypi-parker/0.1.2/", "requires_dist": [ "readme-renderer (>=17.2)" ], "requires_python": "", "summary": "", "version": "0.1.2" }, "last_serial": 3235290, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "6c67519b49fca6d6baaaa478bf68909c", "sha256": "db53980bb5264f11bcc6467b3ac2c931ab717773e73cee34bc3ef8a27977f35a" }, "downloads": -1, "filename": "pypi_parker-0.1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6c67519b49fca6d6baaaa478bf68909c", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18148, "upload_time": "2017-10-02T04:23:05", "url": "https://files.pythonhosted.org/packages/dc/75/63e54b628dc17e12373610f12ba7e03f1e5c4fcdbc71e45b48f2b55cff15/pypi_parker-0.1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "50a895f4fb67733ac4e5b5d7531b5dde", "sha256": "1da241ea868db9521cdcadb99cfea50e27d16babcf91319aaa161b4969277b12" }, "downloads": -1, "filename": "pypi-parker-0.1.0.tar.gz", "has_sig": false, "md5_digest": "50a895f4fb67733ac4e5b5d7531b5dde", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11705, "upload_time": "2017-10-02T04:23:08", "url": "https://files.pythonhosted.org/packages/2b/8b/0f291b9f254f8886eb700907151d6cc6a354c911c21e5dd9b8e5b7fc5601/pypi-parker-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "8fb99cb5736d631cca060c94d7c32258", "sha256": "e42f35f71ce93ec0b0864a879ca64886c3e8d7aaa8e3cc5added419a5d79cca9" }, "downloads": -1, "filename": "pypi_parker-0.1.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "8fb99cb5736d631cca060c94d7c32258", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18268, "upload_time": "2017-10-09T03:46:51", "url": "https://files.pythonhosted.org/packages/61/f3/516405dbf3a65d1d8c925194e7de5abfeae5edae488b30d635a685f24289/pypi_parker-0.1.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c7774b2f788650b36462b5ac410f60f7", "sha256": "9c15dc3e983c1bcd14867f0c3231dd44b41d057947bcf72651ca70ce3a72ce0a" }, "downloads": -1, "filename": "pypi-parker-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c7774b2f788650b36462b5ac410f60f7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11865, "upload_time": "2017-10-09T03:46:53", "url": "https://files.pythonhosted.org/packages/78/78/46c617b2e1f22d718787d76870cf162386f633cfeb95ce9e5ac50abb37c9/pypi-parker-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "93af8fa6ed8ce141626200428a22e4a5", "sha256": "6da5ce5bcf3618ab3a86e3ae8310348a0fe75e88438f4f9bfbf0abf8fb7491ec" }, "downloads": -1, "filename": "pypi_parker-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "93af8fa6ed8ce141626200428a22e4a5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18267, "upload_time": "2017-10-09T04:03:50", "url": "https://files.pythonhosted.org/packages/d5/87/950f91d500dcde81da51d2a7abbdcd606406dfc7e00f62a11c543958dd0b/pypi_parker-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "136ac292082da25060e051d2622cc39d", "sha256": "ddda596ea3f9e0a6a5da911dfe2dfe1a5cefca0c6920b17c1c93068db2c28955" }, "downloads": -1, "filename": "pypi-parker-0.1.2.tar.gz", "has_sig": false, "md5_digest": "136ac292082da25060e051d2622cc39d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11887, "upload_time": "2017-10-09T04:03:51", "url": "https://files.pythonhosted.org/packages/b0/61/af2176d7dd54be657b0e91a869ce30337978ecf8ac5f071a2157bef2200a/pypi-parker-0.1.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "93af8fa6ed8ce141626200428a22e4a5", "sha256": "6da5ce5bcf3618ab3a86e3ae8310348a0fe75e88438f4f9bfbf0abf8fb7491ec" }, "downloads": -1, "filename": "pypi_parker-0.1.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "93af8fa6ed8ce141626200428a22e4a5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 18267, "upload_time": "2017-10-09T04:03:50", "url": "https://files.pythonhosted.org/packages/d5/87/950f91d500dcde81da51d2a7abbdcd606406dfc7e00f62a11c543958dd0b/pypi_parker-0.1.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "136ac292082da25060e051d2622cc39d", "sha256": "ddda596ea3f9e0a6a5da911dfe2dfe1a5cefca0c6920b17c1c93068db2c28955" }, "downloads": -1, "filename": "pypi-parker-0.1.2.tar.gz", "has_sig": false, "md5_digest": "136ac292082da25060e051d2622cc39d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11887, "upload_time": "2017-10-09T04:03:51", "url": "https://files.pythonhosted.org/packages/b0/61/af2176d7dd54be657b0e91a869ce30337978ecf8ac5f071a2157bef2200a/pypi-parker-0.1.2.tar.gz" } ] }