F. Eugene Aumson e61f23d001
Migrate Python libraries to v3 (#2284)
* .gitignore migrations/0x_ganache_snapshot

* .gitignore new-ish Python contract wrappers

These should have been added back when we started generating these
wrappers.

* rm superfluous contract artifact in Python package

All of the contract artifacts were removed from the Python package
recently, because now they're copied from the monorepo/packages area as
an automated build step.  Somehow this one artifact slipped through the
cracks.

* Eliminate circular dependency

This was preventing the Exchange wrapper from ever importing its
validator!

* Improve output of monorepo-level parallel script

- Capture stderr (and have it included in stdout) so that it doesn't
leak onto the console for commands that didn't actually fail.

- Include all error output in the Exception object (eliminate print
statement).

* Silence new versions of linters

Newer versions care about this stuff.  Old versions didn't, and we don't
either.

* Support Rich Reverts via Web3.py middleware

* Fix bug in generated wrappers' bytes handling

`bytes.fromhex(bytes.decode('utf-8')` is just plain wrong.  It would
work for some cases, but is not working when trying to fill orders with
the latest Exchange contract.

* Migrate to Exchange v3

* Fix typo in DevUtils documentation

* Include new contracts in docs

* Re-enable Python checks in CI

* Accept strings for bytes

* Fix CircleCI build artifacts for gen'd python

I swear the previous way was working before, but it wasn't working now,
so this fixes it.

* Accept a provider OR a Web3 object

In various places.  This allows the caller to install middleware (which
in web3.py is installed on a Web3 object, not on a provider) before
executing any RPC calls, which is important for the case where one wants
to produce signatures locally before submitting to a remote node.

* wrapper base: don't assume there are accounts

* Eliminate some inline linter directives

* make CHANGELOGs be REVERSE chronological

* Update CHANGELOG entries and bump version numbers

* @0x/contract-addresses: Put addr's in JSON, not TS

This allows easier consumption by other languages.  (Specifically, it
eliminates the overhead of keeping the Python addresses package in sync
with the TypeScript one.)

* sra_client.py: incl. docker in `./setup.py clean`

* sra_client.py: Migrate to protocol v3

Removed script that existed only to exclude runs of sra_client builds
(parallel_without_sra_client).  Now `parallel` is used by CI,
re-including sra_client in CI checks.

* abi-gen/templates/Py: clarify if/else logic

In response to
https://github.com/0xProject/0x-monorepo/pull/2284#discussion_r342200906

* sra_client.py: Update CHANGELOG and bump version

* contract_addresses/setup.py: rm unnecessary rm

* json_schemas.py: corrections to dev dependencies

* In tests against deployment, also run doctests

* contract_wrappers example: rm xtra Order attribute

Thanks to @steveklebanoff for catching this.
https://github.com/0xProject/0x-monorepo/pull/2284#pullrequestreview-312065368
2019-11-05 23:04:29 -05:00

243 lines
7.6 KiB
Python
Executable File

#!/usr/bin/env python
"""setuptools module for order_utils package."""
# pylint: disable=import-outside-toplevel
# we import things outside of top-level because 3rd party libs may not yet be
# installed when you invoke this script
import subprocess # nosec
from shutil import rmtree
from os import environ, path
from pathlib import Path
from sys import argv, exit # pylint: disable=redefined-builtin
from distutils.command.clean import clean
import distutils.command.build_py
from setuptools import find_packages, setup
from setuptools.command.test import test as TestCommand
class TestCommandExtension(TestCommand):
"""Run pytest tests."""
def run_tests(self):
"""Invoke pytest."""
import pytest
exit(pytest.main(["--doctest-modules", "-rapP"]))
# show short test summary at end ^
class LintCommand(distutils.command.build_py.build_py):
"""Custom setuptools command class for running linters."""
description = "Run linters"
def run(self):
"""Run linter shell commands."""
lint_commands = [
# formatter:
"black --line-length 79 --check --diff src test setup.py".split(),
# style guide checker (formerly pep8):
"pycodestyle src test setup.py".split(),
# docstring style checker:
"pydocstyle src test setup.py".split(),
# static type checker:
"mypy src test setup.py".split(),
# security issue checker:
"bandit -r src ./setup.py".split(),
# general linter:
"pylint src test setup.py".split(),
# pylint takes relatively long to run, so it runs last, to enable
# fast failures.
]
# tell mypy where to find interface stubs for 3rd party libs
environ["MYPYPATH"] = path.join(
path.dirname(path.realpath(argv[0])), "stubs"
)
# HACK(gene): until eth_abi releases
# https://github.com/ethereum/eth-abi/pull/107 , we need to simply
# create an empty file `py.typed` in the eth_abi package directory.
import eth_abi
eth_abi_dir = path.dirname(path.realpath(eth_abi.__file__))
Path(path.join(eth_abi_dir, "py.typed")).touch()
# HACK(gene): until eth_utils fixes
# https://github.com/ethereum/eth-utils/issues/140 , we need to simply
# create an empty file `py.typed` in the eth_abi package directory.
import eth_utils
eth_utils_dir = path.dirname(path.realpath(eth_utils.__file__))
Path(path.join(eth_utils_dir, "py.typed")).touch()
for lint_command in lint_commands:
print(
"Running lint command `", " ".join(lint_command).strip(), "`"
)
subprocess.check_call(lint_command) # nosec
class CleanCommandExtension(clean):
"""Custom command to do custom cleanup."""
def run(self):
"""Run the regular clean, followed by our custom commands."""
super().run()
rmtree("build", ignore_errors=True)
rmtree("dist", ignore_errors=True)
rmtree(".coverage", ignore_errors=True)
rmtree(".eggs", ignore_errors=True)
rmtree(".mypy_cache", ignore_errors=True)
rmtree(".tox", ignore_errors=True)
rmtree(".pytest_cache", ignore_errors=True)
rmtree("src/0x_order_utils.egg-info", ignore_errors=True)
class TestPublishCommand(distutils.command.build_py.build_py):
"""Custom command to publish to test.pypi.org."""
description = (
"Publish dist/* to test.pypi.org. Run sdist & bdist_wheel first."
)
def run(self):
"""Run twine to upload to test.pypi.org."""
subprocess.check_call( # nosec
(
"twine upload --repository-url https://test.pypi.org/legacy/"
+ " --verbose dist/*"
).split()
)
class PublishCommand(distutils.command.build_py.build_py):
"""Custom command to publish to pypi.org."""
description = "Publish dist/* to pypi.org. Run sdist & bdist_wheel first."
def run(self):
"""Run twine to upload to pypi.org."""
subprocess.check_call("twine upload dist/*".split()) # nosec
class PublishDocsCommand(distutils.command.build_py.build_py):
"""Custom command to publish docs to S3."""
description = (
"Publish docs to "
+ "http://0x-order-utils-py.s3-website-us-east-1.amazonaws.com/"
)
def run(self):
"""Run npm package `discharge` to build & upload docs."""
subprocess.check_call("discharge deploy".split()) # nosec
class GanacheCommand(distutils.command.build_py.build_py):
"""Custom command to publish to pypi.org."""
description = "Run ganache daemon to support tests."
def run(self):
"""Run ganache."""
cmd_line = (
"docker run -d -p 8545:8545 0xorg/ganache-cli:2.2.2"
).split()
subprocess.call(cmd_line) # nosec
with open("README.md", "r") as file_handle:
README_MD = file_handle.read()
setup(
name="0x-order-utils",
version="4.0.0",
description="Order utilities for 0x applications",
long_description=README_MD,
long_description_content_type="text/markdown",
url=(
"https://github.com/0xProject/0x-monorepo/tree/development"
"/python-packages/order_utils"
),
author="F. Eugene Aumson",
author_email="feuGeneA@users.noreply.github.com",
cmdclass={
"clean": CleanCommandExtension,
"lint": LintCommand,
"test": TestCommandExtension,
"test_publish": TestPublishCommand,
"publish": PublishCommand,
"publish_docs": PublishDocsCommand,
"ganache": GanacheCommand,
},
install_requires=[
"0x-contract-addresses",
"0x-contract-artifacts",
"0x-json-schemas",
"deprecated",
"web3",
"eth-abi",
"eth_utils",
"mypy_extensions",
],
extras_require={
"dev": [
"0x-contract-wrappers",
"bandit",
"black",
"coverage",
"coveralls",
"mypy",
"mypy_extensions",
"pycodestyle",
"pydocstyle",
"pylint",
"pytest",
"sphinx",
"sphinx-autodoc-typehints",
"tox",
"twine",
]
},
python_requires=">=3.6, <4",
package_data={"zero_ex.order_utils": ["py.typed"]},
package_dir={"": "src"},
license="Apache 2.0",
keywords=(
"ethereum cryptocurrency 0x decentralized blockchain dex exchange"
),
namespace_packages=["zero_ex"],
packages=find_packages("src"),
classifiers=[
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"Intended Audience :: Financial and Insurance Industry",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Topic :: Internet :: WWW/HTTP",
"Topic :: Office/Business :: Financial",
"Topic :: Other/Nonlisted Topic",
"Topic :: Security :: Cryptography",
"Topic :: Software Development :: Libraries",
"Topic :: Utilities",
],
zip_safe=False, # required per mypy
command_options={
"build_sphinx": {
"source_dir": ("setup.py", "src"),
"build_dir": ("setup.py", "build/docs"),
"warning_is_error": ("setup.py", "true"),
}
},
)