Skip to content

Commit

Permalink
feat!: Handle 0.7 breaking changes and updates [SBK-369] (#46)
Browse files Browse the repository at this point in the history
* chore: update versions

* chore: unpin ethpm-types

* chore: bump eth-ape

* chore: more updates

* chore: upgrade taskiq

* fix: unused import

* fix: update to new ape cli network option and connection class

* docs: add a note about the use of Annotated, which was only added in 3.9

* refactor: use existing default

* fix(cli): ensure that default loads from envvar correctly

NOTE: raises if mismatch

---------

Co-authored-by: fubuloubu <[email protected]>
  • Loading branch information
NotPeopling2day and fubuloubu authored Jan 2, 2024
1 parent 7f2c4d1 commit 1092046
Show file tree
Hide file tree
Showing 9 changed files with 60 additions and 39 deletions.
1 change: 0 additions & 1 deletion .mdformat.toml

This file was deleted.

10 changes: 5 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.2.0
rev: v4.5.0
hooks:
- id: check-yaml

Expand All @@ -10,24 +10,24 @@ repos:
- id: isort

- repo: https://github.com/psf/black
rev: 23.7.0
rev: 23.12.0
hooks:
- id: black
name: black

- repo: https://github.com/pycqa/flake8
rev: 5.0.4
rev: 6.1.0
hooks:
- id: flake8

- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.4.1
rev: v1.7.1
hooks:
- id: mypy
additional_dependencies: [types-setuptools, pydantic]

- repo: https://github.com/executablebooks/mdformat
rev: 0.7.14
rev: 0.7.17
hooks:
- id: mdformat
additional_dependencies: [mdformat-gfm, mdformat-frontmatter]
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ To run your bot against a live network, this SDK includes a simple runner you ca
$ silverback run "example:app" --network :mainnet:alchemy
```

**NOTE**: The example is designed to work with Python 3.9+, and we suggest using 3.11+ for speed.

## Docker Usage

```sh
Expand Down
2 changes: 1 addition & 1 deletion example.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Annotated
from typing import Annotated # NOTE: Only Python 3.9+

from ape import chain
from ape.api import BlockAPI
Expand Down
20 changes: 11 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
extras_require = {
"test": [ # `test` GitHub Action jobs uses this
"pytest>=6.0", # Core testing package
"pytest-xdist", # multi-process runner
"pytest-xdist", # Multi-process runner
"pytest-cov", # Coverage analyzer plugin
"hypothesis>=6.2.0,<7.0", # Strategy-based fuzzer
],
"lint": [
"black>=23.7.0", # auto-formatter and linter
"mypy>=1.4.1,<2", # Static type analyzer
"black>=23.12.0,<24", # Auto-formatter and linter
"mypy>=1.7.1,<2", # Static type analyzer
"types-setuptools", # Needed for mypy type shed
"flake8>=5.0.4", # Style linter
"isort>=5.10.1", # Import sorting linter
"mdformat>=0.7.16", # Auto-formatter for markdown
"flake8>=6.1.0,<7", # Style linter
"isort>=5.10.1,<6", # Import sorting linter
"mdformat>=0.7.17", # Auto-formatter for markdown
"mdformat-gfm>=0.3.5", # Needed for formatting GitHub-flavored markdown
"mdformat-frontmatter>=0.4.1", # Needed for frontmatters-style headers in issue templates
"mdformat-pyproject>=0.0.1", # So we can keep config for mdformat in `pyproject.toml`
"mdformat-pyproject>=0.0.1", # Allows configuring in pyproject.toml
],
"doc": [
"myst-parser>=1.0.0,<2", # Parse markdown docs
Expand Down Expand Up @@ -67,9 +67,11 @@
url="https://github.com/ApeWorX/silverback",
include_package_data=True,
install_requires=[
"eth-ape>=0.6.19,<1.0",
"taskiq[metrics]>=0.6.0,<0.7.0",
"click", # Use same version as eth-ape
"eth-ape>=0.7.0,<1.0",
"eth-pydantic-types", # Use same version as eth-ape
"pydantic_settings", # Use same version as eth-ape
"taskiq[metrics]>=0.10.4,<0.11.0",
],
entry_points={
"console_scripts": ["silverback=silverback._cli:cli"],
Expand Down
48 changes: 34 additions & 14 deletions silverback/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
from concurrent.futures import ThreadPoolExecutor

import click
from ape.cli import AccountAliasPromptChoice, ape_cli_context, network_option, verbosity_option
from ape.cli import (
AccountAliasPromptChoice,
ConnectedProviderCommand,
ape_cli_context,
network_option,
verbosity_option,
)
from ape.exceptions import Abort
from taskiq import AsyncBroker
from taskiq.cli.worker.run import shutdown_broker
from taskiq.receiver import Receiver
Expand Down Expand Up @@ -36,10 +43,18 @@ def _account_callback(ctx, param, val):


def _network_callback(ctx, param, val):
if val:
os.environ["SILVERBACK_NETWORK_CHOICE"] = val
# NOTE: Make sure both of these have the same setting
if env_network_choice := os.environ.get("SILVERBACK_NETWORK_CHOICE"):
if val.network_choice != env_network_choice:
raise Abort(
f"Network choice '{val.network_choice}' does not "
f"match environment variable '{env_network_choice}'."
)

# else it matches, no issue

else:
val = os.environ.get("SILVERBACK_NETWORK_CHOICE", "")
os.environ["SILVERBACK_NETWORK_CHOICE"] = val.network_choice

return val

Expand All @@ -64,10 +79,13 @@ async def run_worker(broker: AsyncBroker, worker_count=2, shutdown_timeout=90):
await shutdown_broker(broker, shutdown_timeout)


@cli.command(help="Run Silverback application client")
@cli.command(cls=ConnectedProviderCommand, help="Run Silverback application client")
@ape_cli_context()
@verbosity_option()
@network_option(default=None, callback=_network_callback)
@network_option(
default=os.environ.get("SILVERBACK_NETWORK_CHOICE", "auto"),
callback=_network_callback,
)
@click.option("--account", type=AccountAliasPromptChoice(), callback=_account_callback)
@click.option(
"--runner",
Expand All @@ -76,22 +94,24 @@ async def run_worker(broker: AsyncBroker, worker_count=2, shutdown_timeout=90):
)
@click.option("-x", "--max-exceptions", type=int, default=3)
@click.argument("path")
def run(cli_ctx, network, account, runner, max_exceptions, path):
with cli_ctx.network_manager.parse_network_choice(network):
app = import_from_string(path)
runner = runner(app, max_exceptions=max_exceptions)
asyncio.run(runner.run())
def run(cli_ctx, account, runner, max_exceptions, path):
app = import_from_string(path)
runner = runner(app, max_exceptions=max_exceptions)
asyncio.run(runner.run())


@cli.command(help="Run Silverback application task workers")
@cli.command(cls=ConnectedProviderCommand, help="Run Silverback application task workers")
@ape_cli_context()
@verbosity_option()
@network_option(default=None, callback=_network_callback)
@network_option(
default=os.environ.get("SILVERBACK_NETWORK_CHOICE", "auto"),
callback=_network_callback,
)
@click.option("--account", type=AccountAliasPromptChoice(), callback=_account_callback)
@click.option("-w", "--workers", type=int, default=2)
@click.option("-x", "--max-exceptions", type=int, default=3)
@click.option("-s", "--shutdown_timeout", type=int, default=90)
@click.argument("path")
def worker(cli_ctx, network, account, workers, max_exceptions, shutdown_timeout, path):
def worker(cli_ctx, account, workers, max_exceptions, shutdown_timeout, path):
app = import_from_string(path)
asyncio.run(run_worker(app.broker, worker_count=workers, shutdown_timeout=shutdown_timeout))
8 changes: 4 additions & 4 deletions silverback/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def get_startup_handler(self) -> Optional[AsyncTaskiqDecoratedTask]:
Returns:
Optional[AsyncTaskiqDecoratedTask]: Returns decorated task, if one has been created.
"""
return self.broker.available_tasks.get("silverback_startup")
return self.broker.find_task("silverback_startup")

def get_shutdown_handler(self) -> Optional[AsyncTaskiqDecoratedTask]:
"""
Expand All @@ -136,7 +136,7 @@ def get_shutdown_handler(self) -> Optional[AsyncTaskiqDecoratedTask]:
Returns:
Optional[AsyncTaskiqDecoratedTask]: Returns decorated task, if one has been created.
"""
return self.broker.available_tasks.get("silverback_shutdown")
return self.broker.find_task("silverback_shutdown")

def get_block_handler(self) -> Optional[AsyncTaskiqDecoratedTask]:
"""
Expand All @@ -145,7 +145,7 @@ def get_block_handler(self) -> Optional[AsyncTaskiqDecoratedTask]:
Returns:
Optional[AsyncTaskiqDecoratedTask]: Returns decorated task, if one has been created.
"""
return self.broker.available_tasks.get("block")
return self.broker.find_task("block")

def get_event_handler(
self, event_target: AddressType, event_name: str
Expand All @@ -160,7 +160,7 @@ def get_event_handler(
Returns:
Optional[AsyncTaskiqDecoratedTask]: Returns decorated task, if one has been created.
"""
return self.broker.available_tasks.get(f"{event_target}/event/{event_name}")
return self.broker.find_task(f"{event_target}/event/{event_name}")

def on_(
self,
Expand Down
2 changes: 1 addition & 1 deletion silverback/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def pre_execute(self, message: TaskiqMessage) -> TaskiqMessage:

elif "event" in message.task_name:
# NOTE: Just in case the user doesn't specify type as `ContractLog`
message.args[0] = ContractLog.parse_obj(message.args[0])
message.args[0] = ContractLog.model_validate(message.args[0])

logger.info(f"{self._create_label(message)} - Started")
return message
Expand Down
6 changes: 2 additions & 4 deletions silverback/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from ape.api import AccountAPI, ProviderContextManager
from ape.utils import ManagerAccessMixin
from pydantic import BaseSettings
from pydantic_settings import BaseSettings, SettingsConfigDict
from taskiq import AsyncBroker, InMemoryBroker, PrometheusMiddleware, TaskiqMiddleware

from ._importer import import_from_string
Expand Down Expand Up @@ -38,9 +38,7 @@ class Settings(BaseSettings, ManagerAccessMixin):
# Used for persistent store
PERSISTENCE_CLASS: Optional[str] = None

class Config:
env_prefix = "SILVERBACK_"
case_sensitive = True
model_config = SettingsConfigDict(env_prefix="SILVERBACK_", case_sensitive=True)

def get_broker(self) -> AsyncBroker:
broker_class = import_from_string(self.BROKER_CLASS)
Expand Down

0 comments on commit 1092046

Please sign in to comment.