',tox)
+
+### run tests wit tox
+tox: .tox
+
+tox-clean:
rm -rf .tox
+
+test-clean: tox-clean
+ rm -f .coverage
+
+test-sterile: test-clean
+ find logs -type f -not -name README.md -exec rm -f '{}' +
diff --git a/make/version.mk b/make/version.mk
index 556f709..31f9f00 100644
--- a/make/version.mk
+++ b/make/version.mk
@@ -40,8 +40,8 @@ bump-major: version-update
version-update:
$(call gitclean)
[ -f .bumpversion.cfg ] || { echo "$$BUMPVERSION_CFG" >.bumpversion.cfg; git add .bumpversion.cfg; }
- $(MAKE) requirements.txt requirements-dev.txt requirements-docs.txt
- git add requirements.txt requirements-dev.txt requirements-docs.txt
+ $(MAKE) --no-print-directory requirements
+ git add requirements*.txt
sed -E -i $(module)/version.py -e "s/(.*__timestamp__.*=).*/\1 \"$$(date --rfc-3339=seconds)\"/"
git add $(module)/version.py VERSION
@echo "Updated version.py timestamp and requirements.txt"
@@ -49,3 +49,6 @@ version-update:
# clean up version tempfiles
version-clean:
@:
+
+version-sterile:
+ rm -f .bumpversion.cfg
diff --git a/pyproject.toml b/pyproject.toml
index 014aa33..87cbdbe 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -25,7 +25,7 @@ dependencies = [
]
[tool.flit.module]
-name = "etherscan"
+name = "rstms_etherscan_python"
[project.optional-dependencies]
dev = [
@@ -40,6 +40,7 @@ dev = [
"pyrate-limiter",
"pytest",
"pytest-datadir",
+ "tox"
]
docs = [
"m2r2",
diff --git a/pytest.ini b/pytest.ini
index 65afe8e..1c40189 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,2 +1,2 @@
[pytest]
-addopts = -xv
+addopts = -x
diff --git a/requirements-dev.txt b/requirements-dev.txt
index bfdb5b4..98edf91 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -9,3 +9,4 @@ pdbpp
pyrate-limiter
pytest
pytest-datadir
+tox
diff --git a/requirements-docs.txt b/requirements-docs.txt
deleted file mode 100644
index 42c731e..0000000
--- a/requirements-docs.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-m2r2
-sphinx
-sphinx-click
-sphinx-rtd-theme
diff --git a/etherscan/__init__.py b/rstms_etherscan_python/__init__.py
similarity index 93%
rename from etherscan/__init__.py
rename to rstms_etherscan_python/__init__.py
index 29f86c0..45d933e 100644
--- a/etherscan/__init__.py
+++ b/rstms_etherscan_python/__init__.py
@@ -7,6 +7,7 @@
"""
+from .etherscan import Etherscan
from .modules.accounts import Accounts as accounts
from .modules.blocks import Blocks as blocks
from .modules.contracts import Contracts as contracts
@@ -19,6 +20,7 @@
from .version import __version__
__all__ = [
+ "Etherscan",
"__version__",
"accounts",
"blocks",
diff --git a/etherscan/configs/GOERLI-stable.json b/rstms_etherscan_python/configs/GOERLI-stable.json
similarity index 97%
rename from etherscan/configs/GOERLI-stable.json
rename to rstms_etherscan_python/configs/GOERLI-stable.json
index 5fc57ab..03cde83 100644
--- a/etherscan/configs/GOERLI-stable.json
+++ b/rstms_etherscan_python/configs/GOERLI-stable.json
@@ -81,14 +81,14 @@
"gas": "0x5f5e0ff"
}
},
- "get_est_confirmation_time": {
+ "_get_est_confirmation_time": {
"module": "gastracker",
"kwargs": {
"gas_price": "2000000000"
}
},
- "get_gas_oracle": {
- "module": "gastracker",
+ "_get_gas_oracle": {
+ "module": "gastracker",
"kwargs": {}
},
"get_block_reward_by_block_number": {
@@ -97,10 +97,10 @@
"block_no": "2165403"
}
},
- "get_est_block_countdown_time_by_block_number": {
+ "_get_est_block_countdown_time_by_block_number": {
"module": "blocks",
"kwargs": {
- "block_no": "99999999"
+ "block_no": "16701588"
}
},
"get_block_number_by_timestamp": {
diff --git a/etherscan/configs/KOVAN-stable.json b/rstms_etherscan_python/configs/KOVAN-stable.json
similarity index 100%
rename from etherscan/configs/KOVAN-stable.json
rename to rstms_etherscan_python/configs/KOVAN-stable.json
diff --git a/etherscan/configs/MAIN-stable.json b/rstms_etherscan_python/configs/MAIN-stable.json
similarity index 99%
rename from etherscan/configs/MAIN-stable.json
rename to rstms_etherscan_python/configs/MAIN-stable.json
index 6629a42..5e70803 100644
--- a/etherscan/configs/MAIN-stable.json
+++ b/rstms_etherscan_python/configs/MAIN-stable.json
@@ -94,13 +94,13 @@
"get_block_reward_by_block_number": {
"module": "blocks",
"kwargs": {
- "block_no": "2165403"
+ "block_no": "12697906"
}
},
- "get_est_block_countdown_time_by_block_number": {
+ "_get_est_block_countdown_time_by_block_number": {
"module": "blocks",
"kwargs": {
- "block_no": "99999999"
+ "block_no": "16701588"
}
},
"get_block_number_by_timestamp": {
diff --git a/etherscan/configs/RINKEBY-stable.json b/rstms_etherscan_python/configs/RINKEBY-stable.json
similarity index 100%
rename from etherscan/configs/RINKEBY-stable.json
rename to rstms_etherscan_python/configs/RINKEBY-stable.json
diff --git a/etherscan/configs/ROPSTEN-stable.json b/rstms_etherscan_python/configs/ROPSTEN-stable.json
similarity index 100%
rename from etherscan/configs/ROPSTEN-stable.json
rename to rstms_etherscan_python/configs/ROPSTEN-stable.json
diff --git a/etherscan/configs/__init__.py b/rstms_etherscan_python/configs/__init__.py
similarity index 100%
rename from etherscan/configs/__init__.py
rename to rstms_etherscan_python/configs/__init__.py
diff --git a/etherscan/enums/__init__.py b/rstms_etherscan_python/enums/__init__.py
similarity index 100%
rename from etherscan/enums/__init__.py
rename to rstms_etherscan_python/enums/__init__.py
diff --git a/etherscan/enums/actions_enum.py b/rstms_etherscan_python/enums/actions_enum.py
similarity index 100%
rename from etherscan/enums/actions_enum.py
rename to rstms_etherscan_python/enums/actions_enum.py
diff --git a/etherscan/enums/fields_enum.py b/rstms_etherscan_python/enums/fields_enum.py
similarity index 100%
rename from etherscan/enums/fields_enum.py
rename to rstms_etherscan_python/enums/fields_enum.py
diff --git a/etherscan/enums/modules_enum.py b/rstms_etherscan_python/enums/modules_enum.py
similarity index 100%
rename from etherscan/enums/modules_enum.py
rename to rstms_etherscan_python/enums/modules_enum.py
diff --git a/etherscan/enums/tags_enum.py b/rstms_etherscan_python/enums/tags_enum.py
similarity index 100%
rename from etherscan/enums/tags_enum.py
rename to rstms_etherscan_python/enums/tags_enum.py
diff --git a/etherscan/etherscan.py b/rstms_etherscan_python/etherscan.py
similarity index 96%
rename from etherscan/etherscan.py
rename to rstms_etherscan_python/etherscan.py
index ef6199b..06c45af 100644
--- a/etherscan/etherscan.py
+++ b/rstms_etherscan_python/etherscan.py
@@ -3,8 +3,6 @@
import requests
-import etherscan
-
from . import configs
from .enums.fields_enum import FieldsEnum as fields
from .utils.parsing import ResponseParser as parser
@@ -37,6 +35,8 @@ def wrapper(*args, **kwargs):
@classmethod
def from_config(cls, api_key: str, config_path: str, net: str):
+ import rstms_etherscan_python as etherscan
+
config = cls.__load_config(config_path)
for func, v in config.items():
if not func.startswith("_"): # disabled if _
diff --git a/rstms_etherscan_python/exceptions.py b/rstms_etherscan_python/exceptions.py
new file mode 100644
index 0000000..ed3c245
--- /dev/null
+++ b/rstms_etherscan_python/exceptions.py
@@ -0,0 +1,17 @@
+# Etherscan API Exceptions
+
+
+class EtherscanUnauthorizedEndpoint(Exception):
+ pass
+
+
+class EtherscanErrorResponse(Exception):
+ pass
+
+
+class EtherscanStatusFailure(Exception):
+ pass
+
+
+class EtherscanUnexpectedResponse(Exception):
+ pass
diff --git a/etherscan/modules/__init__.py b/rstms_etherscan_python/modules/__init__.py
similarity index 100%
rename from etherscan/modules/__init__.py
rename to rstms_etherscan_python/modules/__init__.py
diff --git a/etherscan/modules/accounts.py b/rstms_etherscan_python/modules/accounts.py
similarity index 100%
rename from etherscan/modules/accounts.py
rename to rstms_etherscan_python/modules/accounts.py
diff --git a/etherscan/modules/blocks.py b/rstms_etherscan_python/modules/blocks.py
similarity index 100%
rename from etherscan/modules/blocks.py
rename to rstms_etherscan_python/modules/blocks.py
diff --git a/etherscan/modules/contracts.py b/rstms_etherscan_python/modules/contracts.py
similarity index 100%
rename from etherscan/modules/contracts.py
rename to rstms_etherscan_python/modules/contracts.py
diff --git a/etherscan/modules/gastracker.py b/rstms_etherscan_python/modules/gastracker.py
similarity index 100%
rename from etherscan/modules/gastracker.py
rename to rstms_etherscan_python/modules/gastracker.py
diff --git a/etherscan/modules/pro.py b/rstms_etherscan_python/modules/pro.py
similarity index 100%
rename from etherscan/modules/pro.py
rename to rstms_etherscan_python/modules/pro.py
diff --git a/etherscan/modules/proxy.py b/rstms_etherscan_python/modules/proxy.py
similarity index 100%
rename from etherscan/modules/proxy.py
rename to rstms_etherscan_python/modules/proxy.py
diff --git a/etherscan/modules/stats.py b/rstms_etherscan_python/modules/stats.py
similarity index 100%
rename from etherscan/modules/stats.py
rename to rstms_etherscan_python/modules/stats.py
diff --git a/etherscan/modules/tokens.py b/rstms_etherscan_python/modules/tokens.py
similarity index 100%
rename from etherscan/modules/tokens.py
rename to rstms_etherscan_python/modules/tokens.py
diff --git a/etherscan/modules/transactions.py b/rstms_etherscan_python/modules/transactions.py
similarity index 100%
rename from etherscan/modules/transactions.py
rename to rstms_etherscan_python/modules/transactions.py
diff --git a/etherscan/utils/__init__.py b/rstms_etherscan_python/utils/__init__.py
similarity index 100%
rename from etherscan/utils/__init__.py
rename to rstms_etherscan_python/utils/__init__.py
diff --git a/etherscan/utils/conversions.py b/rstms_etherscan_python/utils/conversions.py
similarity index 100%
rename from etherscan/utils/conversions.py
rename to rstms_etherscan_python/utils/conversions.py
diff --git a/rstms_etherscan_python/utils/parsing.py b/rstms_etherscan_python/utils/parsing.py
new file mode 100644
index 0000000..e95c629
--- /dev/null
+++ b/rstms_etherscan_python/utils/parsing.py
@@ -0,0 +1,36 @@
+import requests
+
+from ..exceptions import (
+ EtherscanErrorResponse,
+ EtherscanStatusFailure,
+ EtherscanUnauthorizedEndpoint,
+ EtherscanUnexpectedResponse,
+)
+
+PRO_ENDPOINT_RESPONSE = (
+ "Sorry, it looks like you are trying to access an API Pro endpoint. Contact us to upgrade to API Pro."
+)
+
+
+class ResponseParser:
+ @staticmethod
+ def parse(response: requests.Response):
+ content = response.json()
+ if "result" in content.keys():
+ result = content["result"]
+ elif "error" in content.keys():
+ raise EtherscanErrorResponse(f"response={content}")
+ else:
+ raise EtherscanUnexpectedResponse(f"response={content}")
+ if "status" in content.keys():
+ status = bool(int(content["status"]))
+ if result == PRO_ENDPOINT_RESPONSE:
+ url, _, _ = response.url.partition("apikey=")
+ url += "apikey=..."
+ raise EtherscanUnauthorizedEndpoint(f"{result} {url=}")
+ if status is None:
+ raise EtherscanStatusFailure(f"response={content}")
+ else:
+ # GETH or Parity proxy msg format
+ result = dict(jsonrpc=content["jsonrpc"], cid=int(content["id"]), result=result)
+ return result
diff --git a/rstms_etherscan_python/version.py b/rstms_etherscan_python/version.py
new file mode 100644
index 0000000..dd0edd7
--- /dev/null
+++ b/rstms_etherscan_python/version.py
@@ -0,0 +1 @@
+__version__ = "2.1.11"
diff --git a/tests/test_modules.py b/tests/test_modules.py
index eae929d..35156ef 100644
--- a/tests/test_modules.py
+++ b/tests/test_modules.py
@@ -4,11 +4,17 @@
from datetime import datetime
from unittest import TestCase
-from etherscan.etherscan import Etherscan
+from rstms_etherscan_python import Etherscan
+from rstms_etherscan_python.exceptions import (
+ EtherscanErrorResponse,
+ EtherscanUnauthorizedEndpoint,
+)
-CONFIG_PATH = "etherscan/configs/{}-stable.json"
+CONFIG_PATH = "rstms_etherscan_python/configs/{}-stable.json"
API_KEY = os.environ["API_KEY"] # Encrypted env var by Travis
+TEST_API_PRO_ENDPOINTS = "TEST_API_PRO_ENDPOINTS" in os.environ
+
def test_init():
api = Etherscan(API_KEY)
@@ -38,8 +44,20 @@ def methods(self, net):
for fun, v in config.items():
if not fun.startswith("_"): # disabled if _
if v["module"] == self._MODULE:
- res = getattr(etherscan, fun)(**v["kwargs"])
- print(f"METHOD: {fun}, RTYPE: {type(res)}")
+ try:
+ res = getattr(etherscan, fun)(**v["kwargs"])
+ rtype = type(res)
+ except EtherscanUnauthorizedEndpoint as exc:
+ if TEST_API_PRO_ENDPOINTS:
+ raise exc from exc
+ else:
+ rtype = type(exc)
+ res = repr(exc)
+ except EtherscanErrorResponse as exc:
+ rtype = type(exc)
+ res = repr(exc)
+
+ print(f"METHOD: {fun}, RTYPE: {rtype}")
# Create log files (will update existing ones)
fname = f"logs/standard/{net}-{fun}.json"
log = {
diff --git a/tox.ini b/tox.ini
new file mode 100644
index 0000000..e0ecba7
--- /dev/null
+++ b/tox.ini
@@ -0,0 +1,30 @@
+[tox]
+envlist = flake8, py310
+isolated_build = True
+
+[testenv:flake8]
+skip_install = True
+basepython = python
+deps = flake8
+commands = flake8 rstms_etherscan_python tests
+package = skip
+
+[testenv:py310]
+setenv =
+passenv =
+ API_KEY
+ TEST_API_PRO_ENDPOINTS
+package = skip
+skip_install = True
+allowlist_externals = pip pytest
+commands =
+ pip install -f dist .[dev]
+ pytest {env:PYTEST_OPTIONS} --basetemp={envtmpdir}
+
+[flake8]
+max-line-length = 120
+show-source = False
+max-complexity = 10
+extend-ignore =
+ E501,
+ W505
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy