diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 4c4e24e..0000000 --- a/.flake8 +++ /dev/null @@ -1,39 +0,0 @@ -[flake8] -# As defined at https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings -docstring-convention=google -exclude = .venv, tests, dist, keystore - -# D212 and D213 are mutually exclusive, so we're only allowing D213. -# D205 and D415 don't like multi-line summary statements, which is annoying. -# E203 and W503 don't interact well with black -ignore = D205,D212,D415,E203,W503 - -# This is the line length that black uses -# https://black.readthedocs.io/en/stable/the_black_code_style.html#line-length -max-line-length = 88 - -per-file-ignores = - # For tests, disable type annotation and docstring linting. - tests/*: ANN D DAR - -# Select other tools to enable. - -# ABS enables absolute import checks. - -# ANN enables linting for type annotations. - -# BLK enables using black --check from within flake8. - -# D enables docstrings warnings from pydocstyle. - -# DAR enables docstring style linting via darglint. - -# F are errors reported by pyflakes, a tool which parses source files -# and finds invalid Python code. - -# I is linting errors related to isort, which is the source of truth -# for how imports should be ordered. - -# W and E are warnings and errors reported by pycodestyle, which checks -# your Python code against some of the style conventions in PEP 8. -select = ABS,ANN,DAR,BLK,D,E,F,I,W diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 85060e5..5e403c2 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -42,9 +42,13 @@ jobs: run: | poetry install - - name: Lint with flake8 + - name: Format check (Ruff) run: | - poetry run flake8 . + poetry run ruff format --check . + + - name: Lint with Ruff + run: | + poetry run ruff check . integration: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..87fa000 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +# Ruff: format then lint (same commands as CI / Poetry env). +repos: + - repo: local + hooks: + - id: ruff-format-poetry + name: ruff format (poetry run ruff format .) + entry: poetry run ruff format . + language: system + pass_filenames: false + always_run: true + require_serial: true + - repo: local + hooks: + - id: ruff-poetry + name: ruff check (poetry run ruff check .) + entry: poetry run ruff check --fix . + language: system + pass_filenames: false + always_run: true + require_serial: true diff --git a/.vscode/settings.json b/.vscode/settings.json index d4d2d25..0dd647f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,10 @@ // Place your settings in this file to overwrite default and user settings. { "[python]": { - "formatting.provider": "black", + "editor.defaultFormatter": "charliermarsh.ruff", "linting.pylintEnabled": false, - "linting.flake8Enabled": true, + "linting.flake8Enabled": false, + "ruff.enable": true, "linting.enabled": true, "linting.mypyEnabled": true, // "editor.wordWrap": "wordWrapColumn", diff --git a/basedir.py b/basedir.py index 9fe19ea..66c506c 100644 --- a/basedir.py +++ b/basedir.py @@ -2,4 +2,5 @@ # coding: utf-8 import os + basedir = os.path.abspath(os.path.dirname(__file__)) diff --git a/poetry.lock b/poetry.lock index d22f8aa..ddf3fa3 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "anyio" @@ -144,6 +144,32 @@ files = [ [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +markers = "python_version < \"3.10\"" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "cfgv" +version = "3.5.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.10\"" +files = [ + {file = "cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0"}, + {file = "cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132"}, +] + [[package]] name = "charset-normalizer" version = "3.4.4" @@ -344,6 +370,18 @@ wrapt = ">=1.10,<3" [package.extras] dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "setuptools ; python_version >= \"3.12\"", "tox"] +[[package]] +name = "distlib" +version = "0.4.0" +description = "Distribution utilities" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"}, + {file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"}, +] + [[package]] name = "ecpy" version = "1.2.5" @@ -376,21 +414,30 @@ typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} test = ["pytest (>=6)"] [[package]] -name = "flake8" -version = "3.9.2" -description = "the modular source code checker: pep8 pyflakes and co" +name = "filelock" +version = "3.19.1" +description = "A platform independent file lock." optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.9" groups = ["dev"] +markers = "python_version < \"3.10\"" files = [ - {file = "flake8-3.9.2-py2.py3-none-any.whl", hash = "sha256:bf8fd333346d844f616e8d47905ef3a3384edae6b4e9beb0c5101e25e3110907"}, - {file = "flake8-3.9.2.tar.gz", hash = "sha256:07528381786f2a6237b061f6e96610a4167b226cb926e2aa2b6b1d78057c576b"}, + {file = "filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d"}, + {file = "filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58"}, ] -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.7.0,<2.8.0" -pyflakes = ">=2.3.0,<2.4.0" +[[package]] +name = "filelock" +version = "3.25.2" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.10\"" +files = [ + {file = "filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70"}, + {file = "filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694"}, +] [[package]] name = "h11" @@ -450,6 +497,38 @@ cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +[[package]] +name = "identify" +version = "2.6.15" +description = "File identification library for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version < \"3.10\"" +files = [ + {file = "identify-2.6.15-py2.py3-none-any.whl", hash = "sha256:1181ef7608e00704db228516541eb83a88a9f94433a8c80bb9b5bd54b1d81757"}, + {file = "identify-2.6.15.tar.gz", hash = "sha256:e4f4864b96c6557ef2a1e1c951771838f4edc9df3a72ec7118b338801b11c7bf"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "identify" +version = "2.6.18" +description = "File identification library for Python" +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.10\"" +files = [ + {file = "identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737"}, + {file = "identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd"}, +] + +[package.extras] +license = ["ukkonen"] + [[package]] name = "idna" version = "3.11" @@ -478,15 +557,15 @@ files = [ ] [[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" +name = "nodeenv" +version = "1.10.0" +description = "Node.js virtual environment builder" optional = false -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" groups = ["dev"] files = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, + {file = "nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827"}, + {file = "nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb"}, ] [[package]] @@ -501,6 +580,37 @@ files = [ {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, ] +[[package]] +name = "platformdirs" +version = "4.4.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version < \"3.10\"" +files = [ + {file = "platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85"}, + {file = "platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "platformdirs" +version = "4.9.4" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.10" +groups = ["dev"] +markers = "python_version >= \"3.10\"" +files = [ + {file = "platformdirs-4.9.4-py3-none-any.whl", hash = "sha256:68a9a4619a666ea6439f2ff250c12a853cd1cbd5158d258bd824a7df6be2f868"}, + {file = "platformdirs-4.9.4.tar.gz", hash = "sha256:1ec356301b7dc906d83f371c8f487070e99d3ccf9e501686456394622a01a934"}, +] + [[package]] name = "pluggy" version = "1.6.0" @@ -518,17 +628,24 @@ dev = ["pre-commit", "tox"] testing = ["coverage", "pytest", "pytest-benchmark"] [[package]] -name = "pycodestyle" -version = "2.7.0" -description = "Python style guide checker" +name = "pre-commit" +version = "3.8.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.9" groups = ["dev"] files = [ - {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"}, - {file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"}, + {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, + {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, ] +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + [[package]] name = "pycparser" version = "2.23" @@ -593,18 +710,6 @@ files = [ {file = "pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef"}, ] -[[package]] -name = "pyflakes" -version = "2.3.1" -description = "passive checker of Python programs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -groups = ["dev"] -files = [ - {file = "pyflakes-2.3.1-py2.py3-none-any.whl", hash = "sha256:7893783d01b8a89811dd72d7dfd4d84ff098e5eed95cfa8905b22bbffe52efc3"}, - {file = "pyflakes-2.3.1.tar.gz", hash = "sha256:f5bc8ecabc05bb9d291eb5203d6810b49040f6ff446a756326104746cc00c1db"}, -] - [[package]] name = "pytest" version = "7.4.4" @@ -628,6 +733,26 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "python-discovery" +version = "1.2.0" +description = "Python interpreter discovery" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "python_discovery-1.2.0-py3-none-any.whl", hash = "sha256:1e108f1bbe2ed0ef089823d28805d5ad32be8e734b86a5f212bf89b71c266e4a"}, + {file = "python_discovery-1.2.0.tar.gz", hash = "sha256:7d33e350704818b09e3da2bd419d37e21e7c30db6e0977bb438916e06b41b5b1"}, +] + +[package.dependencies] +filelock = ">=3.15.4" +platformdirs = ">=4.3.6,<5" + +[package.extras] +docs = ["furo (>=2025.12.19)", "sphinx (>=9.1)", "sphinx-autodoc-typehints (>=3.6.3)", "sphinxcontrib-mermaid (>=2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.5.4)", "pytest (>=8.3.5)", "pytest-mock (>=3.14)", "setuptools (>=75.1)"] + [[package]] name = "python-dotenv" version = "1.2.1" @@ -649,7 +774,7 @@ version = "6.0.3" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" -groups = ["main"] +groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.3-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f"}, {file = "PyYAML-6.0.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4"}, @@ -748,6 +873,34 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "ruff" +version = "0.15.7" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "ruff-0.15.7-py3-none-linux_armv6l.whl", hash = "sha256:a81cc5b6910fb7dfc7c32d20652e50fa05963f6e13ead3c5915c41ac5d16668e"}, + {file = "ruff-0.15.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:722d165bd52403f3bdabc0ce9e41fc47070ac56d7a91b4e0d097b516a53a3477"}, + {file = "ruff-0.15.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7fbc2448094262552146cbe1b9643a92f66559d3761f1ad0656d4991491af49e"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b39329b60eba44156d138275323cc726bbfbddcec3063da57caa8a8b1d50adf"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:87768c151808505f2bfc93ae44e5f9e7c8518943e5074f76ac21558ef5627c85"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fb0511670002c6c529ec66c0e30641c976c8963de26a113f3a30456b702468b0"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0d19644f801849229db8345180a71bee5407b429dd217f853ec515e968a6912"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4806d8e09ef5e84eb19ba833d0442f7e300b23fe3f0981cae159a248a10f0036"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce0896488562f09a27b9c91b1f58a097457143931f3c4d519690dea54e624c5"}, + {file = "ruff-0.15.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:1852ce241d2bc89e5dc823e03cff4ce73d816b5c6cdadd27dbfe7b03217d2a12"}, + {file = "ruff-0.15.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5f3e4b221fb4bd293f79912fc5e93a9063ebd6d0dcbd528f91b89172a9b8436c"}, + {file = "ruff-0.15.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b15e48602c9c1d9bdc504b472e90b90c97dc7d46c7028011ae67f3861ceba7b4"}, + {file = "ruff-0.15.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b4705e0e85cedc74b0a23cf6a179dbb3df184cb227761979cc76c0440b5ab0d"}, + {file = "ruff-0.15.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:112c1fa316a558bb34319282c1200a8bf0495f1b735aeb78bfcb2991e6087580"}, + {file = "ruff-0.15.7-py3-none-win32.whl", hash = "sha256:6d39e2d3505b082323352f733599f28169d12e891f7dd407f2d4f54b4c2886de"}, + {file = "ruff-0.15.7-py3-none-win_amd64.whl", hash = "sha256:4d53d712ddebcd7dace1bc395367aec12c057aacfe9adbb6d832302575f4d3a1"}, + {file = "ruff-0.15.7-py3-none-win_arm64.whl", hash = "sha256:18e8d73f1c3fdf27931497972250340f92e8c861722161a9caeb89a58ead6ed2"}, + {file = "ruff-0.15.7.tar.gz", hash = "sha256:04f1ae61fc20fe0b148617c324d9d009b5f63412c0b16474f3d5f1a1a665f7ac"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -856,6 +1009,28 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""] +[[package]] +name = "virtualenv" +version = "21.2.0" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f"}, + {file = "virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = [ + {version = ">=3.24.2,<4", markers = "python_version >= \"3.10\""}, + {version = ">=3.16.1,<=3.19.1", markers = "python_version < \"3.10\""}, +] +platformdirs = ">=3.9.1,<5" +python-discovery = ">=1" +typing-extensions = {version = ">=4.13.2", markers = "python_version < \"3.11\""} + [[package]] name = "websockets" version = "11.0.3" @@ -1101,4 +1276,4 @@ xrpl-py = ">=2.4.0,<3.0.0" [metadata] lock-version = "2.1" python-versions = "^3.9.6" -content-hash = "763b261815371ff168783581e185bd1c9cd844f5086be3d867594b6b60ddac03" +content-hash = "a9a5e6122c22241d3b305f605aede8cbb3f15da20bf930b6714f9e729c718aa5" diff --git a/pyproject.toml b/pyproject.toml index 4cee3a8..e19adb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,9 +10,21 @@ pyyaml = "^6.0.1" requests = "^2.31.0" xrpld-publisher = "^2.0.0" -[tool.poetry.dev-dependencies] +[tool.poetry.group.dev.dependencies] pytest = "^7.2.1" -flake8 = "^3.8.4" +pre-commit = ">=3.7,<4" +ruff = ">=0.8" + +[tool.ruff] +line-length = 88 +target-version = "py39" +exclude = [".venv", "tests", "dist", "keystore"] + +[tool.ruff.lint] +# Mirrors flake8 as declared in Poetry (pycodestyle E/W, pyflakes F); isort (I). +# Former .flake8 also listed D/ANN/ABS/DAR/BLK plugins but they were not dependencies. +select = ["E", "W", "F", "I"] +ignore = ["E203"] [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/test.py b/test.py index 62e5645..138d086 100644 --- a/test.py +++ b/test.py @@ -1,12 +1,14 @@ #!/usr/bin/env python # coding: utf-8 -import pytest -from basedir import basedir import os import shutil import sys +import pytest + +from basedir import basedir + def main(): """main.py.""" @@ -17,22 +19,22 @@ def main(): pytest.main(argv) try: - os.remove(os.path.join(basedir, '.coverage')) + os.remove(os.path.join(basedir, ".coverage")) except OSError: pass try: - shutil.rmtree(os.path.join(basedir, '.cache')) + shutil.rmtree(os.path.join(basedir, ".cache")) except OSError: pass try: - shutil.rmtree(os.path.join(basedir, 'tests/.cache')) + shutil.rmtree(os.path.join(basedir, "tests/.cache")) except OSError: pass -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/xrpld_netgen/cideploy/deploy.py b/xrpld_netgen/cideploy/deploy.py index 8133049..6c0c2fb 100644 --- a/xrpld_netgen/cideploy/deploy.py +++ b/xrpld_netgen/cideploy/deploy.py @@ -1,5 +1,5 @@ -from xrpld_netgen.utils.deploy_kit import download_binary from xrpld_netgen.cli import XAHAU_RELEASE +from xrpld_netgen.utils.deploy_kit import download_binary build_server: str = "https://build.xahau.tech" build_version: str = XAHAU_RELEASE diff --git a/xrpld_netgen/cli.py b/xrpld_netgen/cli.py index 6378d12..19c572c 100644 --- a/xrpld_netgen/cli.py +++ b/xrpld_netgen/cli.py @@ -34,28 +34,29 @@ # xrpld-netgen down:standalone -import os import argparse +import os + from xrpld_netgen.main import ( create_standalone_binary, create_standalone_image, start_local, ) from xrpld_netgen.network import ( - create_network, create_local_network, - update_node_binary, + create_network, enable_node_amendment, + update_node_binary, ) from xrpld_netgen.utils.misc import ( - remove_directory, bcolors, check_deps, remove_containers, + remove_directory, + run_local_logs, + run_logs, run_start, run_stop, - run_logs, - run_local_logs, ) package_dir = os.path.abspath(os.path.dirname(__file__)) @@ -67,6 +68,7 @@ _XRPL_RELEASE_FALLBACK: str = "3.1.1" _XAHAU_RELEASE_FALLBACK: str = "2025.7.9-release+1951" + def main(): parser = argparse.ArgumentParser( description="A python cli to build xrpld networks and standalone ledgers." diff --git a/xrpld_netgen/libs/github.py b/xrpld_netgen/libs/github.py index 141539e..d996913 100644 --- a/xrpld_netgen/libs/github.py +++ b/xrpld_netgen/libs/github.py @@ -1,9 +1,10 @@ #!/usr/bin/env python # coding: utf-8 -import requests import re +import requests + def get_commit_hash_from_server_version(server: str, version: str) -> str: """ @@ -36,7 +37,11 @@ def get_commit_hash_from_server_version(server: str, version: str) -> str: def download_file_at_commit_or_tag( - owner: str, repo: str, commit_hash_or_tag: str, file_path: str, fallback_file_path: str = None + owner: str, + repo: str, + commit_hash_or_tag: str, + file_path: str, + fallback_file_path: str = None, ) -> str: """ Download a specific file from a GitHub repository at a given commit hash or tag. @@ -56,7 +61,9 @@ def download_file_at_commit_or_tag( # Send a GET request to the URL response = requests.get(url) if response.status_code == 404 and fallback_file_path: - return download_file_at_commit_or_tag(owner, repo, commit_hash_or_tag, fallback_file_path) + return download_file_at_commit_or_tag( + owner, repo, commit_hash_or_tag, fallback_file_path + ) response.raise_for_status() # Return the content of the file diff --git a/xrpld_netgen/libs/xrpld.py b/xrpld_netgen/libs/xrpld.py index f3ede10..91c0fb1 100644 --- a/xrpld_netgen/libs/xrpld.py +++ b/xrpld_netgen/libs/xrpld.py @@ -1,12 +1,12 @@ #!/usr/bin/env python # coding: utf-8 -import re +import hashlib import os -from typing import Dict, Any, List # noqa: F401 +import re +from typing import Any, Dict, List # noqa: F401 from xrpld_netgen.utils.misc import read_json -import hashlib basedir = os.path.abspath(os.path.dirname(__file__)) parentdir = os.path.dirname(basedir) @@ -39,7 +39,9 @@ def parse_amendments(lines: Any): elif re.match(r"XRPL_FEATURE", line): amendment_name = re.search(r"XRPL_FEATURE\((.*?),", line).group(1) or 0 elif re.match(r"REGISTER_FIX", line): - amendment_name = re.search(r"REGISTER_FIX\)?.*?\((.*?),", line).group(1) or 0 + amendment_name = ( + re.search(r"REGISTER_FIX\)?.*?\((.*?),", line).group(1) or 0 + ) elif re.match(r"REGISTER_FEATURE", line): amendment_name = re.search(r"REGISTER_FEATURE\((.*?),", line).group(1) or 0 else: diff --git a/xrpld_netgen/main.py b/xrpld_netgen/main.py index 27b83c9..679e1e7 100644 --- a/xrpld_netgen/main.py +++ b/xrpld_netgen/main.py @@ -1,39 +1,40 @@ #!/usr/bin/env python # coding: utf-8 +import json import os -import yaml import shutil -import json -from typing import List, Any, Dict +from typing import Any, Dict, List -from xrpld_netgen.xrpld_cfg import gen_config, XrpldBuild +import yaml + +from xrpld_netgen.libs.github import ( + download_file_at_commit_or_tag, + get_commit_hash_from_server_version, +) +from xrpld_netgen.libs.xrpld import ( + get_feature_lines_from_content, + get_feature_lines_from_path, + parse_amendments, + update_amendments, +) from xrpld_netgen.utils.deploy_kit import ( + build_local_start_sh, + build_start_sh, + build_stop_sh, create_dockerfile, download_binary, - build_stop_sh, - build_start_sh, - build_local_start_sh, -) -from xrpld_netgen.libs.github import ( - get_commit_hash_from_server_version, - download_file_at_commit_or_tag, ) from xrpld_netgen.utils.misc import ( - generate_ports, - save_local_config, bcolors, - write_file, - read_json, + generate_ports, get_node_db_path, get_relational_db, + read_json, + save_local_config, + write_file, ) -from xrpld_netgen.libs.xrpld import ( - update_amendments, - parse_amendments, - get_feature_lines_from_content, - get_feature_lines_from_path, -) +from xrpld_netgen.xrpld_cfg import XrpldBuild, gen_config # Package directory for static resources (deploykit, genesis files, # default features, etc.) @@ -386,7 +387,11 @@ def create_standalone_binary( repo = "xahaud" commit_hash = get_commit_hash_from_server_version(build_server, build_version) content_bytes = download_file_at_commit_or_tag( - owner, repo, commit_hash, "src/ripple/protocol/impl/Feature.cpp", "include/xrpl/protocol/detail/features.macro" + owner, + repo, + commit_hash, + "src/ripple/protocol/impl/Feature.cpp", + "include/xrpl/protocol/detail/features.macro", ) content = get_feature_lines_from_content(content_bytes) url: str = f"{build_server}/{build_version}" @@ -512,7 +517,7 @@ def create_local_folder( cpp_path = "../src/ripple/protocol/impl/Feature.cpp" macro_path = "../include/xrpl/protocol/detail/features.macro" features_path = cpp_path if os.path.exists(cpp_path) else macro_path - + if protocol == "xahau": content: str = get_feature_lines_from_path(features_path) features_json: Dict[str, Any] = parse_amendments(content) @@ -580,8 +585,8 @@ def start_local( stop_sh_content: str = build_stop_sh(basedir, protocol, name, 0, 0, False, True) write_file("stop.sh", stop_sh_content) os.chmod("stop.sh", 0o755) - import sys import subprocess + import sys try: result = subprocess.run( diff --git a/xrpld_netgen/network.py b/xrpld_netgen/network.py index 92389e5..d045e57 100644 --- a/xrpld_netgen/network.py +++ b/xrpld_netgen/network.py @@ -1,54 +1,53 @@ #!/usr/bin/env python # coding: utf-8 +import json import os -import yaml import shutil -import json -from typing import List, Any, Dict +from typing import Any, Dict, List + +import yaml from dotenv import load_dotenv +from xrpld_publisher.publisher import PublisherClient +from xrpld_publisher.validator import ValidatorClient -from xrpld_netgen.xrpld_cfg import gen_config, XrpldBuild +from xrpld_netgen.libs.github import ( + download_file_at_commit_or_tag, + get_commit_hash_from_server_version, +) +from xrpld_netgen.libs.xrpld import ( + get_feature_lines_from_content, + get_feature_lines_from_path, + parse_amendments, + update_amendments, +) from xrpld_netgen.utils.deploy_kit import ( - create_dockerfile, - copy_file, - download_binary, - update_dockerfile, DockerVars, - create_ansible_vars_file, - build_network_stop_sh, - build_network_start_sh, build_local_network_start_sh, build_local_network_stop_sh, -) -from xrpld_netgen.libs.github import ( - get_commit_hash_from_server_version, - download_file_at_commit_or_tag, + build_network_start_sh, + build_network_stop_sh, + copy_file, + create_ansible_vars_file, + create_dockerfile, + download_binary, + update_dockerfile, ) from xrpld_netgen.utils.misc import ( - run_command, + bcolors, generate_ports, - save_local_config, + get_node_db_path, get_node_port, - sha512_half, - run_stop, + get_relational_db, + read_json, remove_directory, - bcolors, + run_command, + run_stop, + save_local_config, + sha512_half, write_file, - read_json, - get_node_db_path, - get_relational_db, ) - -from xrpld_netgen.libs.xrpld import ( - update_amendments, - parse_amendments, - get_feature_lines_from_content, - get_feature_lines_from_path, -) - -from xrpld_publisher.publisher import PublisherClient -from xrpld_publisher.validator import ValidatorClient +from xrpld_netgen.xrpld_cfg import XrpldBuild, gen_config load_dotenv() @@ -378,7 +377,11 @@ def create_network( repo = "xahaud" commit_hash = get_commit_hash_from_server_version(build_server, build_version) content_bytes = download_file_at_commit_or_tag( - owner, repo, commit_hash, "src/ripple/protocol/impl/Feature.cpp", "include/xrpl/protocol/detail/features.macro" + owner, + repo, + commit_hash, + "src/ripple/protocol/impl/Feature.cpp", + "include/xrpl/protocol/detail/features.macro", ) content = get_feature_lines_from_content(content_bytes) url: str = f"{build_server}/{build_version}" @@ -593,9 +596,7 @@ def enable_node_amendment( port: int = get_node_port(int(node_id), node_type) json_str: str = json.dumps(command) escaped_str = json_str.replace('"', '\\"') - command: str = ( - f'curl -X POST -H "Content-Type: application/json" -d "{escaped_str}" http://localhost:{port}' # noqa: E501 - ) + command: str = f'curl -X POST -H "Content-Type: application/json" -d "{escaped_str}" http://localhost:{port}' # noqa: E501 run_command(f"{basedir}/{name}", command) @@ -622,7 +623,11 @@ def create_ansible( repo = "xahaud" commit_hash = get_commit_hash_from_server_version(build_server, build_version) content_bytes = download_file_at_commit_or_tag( - owner, repo, commit_hash, "src/ripple/protocol/impl/Feature.cpp", "include/xrpl/protocol/detail/features.macro" + owner, + repo, + commit_hash, + "src/ripple/protocol/impl/Feature.cpp", + "include/xrpl/protocol/detail/features.macro", ) content = get_feature_lines_from_content(content_bytes) url: str = f"{build_server}/{build_version}" @@ -807,11 +812,11 @@ def create_ansible( f"{basedir}/{name}-cluster/{c_name}/config/", ssh_port, [ - f'RPC_PUBLIC: {ports[0].split(":")[0]}', - f'RPC_ADMIN: {ports[1].split(":")[0]}', - f'WS_PUBLIC: {ports[2].split(":")[0]}', - f'WS_ADMIN: {ports[3].split(":")[0]}', - f'PEER: {ports[4].split(":")[0]}', + f"RPC_PUBLIC: {ports[0].split(':')[0]}", + f"RPC_ADMIN: {ports[1].split(':')[0]}", + f"WS_PUBLIC: {ports[2].split(':')[0]}", + f"WS_ADMIN: {ports[3].split(':')[0]}", + f"PEER: {ports[4].split(':')[0]}", ], int(ports[2].split(":")[-1]), int(ports[4].split(":")[-1]), @@ -861,11 +866,11 @@ def create_ansible( f"{basedir}/{name}-cluster/{c_name}/config/", ssh_port, [ - f'RPC_PUBLIC: {ports[0].split(":")[0]}', - f'RPC_ADMIN: {ports[1].split(":")[0]}', - f'WS_PUBLIC: {ports[2].split(":")[0]}', - f'WS_ADMIN: {ports[3].split(":")[0]}', - f'PEER: {ports[4].split(":")[0]}', + f"RPC_PUBLIC: {ports[0].split(':')[0]}", + f"RPC_ADMIN: {ports[1].split(':')[0]}", + f"WS_PUBLIC: {ports[2].split(':')[0]}", + f"WS_ADMIN: {ports[3].split(':')[0]}", + f"PEER: {ports[4].split(':')[0]}", ], int(ports[2].split(":")[-1]), int(ports[4].split(":")[-1]), @@ -1144,7 +1149,10 @@ def create_local_network( elif os.path.exists(macro_path): content = get_feature_lines_from_path(macro_path) else: - print(f"{bcolors.RED}Error: Cannot find features file at {local_path} or {macro_path}") + print( + f"{bcolors.RED}Error: Cannot find features file \ + at {local_path} or {macro_path}" + ) print(f"Please run this command from your build directory.{bcolors.END}") return diff --git a/xrpld_netgen/utils/deploy_kit.py b/xrpld_netgen/utils/deploy_kit.py index 6e75977..e2625e8 100644 --- a/xrpld_netgen/utils/deploy_kit.py +++ b/xrpld_netgen/utils/deploy_kit.py @@ -1,12 +1,13 @@ #!/usr/bin/env python # coding: utf-8 -import requests -import re import os -import yaml +import re import shutil +import requests +import yaml + from .misc import bcolors @@ -293,8 +294,7 @@ def build_network_start_sh( for i in range(1, num_peers + 1): start_sh_content += f"cp xrpld.{name} pnode{i}/xrpld.{name}\n" start_sh_content += ( - "docker compose -f docker-compose.yml" - " up --build --force-recreate -d" + "docker compose -f docker-compose.yml up --build --force-recreate -d" ) return start_sh_content @@ -317,7 +317,9 @@ def build_network_stop_sh( stop_sh_content += "\n" stop_sh_content += 'if [ "$REMOVE_FLAG" = true ]; then \n' if num_validators > 0 and num_peers > 0: - stop_sh_content += "docker compose -f docker-compose.yml down --remove-orphans\n" # noqa: E501 + stop_sh_content += ( + "docker compose -f docker-compose.yml down --remove-orphans\n" # noqa: E501 + ) for i in range(1, num_validators + 1): stop_sh_content += f"rm -r vnode{i}/lib\n" @@ -350,54 +352,51 @@ def build_local_network_start_sh( start_sh_content += "# Start Explorer and VL services in Docker\n" start_sh_content += "echo 'Starting Docker services (Explorer & VL)...'\n" start_sh_content += ( - "docker compose -f docker-compose.yml" - " up --build --force-recreate -d\n\n" + "docker compose -f docker-compose.yml up --build --force-recreate -d\n\n" ) start_sh_content += "# Wait for services to be ready\n" start_sh_content += "sleep 2\n\n" # Get the absolute path to the cluster directory first start_sh_content += "# Get the absolute path to the cluster directory\n" - start_sh_content += "CLUSTER_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n" + start_sh_content += 'CLUSTER_DIR="$(cd "$(dirname "$0")" && pwd)"\n\n' # Find and copy binary to each node folder start_sh_content += "# Locate xrpld binary\n" - start_sh_content += f"if [ -f \"$CLUSTER_DIR/../{binary_name}\" ]; then\n" - start_sh_content += f" BINARY_PATH=\"$CLUSTER_DIR/../{binary_name}\"\n" + start_sh_content += f'if [ -f "$CLUSTER_DIR/../{binary_name}" ]; then\n' + start_sh_content += f' BINARY_PATH="$CLUSTER_DIR/../{binary_name}"\n' start_sh_content += f"elif command -v {binary_name} &> /dev/null; then\n" start_sh_content += f" BINARY_PATH=$(command -v {binary_name})\n" start_sh_content += "else\n" start_sh_content += f" echo 'Error: {binary_name} binary not found!'\n" start_sh_content += f" echo 'Please ensure {binary_name} is either:'\n" start_sh_content += ( - " echo ' 1. In the parent directory:" - f" $CLUSTER_DIR/../{binary_name}'\n" + f" echo ' 1. In the parent directory: $CLUSTER_DIR/../{binary_name}'\n" ) start_sh_content += ( - " echo ' 2. In your PATH" - f" (e.g., /usr/local/bin/{binary_name})'\n" + f" echo ' 2. In your PATH (e.g., /usr/local/bin/{binary_name})'\n" ) start_sh_content += " exit 1\n" start_sh_content += "fi\n\n" - start_sh_content += "echo \"Using binary: $BINARY_PATH\"\n\n" + start_sh_content += 'echo "Using binary: $BINARY_PATH"\n\n' start_sh_content += "# Copy xrpld binary to each node (if not already present)\n" for i in range(1, num_validators + 1): start_sh_content += ( - f"if [ ! -f \"vnode{i}/{binary_name}\" ]" - " || [ \"$BINARY_PATH\" -nt" - f" \"vnode{i}/{binary_name}\" ]; then\n" + f'if [ ! -f "vnode{i}/{binary_name}" ]' + ' || [ "$BINARY_PATH" -nt' + f' "vnode{i}/{binary_name}" ]; then\n' ) - start_sh_content += f" cp \"$BINARY_PATH\" vnode{i}/{binary_name}\n" + start_sh_content += f' cp "$BINARY_PATH" vnode{i}/{binary_name}\n' start_sh_content += f" echo 'Copied binary to vnode{i}'\n" start_sh_content += "fi\n" for i in range(1, num_peers + 1): start_sh_content += ( - f"if [ ! -f \"pnode{i}/{binary_name}\" ]" - " || [ \"$BINARY_PATH\" -nt" - f" \"pnode{i}/{binary_name}\" ]; then\n" + f'if [ ! -f "pnode{i}/{binary_name}" ]' + ' || [ "$BINARY_PATH" -nt' + f' "pnode{i}/{binary_name}" ]; then\n' ) - start_sh_content += f" cp \"$BINARY_PATH\" pnode{i}/{binary_name}\n" + start_sh_content += f' cp "$BINARY_PATH" pnode{i}/{binary_name}\n' start_sh_content += f" echo 'Copied binary to pnode{i}'\n" start_sh_content += "fi\n" start_sh_content += "\n" @@ -405,26 +404,26 @@ def build_local_network_start_sh( start_sh_content += "# Start validator nodes in background\n" for i in range(1, num_validators + 1): start_sh_content += f"echo 'Starting vnode{i} in background...'\n" - start_sh_content += f"cd \"$CLUSTER_DIR/vnode{i}\"\n" + start_sh_content += f'cd "$CLUSTER_DIR/vnode{i}"\n' start_sh_content += ( f"nohup ./{binary_name} --conf config/xrpld.cfg" " --ledgerfile config/genesis.json" " > /dev/null 2>&1 &\n" ) - start_sh_content += f"echo $! > \"$CLUSTER_DIR/vnode{i}/xrpld.pid\"\n" - start_sh_content += "cd \"$CLUSTER_DIR\"\n" + start_sh_content += f'echo $! > "$CLUSTER_DIR/vnode{i}/xrpld.pid"\n' + start_sh_content += 'cd "$CLUSTER_DIR"\n' start_sh_content += "\n# Start peer nodes in background\n" for i in range(1, num_peers + 1): start_sh_content += f"echo 'Starting pnode{i} in background...'\n" - start_sh_content += f"cd \"$CLUSTER_DIR/pnode{i}\"\n" + start_sh_content += f'cd "$CLUSTER_DIR/pnode{i}"\n' start_sh_content += ( f"nohup ./{binary_name} --conf config/xrpld.cfg" " --ledgerfile config/genesis.json" " > /dev/null 2>&1 &\n" ) - start_sh_content += f"echo $! > \"$CLUSTER_DIR/pnode{i}/xrpld.pid\"\n" - start_sh_content += "cd \"$CLUSTER_DIR\"\n" + start_sh_content += f'echo $! > "$CLUSTER_DIR/pnode{i}/xrpld.pid"\n' + start_sh_content += 'cd "$CLUSTER_DIR"\n' start_sh_content += "\n# Wait for nodes to start\n" start_sh_content += "sleep 3\n\n" @@ -441,7 +440,7 @@ def build_local_network_start_sh( start_sh_content += "echo 'Each node is running in the background.'\n" start_sh_content += ( "echo 'Use \"xrpld-netgen logs:local" - " --node \" to view logs" + ' --node " to view logs' " (e.g., --node vnode1).'\n" ) start_sh_content += "echo 'Use \"./stop.sh\" to stop all nodes.'\n" @@ -475,13 +474,13 @@ def build_local_network_stop_sh( stop_sh_content += "echo 'Stopping all xrpld nodes...'\n\n" stop_sh_content += "# Get the absolute path to the cluster directory\n" - stop_sh_content += "CLUSTER_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n" + stop_sh_content += 'CLUSTER_DIR="$(cd "$(dirname "$0")" && pwd)"\n\n' stop_sh_content += "# Stop validator nodes\n" for i in range(1, num_validators + 1): stop_sh_content += f"echo 'Stopping vnode{i}...'\n" - stop_sh_content += f"if [ -f \"$CLUSTER_DIR/vnode{i}/xrpld.pid\" ]; then\n" - stop_sh_content += f" PID=$(cat \"$CLUSTER_DIR/vnode{i}/xrpld.pid\")\n" + stop_sh_content += f'if [ -f "$CLUSTER_DIR/vnode{i}/xrpld.pid" ]; then\n' + stop_sh_content += f' PID=$(cat "$CLUSTER_DIR/vnode{i}/xrpld.pid")\n' stop_sh_content += " if ps -p $PID > /dev/null 2>&1; then\n" stop_sh_content += " kill $PID 2>/dev/null || true\n" stop_sh_content += " sleep 1\n" @@ -490,19 +489,19 @@ def build_local_network_stop_sh( stop_sh_content += " kill -9 $PID 2>/dev/null || true\n" stop_sh_content += " fi\n" stop_sh_content += " fi\n" - stop_sh_content += f" rm -f \"$CLUSTER_DIR/vnode{i}/xrpld.pid\"\n" + stop_sh_content += f' rm -f "$CLUSTER_DIR/vnode{i}/xrpld.pid"\n' stop_sh_content += "fi\n" stop_sh_content += ( "# Fallback: Find and kill any xrpld" f" process running in vnode{i} directory\n" ) - stop_sh_content += f"pkill -9 -f \"vnode{i}/xrpld\" 2>/dev/null || true\n" + stop_sh_content += f'pkill -9 -f "vnode{i}/xrpld" 2>/dev/null || true\n' stop_sh_content += "\n# Stop peer nodes\n" for i in range(1, num_peers + 1): stop_sh_content += f"echo 'Stopping pnode{i}...'\n" - stop_sh_content += f"if [ -f \"$CLUSTER_DIR/pnode{i}/xrpld.pid\" ]; then\n" - stop_sh_content += f" PID=$(cat \"$CLUSTER_DIR/pnode{i}/xrpld.pid\")\n" + stop_sh_content += f'if [ -f "$CLUSTER_DIR/pnode{i}/xrpld.pid" ]; then\n' + stop_sh_content += f' PID=$(cat "$CLUSTER_DIR/pnode{i}/xrpld.pid")\n' stop_sh_content += " if ps -p $PID > /dev/null 2>&1; then\n" stop_sh_content += " kill $PID 2>/dev/null || true\n" stop_sh_content += " sleep 1\n" @@ -511,13 +510,13 @@ def build_local_network_stop_sh( stop_sh_content += " kill -9 $PID 2>/dev/null || true\n" stop_sh_content += " fi\n" stop_sh_content += " fi\n" - stop_sh_content += f" rm -f \"$CLUSTER_DIR/pnode{i}/xrpld.pid\"\n" + stop_sh_content += f' rm -f "$CLUSTER_DIR/pnode{i}/xrpld.pid"\n' stop_sh_content += "fi\n" stop_sh_content += ( "# Fallback: Find and kill any xrpld" f" process running in pnode{i} directory\n" ) - stop_sh_content += f"pkill -9 -f \"pnode{i}/xrpld\" 2>/dev/null || true\n" + stop_sh_content += f'pkill -9 -f "pnode{i}/xrpld" 2>/dev/null || true\n' stop_sh_content += "\n# Wait for processes to terminate\n" stop_sh_content += "sleep 2\n\n" @@ -530,13 +529,11 @@ def build_local_network_stop_sh( # Clean up directories if --remove flag is used for i in range(1, num_validators + 1): stop_sh_content += ( - f" rm -rf vnode{i}/lib vnode{i}/log" - f" vnode{i}/xrpld vnode{i}/db\n" + f" rm -rf vnode{i}/lib vnode{i}/log vnode{i}/xrpld vnode{i}/db\n" ) for i in range(1, num_peers + 1): stop_sh_content += ( - f" rm -rf pnode{i}/lib pnode{i}/log" - f" pnode{i}/xrpld pnode{i}/db\n" + f" rm -rf pnode{i}/lib pnode{i}/log pnode{i}/xrpld pnode{i}/db\n" ) stop_sh_content += "else\n" diff --git a/xrpld_netgen/utils/misc.py b/xrpld_netgen/utils/misc.py index 512c714..6f6b9ea 100644 --- a/xrpld_netgen/utils/misc.py +++ b/xrpld_netgen/utils/misc.py @@ -1,16 +1,16 @@ #!/usr/bin/env python # coding: utf-8 -import os +import hashlib import json -import requests +import os +import shlex import shutil import subprocess -import shlex -import hashlib import sys +from typing import Any, Dict, List, Tuple -from typing import Dict, Any, Tuple, List +import requests class bcolors: @@ -68,10 +68,7 @@ def run_start(cmd: List[str], protocol: str, version: str, type: str): ) sys.exit(1) except FileNotFoundError: - print( - f"{bcolors.RED}❌ The file {cmd[0]} does not exist or cannot be " - f"found." - ) + print(f"{bcolors.RED}❌ The file {cmd[0]} does not exist or cannot be found.") sys.exit(1) except OSError as e: print(f"{bcolors.RED}❌ An OS error occurred: {e}") @@ -98,10 +95,7 @@ def run_stop(cmd: List[str]): ) sys.exit(1) except FileNotFoundError: - print( - f"{bcolors.RED}❌ The file {cmd[0]} does not exist or cannot be " - f"found." - ) + print(f"{bcolors.RED}❌ The file {cmd[0]} does not exist or cannot be found.") sys.exit(1) except OSError as e: print(f"{bcolors.RED}❌ An OS error occurred: {e}") @@ -214,8 +208,7 @@ def run_local_logs(node: str = None): log_path = "config/debug.log" if not os.path.exists(log_path): print( - f"{bcolors.RED}Error: Log file not found at " - f"{log_path}{bcolors.END}" + f"{bcolors.RED}Error: Log file not found at {log_path}{bcolors.END}" ) print() print( @@ -331,7 +324,9 @@ def download_json(url: str, destination_dir: str) -> Dict[str, Any]: raise ValueError(f"Failed to download file from {url}") -def save_local_config(protocol: str, cfg_path: str, cfg_out: str, validators_out: str) -> None: +def save_local_config( + protocol: str, cfg_path: str, cfg_out: str, validators_out: str +) -> None: with open(f"{cfg_path}/{protocol}d.cfg", "w") as text_file: text_file.write(cfg_out) diff --git a/xrpld_netgen/xrpld_cfg.py b/xrpld_netgen/xrpld_cfg.py index f574272..2d96b4c 100644 --- a/xrpld_netgen/xrpld_cfg.py +++ b/xrpld_netgen/xrpld_cfg.py @@ -2,8 +2,8 @@ # coding: utf-8 import sys -from typing import List, Dict from dataclasses import dataclass +from typing import Dict, List @dataclass