-
-
Notifications
You must be signed in to change notification settings - Fork 25
Fail gracefully at parsing setup.py with no deps. #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
93c803d
1fb0aff
6744983
01e839c
25fc03f
88be605
4e0cae5
aa64f26
5dadfb3
093275f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,8 +7,10 @@ | |
| # See https://aboutcode.org for more information about nexB OSS projects. | ||
| # | ||
|
|
||
| import ast | ||
| import operator | ||
| import os | ||
| import re | ||
| import tarfile | ||
| from typing import Dict | ||
| from typing import Generator | ||
|
|
@@ -281,7 +283,7 @@ def get_requirements_from_python_manifest( | |
| """ | ||
| Return a list of parsed requirements from the ``sdist_location`` sdist location | ||
| """ | ||
| # Look in requirements file if and only if thy are refered in setup.py or setup.cfg | ||
| # Look in requirements file if and only if they are refered in setup.py or setup.cfg | ||
| # And no deps have been yielded by requirements file. | ||
| requirements = list( | ||
| get_reqs_from_requirements_file_in_sdist( | ||
|
|
@@ -299,11 +301,48 @@ def get_requirements_from_python_manifest( | |
| ) | ||
|
|
||
| else: | ||
| # We should not raise exception here as we may have a setup.py that does not | ||
| # have any dependencies. We should not fail in this case. | ||
| raise Exception( | ||
| f"Unable to collect setup.py dependencies securely: {setup_py_location}" | ||
| ) | ||
| # Do not raise exception here as we may have a setup.py that does not | ||
| # have any dependencies. | ||
| with (open(setup_py_location)) as sf: | ||
| file_contents = sf.read() | ||
| node = ast.parse(file_contents) | ||
| setup_fct = [ | ||
| elem | ||
| for elem in ast.walk(node) | ||
| if ( | ||
| isinstance(elem, ast.Expr) | ||
| and isinstance(elem.value, ast.Call) | ||
| and isinstance(elem.value.func, ast.Name) | ||
| and elem.value.func.id == "setup" | ||
| ) | ||
| ] | ||
| if len(setup_fct) == 0: | ||
| raise Exception( | ||
| f"Unable to collect setup.py dependencies securely: {setup_py_location}" | ||
| ) | ||
| if len(setup_fct) > 1: | ||
| print( | ||
| f"Warning: identified multiple definitions of 'setup()' in {setup_py_location}, " | ||
| "defaulting to the first occurrence" | ||
| ) | ||
| setup_fct = setup_fct[0] | ||
| install_requires = [ | ||
| k.value for k in setup_fct.value.keywords if k.arg == "install_requires" | ||
| ] | ||
| if len(install_requires) == 0: | ||
| raise Exception( | ||
| f"Unable to collect setup.py dependencies securely: {setup_py_location}" | ||
| ) | ||
| if len(install_requires) > 1: | ||
| print( | ||
| f"Warning: identified multiple definitions of 'install_requires' in " | ||
| "{setup_py_location}, defaulting to the first occurrence" | ||
| ) | ||
| install_requires = install_requires[0].elts | ||
| if len(install_requires) != 0: | ||
| raise Exception( | ||
| f"Unable to collect setup.py dependencies securely: {setup_py_location}" | ||
| ) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are missing one case which is when there are install_requires that are processed dynamically commonly either loaded from a requirements file (that we do not handle and needs "insecure loading") or from a variable (that we handle and that would be regression See https://github.com/nexB/python-inspector/blob/9e765ec50ed4c30eca20ef56686c9bcbe07fb89e/src/_packagedcode/pypi_setup_py.py#L155 ) But I ran a test with this setup.py and it works, so there is no issue: from distutils.core import setup
reqs = ["boolean.py"]
setup(
name="foo",
version="0.3.0",
install_requires=reqs,
) |
||
|
|
||
|
|
||
| DEFAULT_ENVIRONMENT = utils_pypi.Environment.from_pyver_and_os( | ||
|
|
||
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2831,12 +2831,12 @@ | |
| "type": "pypi", | ||
| "namespace": null, | ||
| "name": "openpyxl", | ||
| "version": "3.1.0", | ||
| "version": "3.1.1", | ||
| "qualifiers": {}, | ||
| "subpath": null, | ||
| "primary_language": "Python", | ||
| "description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html", | ||
| "release_date": "2023-01-31T14:40:28", | ||
| "release_date": "2023-02-13T16:51:26", | ||
| "parties": [ | ||
| { | ||
| "type": "person", | ||
|
|
@@ -2860,11 +2860,11 @@ | |
| "Programming Language :: Python :: 3.9" | ||
| ], | ||
| "homepage_url": "https://openpyxl.readthedocs.io", | ||
| "download_url": "https://files.pythonhosted.org/packages/0d/89/f78a9a895e221ec8b13ae7f9495f340a0fb43563b13e2891b5df134f20ea/openpyxl-3.1.0-py2.py3-none-any.whl", | ||
| "size": 250043, | ||
| "download_url": "https://files.pythonhosted.org/packages/9e/57/1d3c2ce7f6f783be9b21569fc468a9f3660e35cc17017abfbbc26d3bd061/openpyxl-3.1.1-py2.py3-none-any.whl", | ||
| "size": 249839, | ||
| "sha1": null, | ||
| "md5": "66351b61736b19d3c88cd108908447d1", | ||
| "sha256": "24d7d361025d186ba91eff58135d50855cf035a84371b891e58fb6eb5125660f", | ||
| "md5": "864e1e1ea061fe056ade64f4e7bbaf22", | ||
| "sha256": "a0266e033e65f33ee697254b66116a5793c15fc92daf64711080000df4cfe0a8", | ||
| "sha512": null, | ||
| "bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues", | ||
| "code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl", | ||
|
|
@@ -2884,20 +2884,20 @@ | |
| "dependencies": [], | ||
| "repository_homepage_url": null, | ||
| "repository_download_url": null, | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json", | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json", | ||
| "datasource_id": null, | ||
| "purl": "pkg:pypi/[email protected].0" | ||
| "purl": "pkg:pypi/[email protected].1" | ||
| }, | ||
| { | ||
| "type": "pypi", | ||
| "namespace": null, | ||
| "name": "openpyxl", | ||
| "version": "3.1.0", | ||
| "version": "3.1.1", | ||
| "qualifiers": {}, | ||
| "subpath": null, | ||
| "primary_language": "Python", | ||
| "description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html", | ||
| "release_date": "2023-01-31T14:40:31", | ||
| "release_date": "2023-02-13T16:51:28", | ||
| "parties": [ | ||
| { | ||
| "type": "person", | ||
|
|
@@ -2921,11 +2921,11 @@ | |
| "Programming Language :: Python :: 3.9" | ||
| ], | ||
| "homepage_url": "https://openpyxl.readthedocs.io", | ||
| "download_url": "https://files.pythonhosted.org/packages/3d/73/bb87810cdde809f69fef11d31e77297894e58710d47626dc5e5b3ff8f92a/openpyxl-3.1.0.tar.gz", | ||
| "size": 186306, | ||
| "download_url": "https://files.pythonhosted.org/packages/10/bf/950ea7896f3c42ab04073cd2903f0a190ba77ef28bdf76191f6f86373712/openpyxl-3.1.1.tar.gz", | ||
| "size": 185802, | ||
| "sha1": null, | ||
| "md5": "b7ba597b801b9a102f27599b2fa227b3", | ||
| "sha256": "eccedbe1cdd8b2494057e73959b496821141038dbb7eb9266ea59e3f34208231", | ||
| "md5": "0b1a5d776707ef471810f61c7bf77a2d", | ||
| "sha256": "f06d44e2c973781068bce5ecf860a09bcdb1c7f5ce1facd5e9aa82c92c93ae72", | ||
| "sha512": null, | ||
| "bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues", | ||
| "code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl", | ||
|
|
@@ -2945,9 +2945,9 @@ | |
| "dependencies": [], | ||
| "repository_homepage_url": null, | ||
| "repository_download_url": null, | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json", | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json", | ||
| "datasource_id": null, | ||
| "purl": "pkg:pypi/[email protected].0" | ||
| "purl": "pkg:pypi/[email protected].1" | ||
| }, | ||
| { | ||
| "type": "pypi", | ||
|
|
@@ -5025,7 +5025,7 @@ | |
| { | ||
| "key": "openpyxl", | ||
| "package_name": "openpyxl", | ||
| "installed_version": "3.1.0", | ||
| "installed_version": "3.1.1", | ||
| "dependencies": [ | ||
| { | ||
| "key": "et-xmlfile", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2831,12 +2831,12 @@ | |
| "type": "pypi", | ||
| "namespace": null, | ||
| "name": "openpyxl", | ||
| "version": "3.1.0", | ||
| "version": "3.1.1", | ||
| "qualifiers": {}, | ||
| "subpath": null, | ||
| "primary_language": "Python", | ||
| "description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html", | ||
| "release_date": "2023-01-31T14:40:28", | ||
| "release_date": "2023-02-13T16:51:26", | ||
| "parties": [ | ||
| { | ||
| "type": "person", | ||
|
|
@@ -2860,11 +2860,11 @@ | |
| "Programming Language :: Python :: 3.9" | ||
| ], | ||
| "homepage_url": "https://openpyxl.readthedocs.io", | ||
| "download_url": "https://files.pythonhosted.org/packages/0d/89/f78a9a895e221ec8b13ae7f9495f340a0fb43563b13e2891b5df134f20ea/openpyxl-3.1.0-py2.py3-none-any.whl", | ||
| "size": 250043, | ||
| "download_url": "https://files.pythonhosted.org/packages/9e/57/1d3c2ce7f6f783be9b21569fc468a9f3660e35cc17017abfbbc26d3bd061/openpyxl-3.1.1-py2.py3-none-any.whl", | ||
| "size": 249839, | ||
| "sha1": null, | ||
| "md5": "66351b61736b19d3c88cd108908447d1", | ||
| "sha256": "24d7d361025d186ba91eff58135d50855cf035a84371b891e58fb6eb5125660f", | ||
| "md5": "864e1e1ea061fe056ade64f4e7bbaf22", | ||
| "sha256": "a0266e033e65f33ee697254b66116a5793c15fc92daf64711080000df4cfe0a8", | ||
| "sha512": null, | ||
| "bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues", | ||
| "code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl", | ||
|
|
@@ -2884,20 +2884,20 @@ | |
| "dependencies": [], | ||
| "repository_homepage_url": null, | ||
| "repository_download_url": null, | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json", | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json", | ||
| "datasource_id": null, | ||
| "purl": "pkg:pypi/[email protected].0" | ||
| "purl": "pkg:pypi/[email protected].1" | ||
| }, | ||
| { | ||
| "type": "pypi", | ||
| "namespace": null, | ||
| "name": "openpyxl", | ||
| "version": "3.1.0", | ||
| "version": "3.1.1", | ||
| "qualifiers": {}, | ||
| "subpath": null, | ||
| "primary_language": "Python", | ||
| "description": "A Python library to read/write Excel 2010 xlsx/xlsm files\n.. image:: https://coveralls.io/repos/bitbucket/openpyxl/openpyxl/badge.svg?branch=default\n :target: https://coveralls.io/bitbucket/openpyxl/openpyxl?branch=default\n :alt: coverage status\n\nIntroduction\n------------\n\nopenpyxl is a Python library to read/write Excel 2010 xlsx/xlsm/xltx/xltm files.\n\nIt was born from lack of existing library to read/write natively from Python\nthe Office Open XML format.\n\nAll kudos to the PHPExcel team as openpyxl was initially based on PHPExcel.\n\n\nSecurity\n--------\n\nBy default openpyxl does not guard against quadratic blowup or billion laughs\nxml attacks. To guard against these attacks install defusedxml.\n\nMailing List\n------------\n\nThe user list can be found on http://groups.google.com/group/openpyxl-users\n\n\nSample code::\n\n from openpyxl import Workbook\n wb = Workbook()\n\n # grab the active worksheet\n ws = wb.active\n\n # Data can be assigned directly to cells\n ws['A1'] = 42\n\n # Rows can also be appended\n ws.append([1, 2, 3])\n\n # Python types will automatically be converted\n import datetime\n ws['A2'] = datetime.datetime.now()\n\n # Save the file\n wb.save(\"sample.xlsx\")\n\n\nDocumentation\n-------------\n\nThe documentation is at: https://openpyxl.readthedocs.io\n\n* installation methods\n* code examples\n* instructions for contributing\n\nRelease notes: https://openpyxl.readthedocs.io/en/stable/changes.html", | ||
| "release_date": "2023-01-31T14:40:31", | ||
| "release_date": "2023-02-13T16:51:28", | ||
| "parties": [ | ||
| { | ||
| "type": "person", | ||
|
|
@@ -2921,11 +2921,11 @@ | |
| "Programming Language :: Python :: 3.9" | ||
| ], | ||
| "homepage_url": "https://openpyxl.readthedocs.io", | ||
| "download_url": "https://files.pythonhosted.org/packages/3d/73/bb87810cdde809f69fef11d31e77297894e58710d47626dc5e5b3ff8f92a/openpyxl-3.1.0.tar.gz", | ||
| "size": 186306, | ||
| "download_url": "https://files.pythonhosted.org/packages/10/bf/950ea7896f3c42ab04073cd2903f0a190ba77ef28bdf76191f6f86373712/openpyxl-3.1.1.tar.gz", | ||
| "size": 185802, | ||
| "sha1": null, | ||
| "md5": "b7ba597b801b9a102f27599b2fa227b3", | ||
| "sha256": "eccedbe1cdd8b2494057e73959b496821141038dbb7eb9266ea59e3f34208231", | ||
| "md5": "0b1a5d776707ef471810f61c7bf77a2d", | ||
| "sha256": "f06d44e2c973781068bce5ecf860a09bcdb1c7f5ce1facd5e9aa82c92c93ae72", | ||
| "sha512": null, | ||
| "bug_tracking_url": "https://foss.heptapod.net/openpyxl/openpyxl/-/issues", | ||
| "code_view_url": "https://foss.heptapod.net/openpyxl/openpyxl", | ||
|
|
@@ -2945,9 +2945,9 @@ | |
| "dependencies": [], | ||
| "repository_homepage_url": null, | ||
| "repository_download_url": null, | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.0/json", | ||
| "api_data_url": "https://pypi.org/pypi/openpyxl/3.1.1/json", | ||
| "datasource_id": null, | ||
| "purl": "pkg:pypi/[email protected].0" | ||
| "purl": "pkg:pypi/[email protected].1" | ||
| }, | ||
| { | ||
| "type": "pypi", | ||
|
|
@@ -4976,7 +4976,7 @@ | |
| "pkg:pypi/[email protected]", | ||
| "pkg:pypi/[email protected]", | ||
| "pkg:pypi/[email protected]", | ||
| "pkg:pypi/[email protected].0", | ||
| "pkg:pypi/[email protected].1", | ||
| "pkg:pypi/[email protected]", | ||
| "pkg:pypi/[email protected]" | ||
| ] | ||
|
|
@@ -5066,7 +5066,7 @@ | |
| "dependencies": [] | ||
| }, | ||
| { | ||
| "package": "pkg:pypi/[email protected].0", | ||
| "package": "pkg:pypi/[email protected].1", | ||
| "dependencies": [ | ||
| "pkg:pypi/[email protected]" | ||
| ] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| """ | ||
| Copyright 2018 Matthew Aynalem | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| """ | ||
| from distutils.core import setup | ||
|
|
||
| from setuptools import find_packages | ||
|
|
||
| setup( | ||
| name="packer.py", | ||
| version="0.3.0", | ||
| author="Matthew Aynalem", | ||
| author_email="[email protected]", | ||
| packages=["packerpy"], | ||
| url="https://github.com/mayn/packer.py", | ||
| license="Apache License 2.0", | ||
| description="packer.py - python library to run hashicorp packer CLI commands", | ||
| keywords="hashicorp packer", | ||
| long_description=open("README.rst").read(), | ||
| install_requires=[], | ||
| classifiers=[ | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Programming Language :: Python :: 2", | ||
| "Programming Language :: Python :: 2.7", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.4", | ||
| "Programming Language :: Python :: 3.5", | ||
| "Programming Language :: Python :: 3.6", | ||
| ], | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| """ | ||
| Copyright 2018 Matthew Aynalem | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| """ | ||
| from distutils.core import setup | ||
|
|
||
| from setuptools import find_packages | ||
|
|
||
| setup( | ||
| name="packer.py", | ||
| version="0.3.0", | ||
| author="Matthew Aynalem", | ||
| author_email="[email protected]", | ||
| packages=["packerpy"], | ||
| url="https://github.com/mayn/packer.py", | ||
| license="Apache License 2.0", | ||
| description="packer.py - python library to run hashicorp packer CLI commands", | ||
| keywords="hashicorp packer", | ||
| long_description=open("README.rst").read(), | ||
| classifiers=[ | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Programming Language :: Python :: 2", | ||
| "Programming Language :: Python :: 2.7", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.4", | ||
| "Programming Language :: Python :: 3.5", | ||
| "Programming Language :: Python :: 3.6", | ||
| ], | ||
| ) |
Uh oh!
There was an error while loading. Please reload this page.