Skip to content

chore: update hathorlib to v0.14.1, Python to 3.11 and modernize dependencies - #161

Merged
luislhl merged 10 commits into
masterfrom
chore/update-hathorlib-0.14.1
Mar 18, 2026
Merged

chore: update hathorlib to v0.14.1, Python to 3.11 and modernize dependencies#161
luislhl merged 10 commits into
masterfrom
chore/update-hathorlib-0.14.1

Conversation

@luislhl

@luislhl luislhl commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

Acceptance Criteria

  • We should upgrade hathorlib to v0.14.1
  • Because of some other changes I wasn't aware of in hathorlib that were included in v0.14.1, I also had to update the python version in tx-mining-service to 3.11 at minimum, but with 3.12 in the CI/CD as well. This caused a cascading effect of dependencies breaking which I had to deal with.
  • Set HATHOR_CONFIG_FILE when running with --testnet, instead of TXMINING_CONFIG_FILE, because of feat: pydantic settings hathor-core#1600

Summary by CodeRabbit

  • Chores

    • Minimum Python requirement raised to 3.11; runtime images and CI updated (CI matrix includes 3.12).
    • Dependency cleanup and updates, added healthcheck and setuptools constraint; dev tooling reorganized and Black added.
  • Tests

    • Test suite modernized to use unittest's async support and removed legacy async test dependency; added a synthetic clock test utility for reliable async timing.
  • Documentation

    • Examples/doctests updated for a stable object representation.

@luislhl
luislhl requested a review from msbrogli as a code owner March 2, 2026 20:44
@luislhl luislhl self-assigned this Mar 2, 2026
@luislhl luislhl moved this from Todo to In Progress (Done) in Hathor Network Mar 2, 2026
@luislhl
luislhl force-pushed the chore/update-hathorlib-0.14.1 branch 2 times, most recently from 7d003be to 131fda2 Compare March 2, 2026 20:48
@github-project-automation github-project-automation Bot moved this from In Progress (Done) to In Review (WIP) in Hathor Network Mar 2, 2026
@luislhl
luislhl requested a review from r4mmer March 3, 2026 15:32
@coderabbitai

coderabbitai Bot commented Mar 17, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

CI, Docker, and pyproject bumped to Python 3.11+; tests migrated off asynctest to asyncio-native patterns (unittest.IsolatedAsyncioTestCase or a new ClockedTestCase); tests/utils adds an advanceable synthetic clock to patch loop time.

Changes

Cohort / File(s) Summary
CI Configuration
\.github/workflows/main.yml
Python matrix updated from 3.9/3.103.11/3.12; coverage upload condition adjusted to trigger for matrix.python == '3.11' on ubuntu-latest.
Container Build
Dockerfile
Base image changed from python:3.9-alpinepython:3.11-alpine; site-packages copy paths updated to Python 3.11; added COPY main.py log.conf ./ and ENTRYPOINT ["python", "-m", "main"].
Project metadata & deps
pyproject.toml
Python requirement bumped to >=3.11,<4.0; removed asynctest and dataclasses; added/updated deps (e.g., hathorlib ^0.14.1 with extras, python-healthchecklib ^0.1.0, numpy ^1.26.0); dev deps reorganized under [tool.poetry.group.dev].
Test framework migration
tests/test_filters.py, tests/test_healthcheck.py, tests/test_prometheus.py, tests/test_manager.py, tests/test_time.py
Replaced asynctest with unittest/IsolatedAsyncioTestCase or ClockedTestCase; removed custom AsyncMock shim; tests converted to async def and updated to use await instead of loop.run_until_complete/legacy scheduling.
Test utilities
tests/utils.py
Added ClockedTestCase (an IsolatedAsyncioTestCase) and synthetic Clock that patches the running loop's time(); provides asyncSetUp and advance(seconds) to advance fake time and drain callbacks.
Small util repr
txstratum/utils.py
Added __repr__ to MaxSizeOrderedDict to produce a stable representation across Python versions; no behavioral changes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • glevco

Poem

🐇 I hopped through code with nimble feet,

Bumped the Python and tuned the beat.
Clocks that tick when I command,
Tests now race at my demand.
A carrot-coded, cozy feat!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main objectives of the pull request: updating hathorlib to v0.14.1, upgrading Python to 3.11, and modernizing dependencies.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/update-hathorlib-0.14.1
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Dockerfile (1)

16-24: ⚠️ Potential issue | 🟠 Major

Run the final container as a non-root user.

The final stage has no USER directive, so it runs as root by default. This is a security hardening gap for production containers.

🔒 Proposed hardening patch
 FROM python:3.11-alpine
 
+WORKDIR /app
 COPY --from=build /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
 RUN apk add libgcc
 
 COPY txstratum/ ./txstratum
 COPY main.py log.conf ./
 
+RUN addgroup -S app && adduser -S -G app app \
+  && chown -R app:app /app
+USER app
+
 ENTRYPOINT ["python", "-m", "main"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Dockerfile` around lines 16 - 24, The Dockerfile final stage runs as root (no
USER directive) which is insecure; create a non-root runtime user and group
(e.g., add a user like "appuser"), ensure application files copied by COPY
(/txstratum, main.py, log.conf and site-packages) are owned by that user (chown)
and switch to it before ENTRYPOINT by adding a USER directive; update the
Dockerfile around the COPY and ENTRYPOINT steps so ownership is set and the
final image uses USER appuser to run the ENTRYPOINT ["python", "-m", "main"].
pyproject.toml (1)

18-27: ⚠️ Potential issue | 🔴 Critical

asynctest = "^0.13.0" is incompatible with Python 3.11+ and will break installation.

Line 18 enforces python = ">=3.11,<4.0", but asynctest 0.13.0 only declares support for Python 3.5–3.7 per PyPI metadata. Either upgrade asynctest to a version supporting 3.11+, or remove it if no longer needed. Note: numpy is not present in the current dependency list.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyproject.toml` around lines 18 - 27, pyproject.toml declares Python >=3.11
but lists asynctest = "^0.13.0", which is incompatible with 3.11; update
pyproject.toml to either remove the asynctest dependency if it's unused or
replace it with a Python-3.11-compatible test async library (e.g., switch to
pytest-asyncio or a maintained fork) and update any test imports/usages
accordingly (look for references to "asynctest" in tests and test config), then
bump the dependency entry or delete the line so the declared python version and
test dependency are consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@Dockerfile`:
- Around line 16-24: The Dockerfile final stage runs as root (no USER directive)
which is insecure; create a non-root runtime user and group (e.g., add a user
like "appuser"), ensure application files copied by COPY (/txstratum, main.py,
log.conf and site-packages) are owned by that user (chown) and switch to it
before ENTRYPOINT by adding a USER directive; update the Dockerfile around the
COPY and ENTRYPOINT steps so ownership is set and the final image uses USER
appuser to run the ENTRYPOINT ["python", "-m", "main"].

In `@pyproject.toml`:
- Around line 18-27: pyproject.toml declares Python >=3.11 but lists asynctest =
"^0.13.0", which is incompatible with 3.11; update pyproject.toml to either
remove the asynctest dependency if it's unused or replace it with a
Python-3.11-compatible test async library (e.g., switch to pytest-asyncio or a
maintained fork) and update any test imports/usages accordingly (look for
references to "asynctest" in tests and test config), then bump the dependency
entry or delete the line so the declared python version and test dependency are
consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26353f1c-3900-4ce7-acf0-5338a3288ff6

📥 Commits

Reviewing files that changed from the base of the PR and between a677e3b and 79a87cd.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (3)
  • .github/workflows/main.yml
  • Dockerfile
  • pyproject.toml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
tests/test_prometheus.py (1)

56-66: Consider storing the task reference for cleaner semantics.

The static analysis flags that asyncio.ensure_future() return value is not stored. While the current polling approach works, storing the task reference would be more explicit.

♻️ Optional refactor
     async def _run_all_pending_events(self):
         """Run all pending events."""
         async def _fn():
             self.ran_all = True

-        asyncio.ensure_future(_fn())
+        task = asyncio.ensure_future(_fn())

         while getattr(self, "ran_all", False) is False:
             await asyncio.sleep(0.1)

         self.ran_all = False
+        return task
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_prometheus.py` around lines 56 - 66, The helper
_run_all_pending_events currently calls asyncio.ensure_future(_fn()) without
keeping the returned Task; change it to store the Task (e.g., task =
asyncio.create_task(_fn()) or task = asyncio.ensure_future(_fn())) so the task
reference is retained, and then either await task or cancel/cleanup it after
use; update the logic around getattr(self, "ran_all", False) and setting
self.ran_all = False to ensure the stored task is awaited or properly cancelled
to avoid unreferenced background tasks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pyproject.toml`:
- Line 27: The pyproject dependency declaration for "hathorlib" includes an
extras spec that may not exist in version 0.14.1; inspect the dependency line
referencing hathorlib (hathorlib = {version = "^0.14.1", extras = ["client"]})
and either remove the extras key entirely or verify upstream that version 0.14.1
provides the "client" extra and update the version to one that does if needed;
ensure the final pyproject.toml uses either hathorlib = "^0.14.1" or a
version+extras combination confirmed to exist.
- Line 26: The setuptools version constraint ("setuptools = \">=68.0,<71\"") is
overly restrictive; either relax it to allow modern stable releases (for example
change to "setuptools = \">=68.0,<83\"" or simply ">=68.0") or explicitly
document why the "<71" cap is required; update the pyproject.toml line for
"setuptools" accordingly or add a comment above that line describing the
compatibility reason and the affected dependency if the cap must remain.

In `@tests/test_filters.py`:
- Line 9: The import line in tests/test_filters.py includes an unused symbol
MagicMock; remove MagicMock from the import so only AsyncMock is imported (i.e.,
change "from unittest.mock import AsyncMock, MagicMock" to import only
AsyncMock) and run the tests to ensure there are no other references to
MagicMock in this file.

---

Nitpick comments:
In `@tests/test_prometheus.py`:
- Around line 56-66: The helper _run_all_pending_events currently calls
asyncio.ensure_future(_fn()) without keeping the returned Task; change it to
store the Task (e.g., task = asyncio.create_task(_fn()) or task =
asyncio.ensure_future(_fn())) so the task reference is retained, and then either
await task or cancel/cleanup it after use; update the logic around getattr(self,
"ran_all", False) and setting self.ran_all = False to ensure the stored task is
awaited or properly cancelled to avoid unreferenced background tasks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8ebe9ab4-920f-42e5-94f9-4a7792d4c6ae

📥 Commits

Reviewing files that changed from the base of the PR and between 79a87cd and 3622f10.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • pyproject.toml
  • tests/test_filters.py
  • tests/test_healthcheck.py
  • tests/test_manager.py
  • tests/test_prometheus.py
  • tests/test_time.py
  • tests/utils.py

Comment thread pyproject.toml Outdated
Comment thread pyproject.toml
Comment thread tests/test_filters.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
pyproject.toml (1)

27-27: ⚠️ Potential issue | 🟠 Major

hathorlib extra "client" still looks unsupported in 0.14.1.

Line 27 keeps extras = ["client"], but PyPI metadata for hathorlib==0.14.1 currently reports provides_extra: null. Please remove the extra or move to a release that explicitly exports it.
Source: https://pypi.org/pypi/hathorlib/0.14.1/json

🔧 Proposed fix
-hathorlib = {version = "^0.14.1", extras = ["client"]}
+hathorlib = "^0.14.1"
#!/bin/bash
# Verify whether hathorlib 0.14.1 exposes extras metadata
curl -s https://pypi.org/pypi/hathorlib/0.14.1/json | jq '.info.version, .info.provides_extra, .info.requires_dist'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pyproject.toml` at line 27, The dependency declaration hathorlib = {version =
"^0.14.1", extras = ["client"]} is incorrect because version 0.14.1 does not
expose the "client" extra; update pyproject.toml by removing the extras field
from the Hathor dependency (change to hathorlib = "^0.14.1" or the equivalent
table form without extras) or replace the version with a specific release that
documents and provides the "client" extra; ensure you update the same dependency
entry (hathorlib) and run dependency resolution to verify the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/test_prometheus.py`:
- Around line 62-65: Replace the fire-and-forget asyncio.ensure_future(_fn())
and the polling loop that waits on self.ran_all with an explicitly created task
and awaiting it: create the task with asyncio.create_task(_fn()) (keep reference
to the task variable), then await that task instead of the while/getattr loop so
task completion and exceptions propagate properly; update the test to remove the
sleep-poll loop and use the stored task reference to await completion and
optionally handle/inspect exceptions from the task.

In `@tests/utils.py`:
- Around line 65-71: The advance() helper currently uses a fixed for-loop of 100
iterations which can fail to drain deep callback chains; change it to repeatedly
await asyncio.sleep(0) until the event loop has no more ready callbacks.
Concretely, in advance() (which adjusts self.loop._test_clock_offset) replace
the for _ in range(100) loop with a while loop that checks the loop's ready
queue (e.g. inspect self.loop._ready or equivalent) and breaks only when that
queue is empty, yielding each iteration with await asyncio.sleep(0) so all
chained call_later()/callbacks are drained.

---

Duplicate comments:
In `@pyproject.toml`:
- Line 27: The dependency declaration hathorlib = {version = "^0.14.1", extras =
["client"]} is incorrect because version 0.14.1 does not expose the "client"
extra; update pyproject.toml by removing the extras field from the Hathor
dependency (change to hathorlib = "^0.14.1" or the equivalent table form without
extras) or replace the version with a specific release that documents and
provides the "client" extra; ensure you update the same dependency entry
(hathorlib) and run dependency resolution to verify the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 65d1e14f-ea6b-416b-ba2a-2514f55d2334

📥 Commits

Reviewing files that changed from the base of the PR and between 3622f10 and 1d43844.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • pyproject.toml
  • tests/test_filters.py
  • tests/test_prometheus.py
  • tests/test_time.py
  • tests/utils.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/test_time.py

Comment thread tests/test_prometheus.py Outdated
Comment thread tests/utils.py
@luislhl
luislhl requested review from glevco and r4mmer and removed request for msbrogli March 17, 2026 22:56
@luislhl
luislhl force-pushed the chore/update-hathorlib-0.14.1 branch from 515033c to c33034b Compare March 17, 2026 23:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/test_prometheus.py (1)

56-67: Store the task reference to silence Ruff warning.

The static analysis tool correctly identifies that the return value of asyncio.create_task() should be stored. While the current implementation works, storing the reference is cleaner and prevents the task from being garbage collected prematurely in edge cases.

Optional fix to store task reference
     async def _run_all_pending_events(self):
         """Run all pending events."""
 
         async def _fn():
             self.ran_all = True
 
-        asyncio.create_task(_fn())
+        task = asyncio.create_task(_fn())
 
         while getattr(self, "ran_all", False) is False:
             await asyncio.sleep(0)
 
         self.ran_all = False
+        # Ensure task completed (should be instant since ran_all is True)
+        await task
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_prometheus.py` around lines 56 - 67, The helper method
_run_all_pending_events creates a background coroutine with
asyncio.create_task() but doesn't store the returned Task, triggering a Ruff
warning; update _run_all_pending_events to assign the result of
asyncio.create_task(_fn()) to a local variable (e.g., task) so the Task
reference is retained until completion, leaving the rest of the loop logic
(polling ran_all and resetting it) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@tests/test_prometheus.py`:
- Around line 56-67: The helper method _run_all_pending_events creates a
background coroutine with asyncio.create_task() but doesn't store the returned
Task, triggering a Ruff warning; update _run_all_pending_events to assign the
result of asyncio.create_task(_fn()) to a local variable (e.g., task) so the
Task reference is retained until completion, leaving the rest of the loop logic
(polling ran_all and resetting it) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ef171d9-b953-495b-b363-40467ec1eb00

📥 Commits

Reviewing files that changed from the base of the PR and between 75c4cc3 and c33034b.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .github/workflows/main.yml
  • Dockerfile
  • pyproject.toml
  • tests/test_filters.py
  • tests/test_healthcheck.py
  • tests/test_manager.py
  • tests/test_prometheus.py
  • tests/test_time.py
  • tests/utils.py
  • txstratum/utils.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/main.yml
  • tests/test_manager.py
  • tests/test_time.py
  • tests/test_healthcheck.py

@luislhl
luislhl force-pushed the chore/update-hathorlib-0.14.1 branch from c928ba5 to 3b048df Compare March 18, 2026 15:46
@luislhl luislhl moved this from In Review (WIP) to In Progress (Done) in Hathor Network Mar 18, 2026
@luislhl luislhl changed the title chore: update hathorlib to v0.14.1 chore: update hathorlib to v0.14.1 and modernize dependencies Mar 18, 2026
@luislhl luislhl changed the title chore: update hathorlib to v0.14.1 and modernize dependencies chore: update hathorlib to v0.14.1, Python to 3.11 and modernize dependencies Mar 18, 2026
@github-project-automation github-project-automation Bot moved this from In Progress (Done) to In Review (WIP) in Hathor Network Mar 18, 2026
@luislhl luislhl moved this from In Review (WIP) to In Review (Done) in Hathor Network Mar 18, 2026
@luislhl
luislhl merged commit 0b87cd5 into master Mar 18, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from In Review (Done) to Waiting to be deployed in Hathor Network Mar 18, 2026
@luislhl
luislhl deleted the chore/update-hathorlib-0.14.1 branch March 18, 2026 18:51
@luislhl luislhl moved this from Waiting to be deployed to Done in Hathor Network Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants