Skip to content

Commit

Permalink
Use latest post-v0.7.0 SDK - fix breaking changes (#173)
Browse files Browse the repository at this point in the history
* Internal: Add test for file upload

* Fix: Unit test docstring

* Problem: GH Action failing due to Python and Aleph SDK dependencies

Solution: Restrict to Python 3.11 on macOS and use current 0.7.0 release of Aleph SDK

* Problem: aleph-client was using main branch of aleph-sdk-python, which includes breaking changes relative to v0.7.0

Solution: Update usage of the SDK to reflect and accommodate breaking changes; use AsyncTyper class to implement async commands

* Fix: aggregate.py and files.py to use async functions.

* Replace subprocess calls with runner.invoke

---------

Co-authored-by: 1yam <[email protected]>
  • Loading branch information
MHHukiewitz and 1yam authored Nov 10, 2023
1 parent 74fba9c commit 28a6558
Show file tree
Hide file tree
Showing 11 changed files with 177 additions and 106 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ jobs:
brew update
brew tap cuber/homebrew-libsecp256k1
brew install libsecp256k1
- name: Set up Python for macOS
if: startsWith(matrix.os, 'macos')
uses: actions/setup-python@v2
with:
python-version: 3.11


- name: Install required system packages only for Ubuntu Linux
if: startsWith(matrix.os, 'ubuntu-')
Expand Down
5 changes: 4 additions & 1 deletion src/aleph_client/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

import typer

from aleph_client.utils import AsyncTyper
from .commands import about, account, aggregate, files, message, program

app = typer.Typer()
app = AsyncTyper()


@app.callback()
def common(
Expand All @@ -16,6 +18,7 @@ def common(
):
pass


app.add_typer(account.app, name="account", help="Manage account")
app.add_typer(
aggregate.app, name="aggregate", help="Manage aggregate messages on aleph.im"
Expand Down
Empty file added src/aleph_client/account.py
Empty file.
4 changes: 3 additions & 1 deletion src/aleph_client/commands/about.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import typer
from pkg_resources import get_distribution

app = typer.Typer()
from aleph_client.utils import AsyncTyper

app = AsyncTyper()


def get_version(value: bool):
Expand Down
3 changes: 2 additions & 1 deletion src/aleph_client/commands/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@

from aleph_client.commands import help_strings
from aleph_client.commands.utils import setup_logging
from aleph_client.utils import AsyncTyper

logger = logging.getLogger(__name__)
app = typer.Typer()
app = AsyncTyper()


@app.command()
Expand Down
22 changes: 13 additions & 9 deletions src/aleph_client/commands/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@

import typer
from aleph.sdk.account import _load_account
from aleph.sdk.client import AuthenticatedAlephClient
from aleph.sdk.client import AuthenticatedAlephHttpClient
from aleph.sdk.conf import settings as sdk_settings
from aleph.sdk.types import AccountFromPrivateKey
from aleph.sdk.query.filters import MessageFilter
from aleph_message.models import MessageType

from aleph_client.commands import help_strings
from aleph_client.commands.utils import setup_logging
from aleph_client.utils import AsyncTyper

app = typer.Typer()
app = AsyncTyper()


@app.command()
def forget(
async def forget(
key: str = typer.Argument(..., help="Aggregate item hash to be removed."),
reason: Optional[str] = typer.Option(
None, help="A description of why the messages are being forgotten"
Expand All @@ -35,14 +37,16 @@ def forget(

account: AccountFromPrivateKey = _load_account(private_key, private_key_file)

with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
message_response = client.get_messages(
addresses=[account.get_address()],
message_type=MessageType.aggregate.value,
content_keys=[key],
message_response = await client.get_messages(
message_filter=MessageFilter(
addresses=[account.get_address()],
message_types=[MessageType.aggregate.value],
content_keys=[key],
)
)
hash_list = [message["item_hash"] for message in message_response.messages]

client.forget(hashes=hash_list, reason=reason, channel=channel)
await client.forget(hashes=hash_list, reason=reason, channel=channel)
17 changes: 9 additions & 8 deletions src/aleph_client/commands/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import Optional

import typer
from aleph.sdk import AuthenticatedAlephClient
from aleph.sdk import AuthenticatedAlephHttpClient
from aleph.sdk.account import _load_account
from aleph.sdk.conf import settings as sdk_settings
from aleph.sdk.types import AccountFromPrivateKey, StorageEnum
Expand All @@ -12,13 +12,14 @@

from aleph_client.commands import help_strings
from aleph_client.commands.utils import setup_logging
from aleph_client.utils import AsyncTyper

logger = logging.getLogger(__name__)
app = typer.Typer()
app = AsyncTyper()


@app.command()
def pin(
async def pin(
item_hash: str = typer.Argument(..., help="IPFS hash to pin on aleph.im"),
channel: Optional[str] = typer.Option(default=None, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
Expand All @@ -36,12 +37,12 @@ def pin(

account: AccountFromPrivateKey = _load_account(private_key, private_key_file)

with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
result: StoreMessage
status: MessageStatus
result, status = client.create_store(
result, status = await client.create_store(
file_hash=item_hash,
storage_engine=StorageEnum.ipfs,
channel=channel,
Expand All @@ -52,7 +53,7 @@ def pin(


@app.command()
def upload(
async def upload(
path: Path = typer.Argument(..., help="Path of the file to upload"),
channel: Optional[str] = typer.Option(default=None, help=help_strings.CHANNEL),
private_key: Optional[str] = typer.Option(
Expand All @@ -70,7 +71,7 @@ def upload(

account: AccountFromPrivateKey = _load_account(private_key, private_key_file)

with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
if not path.is_file():
Expand All @@ -89,7 +90,7 @@ def upload(
logger.debug("Uploading file")
result: StoreMessage
status: MessageStatus
result, status = client.create_store(
result, status = await client.create_store(
file_content=file_content,
storage_engine=storage_engine,
channel=channel,
Expand Down
97 changes: 47 additions & 50 deletions src/aleph_client/commands/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
from typing import Dict, List, Optional

import typer
from aleph.sdk import AlephClient, AuthenticatedAlephClient
from aleph.sdk import AlephHttpClient, AuthenticatedAlephHttpClient
from aleph.sdk.account import _load_account
from aleph.sdk.conf import settings as sdk_settings
from aleph.sdk.models import MessagesResponse
from aleph.sdk.query.responses import MessagesResponse
from aleph.sdk.query.filters import MessageFilter
from aleph.sdk.types import AccountFromPrivateKey, StorageEnum
from aleph_message.models import AlephMessage, ItemHash, MessageType, ProgramMessage

Expand All @@ -23,24 +24,25 @@
setup_logging,
str_to_datetime,
)
from aleph_client.utils import AsyncTyper

app = typer.Typer()
app = AsyncTyper()


@app.command()
def get(
async def get(
item_hash: str,
):
with AlephClient(api_server=sdk_settings.API_HOST) as client:
message = client.get_message(item_hash=ItemHash(item_hash))
async with AlephHttpClient(api_server=sdk_settings.API_HOST) as client:
message = await client.get_message(item_hash=ItemHash(item_hash))
typer.echo(colorful_message_json(message))


@app.command()
def find(
async def find(
pagination: int = 200,
page: int = 1,
message_type: Optional[str] = None,
message_types: Optional[str] = None,
content_types: Optional[str] = None,
content_keys: Optional[str] = None,
refs: Optional[str] = None,
Expand All @@ -53,17 +55,7 @@ def find(
end_date: Optional[str] = None,
ignore_invalid_messages: bool = True,
):
message_type = MessageType(message_type) if message_type else None

parsed_content_types: Optional[List[str]] = None
parsed_content_keys: Optional[List[str]] = None
parsed_refs: Optional[List[str]] = None
parsed_addresses: Optional[List[str]] = None
parsed_tags: Optional[List[str]] = None
parsed_hashes: Optional[List[str]] = None
parsed_channels: Optional[List[str]] = None
parsed_chains: Optional[List[str]] = None

parsed_message_types = message_types.split(",") if message_types else None
parsed_content_types = content_types.split(",") if content_types else None
parsed_content_keys = content_keys.split(",") if content_keys else None
parsed_refs = refs.split(",") if refs else None
Expand All @@ -73,33 +65,37 @@ def find(
parsed_channels = channels.split(",") if channels else None
parsed_chains = chains.split(",") if chains else None

message_type = MessageType(message_type) if message_type else None
message_types = [
MessageType(message_type) for message_type in parsed_message_types
] if parsed_message_types else None

start_time = str_to_datetime(start_date)
end_time = str_to_datetime(end_date)

with AlephClient(api_server=sdk_settings.API_HOST) as client:
response: MessagesResponse = client.get_messages(
pagination=pagination,
async with AlephHttpClient(api_server=sdk_settings.API_HOST) as client:
response: MessagesResponse = await client.get_messages(
page_size=pagination,
page=page,
message_type=message_type,
content_types=parsed_content_types,
content_keys=parsed_content_keys,
refs=parsed_refs,
addresses=parsed_addresses,
tags=parsed_tags,
hashes=parsed_hashes,
channels=parsed_channels,
chains=parsed_chains,
start_date=start_time,
end_date=end_time,
message_filter=MessageFilter(
message_types=message_types,
content_types=parsed_content_types,
content_keys=parsed_content_keys,
refs=parsed_refs,
addresses=parsed_addresses,
tags=parsed_tags,
hashes=parsed_hashes,
channels=parsed_channels,
chains=parsed_chains,
start_date=start_time,
end_date=end_time,
),
ignore_invalid_messages=ignore_invalid_messages,
)
typer.echo(colorful_json(response.json(sort_keys=True, indent=4)))


@app.command()
def post(
async def post(
path: Optional[Path] = typer.Option(
None,
help="Path to the content you want to post. If omitted, you can input your content directly",
Expand Down Expand Up @@ -149,10 +145,10 @@ def post(
typer.echo("Not valid JSON")
raise typer.Exit(code=2)

with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
result, status = client.create_post(
result, status = await client.create_post(
post_content=content,
post_type=type,
ref=ref,
Expand All @@ -165,7 +161,7 @@ def post(


@app.command()
def amend(
async def amend(
item_hash: str = typer.Argument(..., help="Hash reference of the message to amend"),
private_key: Optional[str] = typer.Option(
sdk_settings.PRIVATE_KEY_STRING, help=help_strings.PRIVATE_KEY
Expand All @@ -181,8 +177,8 @@ def amend(

account: AccountFromPrivateKey = _load_account(private_key, private_key_file)

with AlephClient(api_server=sdk_settings.API_HOST) as client:
existing_message: AlephMessage = client.get_message(item_hash=item_hash)
async with AlephHttpClient(api_server=sdk_settings.API_HOST) as client:
existing_message: AlephMessage = await client.get_message(item_hash=item_hash)

editor: str = os.getenv("EDITOR", default="nano")
with tempfile.NamedTemporaryFile(suffix="json") as fd:
Expand All @@ -207,10 +203,10 @@ def amend(
new_content.ref = existing_message.item_hash

typer.echo(new_content)
with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
message, _status = client.submit(
message, _status = await client.submit(
content=new_content.dict(),
message_type=existing_message.type,
channel=existing_message.channel,
Expand All @@ -219,7 +215,7 @@ def amend(


@app.command()
def forget(
async def forget(
hashes: str = typer.Argument(
..., help="Comma separated list of hash references of messages to forget"
),
Expand All @@ -242,14 +238,14 @@ def forget(
hash_list: List[str] = hashes.split(",")

account: AccountFromPrivateKey = _load_account(private_key, private_key_file)
with AuthenticatedAlephClient(
async with AuthenticatedAlephHttpClient(
account=account, api_server=sdk_settings.API_HOST
) as client:
client.forget(hashes=hash_list, reason=reason, channel=channel)
await client.forget(hashes=hash_list, reason=reason, channel=channel)


@app.command()
def watch(
async def watch(
ref: str = typer.Argument(..., help="Hash reference of the message to watch"),
indent: Optional[int] = typer.Option(None, help="Number of indents to use"),
debug: bool = False,
Expand All @@ -258,11 +254,12 @@ def watch(

setup_logging(debug)

with AlephClient(api_server=sdk_settings.API_HOST) as client:
original: AlephMessage = client.get_message(item_hash=ref)
for message in client.watch_messages(
async with AlephHttpClient(api_server=sdk_settings.API_HOST) as client:
original: AlephMessage = await client.get_message(item_hash=ref)
async for message in client.watch_messages(
message_filter=MessageFilter(
refs=[ref], addresses=[original.content.address]
):
)):
typer.echo(f"{message.json(indent=indent)}")


Expand Down
Loading

0 comments on commit 28a6558

Please sign in to comment.