Skip to content

Commit

Permalink
fix: minor patches in dataclass inheritance; fixes for mypy errors; a…
Browse files Browse the repository at this point in the history
…ddressing internal feedback (#37)

* fix: minor patches in dataclass inheritance; fixes for mypy errors

* refactor: ensure create, update, delete params in factory deploy only require args dataclass (to figure out signature)
  • Loading branch information
aorumbayev authored Feb 5, 2025
1 parent 58f13aa commit 82a1a1c
Show file tree
Hide file tree
Showing 18 changed files with 566 additions and 165 deletions.
14 changes: 10 additions & 4 deletions examples/arc56_test/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand Down Expand Up @@ -100,6 +100,10 @@ class FooArgs:
"""Dataclass for foo arguments"""
inputs: Inputs

@property
def abi_method_signature(self) -> str:
return "foo(((uint64,uint64),(uint64,uint64)))(uint64,uint64)"


class _Arc56TestOptIn:
def __init__(self, app_client: algokit_utils.AppClient):
Expand Down Expand Up @@ -679,17 +683,19 @@ def decode_return_value(
class Arc56TestMethodCallCreateParams(
algokit_utils.AppClientCreateSchema, algokit_utils.BaseAppClientMethodCallParams[
typing.Any,
typing.Any,
str | None,
]
):
"""Parameters for creating Arc56Test contract using ABI"""
on_complete: typing.Literal[OnComplete.NoOpOC] | None = None
method: str | None = None

def to_algokit_utils_params(self) -> algokit_utils.AppClientMethodCallCreateParams:
method_args = _parse_abi_args(self.args)
return algokit_utils.AppClientMethodCallCreateParams(
**{
**self.__dict__,
"method": self.method or getattr(self.args, "abi_method_signature", None),
"args": method_args,
}
)
Expand Down Expand Up @@ -911,7 +917,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class Arc56TestFactoryDeleteParams:
Expand All @@ -929,7 +935,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
6 changes: 3 additions & 3 deletions examples/duplicate_structs/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand Down Expand Up @@ -584,7 +584,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class DuplicateStructsContractFactoryDeleteParams:
Expand All @@ -602,7 +602,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
18 changes: 13 additions & 5 deletions examples/helloworld/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand All @@ -69,11 +69,19 @@ class HelloArgs:
"""Dataclass for hello arguments"""
name: str

@property
def abi_method_signature(self) -> str:
return "hello(string)string"

@dataclasses.dataclass(frozen=True, kw_only=True)
class HelloWorldCheckArgs:
"""Dataclass for hello_world_check arguments"""
name: str

@property
def abi_method_signature(self) -> str:
return "hello_world_check(string)void"


class _HelloWorldAppUpdate:
def __init__(self, app_client: algokit_utils.AppClient):
Expand Down Expand Up @@ -498,15 +506,15 @@ def to_algokit_utils_params(self) -> algokit_utils.AppClientBareCallCreateParams
return algokit_utils.AppClientBareCallCreateParams(**self.__dict__)

@dataclasses.dataclass(frozen=True)
class HelloWorldAppBareCallUpdateParams(algokit_utils.AppClientBareCallCreateParams):
class HelloWorldAppBareCallUpdateParams(algokit_utils.AppClientBareCallParams):
"""Parameters for calling HelloWorldApp contract with bare calls"""
on_complete: typing.Literal[OnComplete.UpdateApplicationOC] | None = None

def to_algokit_utils_params(self) -> algokit_utils.AppClientBareCallParams:
return algokit_utils.AppClientBareCallParams(**self.__dict__)

@dataclasses.dataclass(frozen=True)
class HelloWorldAppBareCallDeleteParams(algokit_utils.AppClientBareCallCreateParams):
class HelloWorldAppBareCallDeleteParams(algokit_utils.AppClientBareCallParams):
"""Parameters for calling HelloWorldApp contract with bare calls"""
on_complete: typing.Literal[OnComplete.DeleteApplicationOC] | None = None

Expand Down Expand Up @@ -712,7 +720,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class HelloWorldAppFactoryDeleteParams:
Expand All @@ -730,7 +738,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
26 changes: 20 additions & 6 deletions examples/lifecycle/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand All @@ -69,17 +69,29 @@ class HelloStringStringArgs:
"""Dataclass for hello_string_string arguments"""
name: str

@property
def abi_method_signature(self) -> str:
return "hello(string)string"

@dataclasses.dataclass(frozen=True, kw_only=True)
class CreateStringStringArgs:
"""Dataclass for create_string_string arguments"""
greeting: str

@property
def abi_method_signature(self) -> str:
return "create(string)string"

@dataclasses.dataclass(frozen=True, kw_only=True)
class CreateStringUint32VoidArgs:
"""Dataclass for create_string_uint32_void arguments"""
greeting: str
times: int

@property
def abi_method_signature(self) -> str:
return "create(string,uint32)void"


class _LifeCycleAppUpdate:
def __init__(self, app_client: algokit_utils.AppClient):
Expand Down Expand Up @@ -592,18 +604,20 @@ def decode_return_value(
@dataclasses.dataclass(frozen=True)
class LifeCycleAppMethodCallCreateParams(
algokit_utils.AppClientCreateSchema, algokit_utils.BaseAppClientMethodCallParams[
tuple[str] | CreateStringStringArgs | tuple[str, int] | CreateStringUint32VoidArgs,
typing.Literal["create(string)string"] | typing.Literal["create(string,uint32)void"],
CreateStringStringArgs | CreateStringUint32VoidArgs,
str | None,
]
):
"""Parameters for creating LifeCycleApp contract using ABI"""
on_complete: typing.Literal[OnComplete.NoOpOC] | None = None
method: str | None = None

def to_algokit_utils_params(self) -> algokit_utils.AppClientMethodCallCreateParams:
method_args = _parse_abi_args(self.args)
return algokit_utils.AppClientMethodCallCreateParams(
**{
**self.__dict__,
"method": self.method or getattr(self.args, "abi_method_signature", None),
"args": method_args,
}
)
Expand All @@ -617,7 +631,7 @@ def to_algokit_utils_params(self) -> algokit_utils.AppClientBareCallCreateParams
return algokit_utils.AppClientBareCallCreateParams(**self.__dict__)

@dataclasses.dataclass(frozen=True)
class LifeCycleAppBareCallUpdateParams(algokit_utils.AppClientBareCallCreateParams):
class LifeCycleAppBareCallUpdateParams(algokit_utils.AppClientBareCallParams):
"""Parameters for calling LifeCycleApp contract with bare calls"""
on_complete: typing.Literal[OnComplete.UpdateApplicationOC] | None = None

Expand Down Expand Up @@ -862,7 +876,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class LifeCycleAppFactoryDeleteParams:
Expand All @@ -880,7 +894,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
3 changes: 1 addition & 2 deletions examples/lifecycle/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ def test_create_2arg(lifecycle_factory: LifeCycleAppFactory) -> None:
def test_deploy_create_1arg(lifecycle_factory: LifeCycleAppFactory) -> None:
client, response = lifecycle_factory.deploy(
create_params=LifeCycleAppMethodCallCreateParams(
args=CreateStringStringArgs(greeting="greeting"),
method="create(string)string",
args=CreateStringStringArgs(greeting="greeting")
)
)

Expand Down
10 changes: 5 additions & 5 deletions examples/minimal/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand Down Expand Up @@ -384,15 +384,15 @@ def to_algokit_utils_params(self) -> algokit_utils.AppClientBareCallCreateParams
return algokit_utils.AppClientBareCallCreateParams(**self.__dict__)

@dataclasses.dataclass(frozen=True)
class AppBareCallUpdateParams(algokit_utils.AppClientBareCallCreateParams):
class AppBareCallUpdateParams(algokit_utils.AppClientBareCallParams):
"""Parameters for calling App contract with bare calls"""
on_complete: typing.Literal[OnComplete.UpdateApplicationOC] | None = None

def to_algokit_utils_params(self) -> algokit_utils.AppClientBareCallParams:
return algokit_utils.AppClientBareCallParams(**self.__dict__)

@dataclasses.dataclass(frozen=True)
class AppBareCallDeleteParams(algokit_utils.AppClientBareCallCreateParams):
class AppBareCallDeleteParams(algokit_utils.AppClientBareCallParams):
"""Parameters for calling App contract with bare calls"""
on_complete: typing.Literal[OnComplete.DeleteApplicationOC] | None = None

Expand Down Expand Up @@ -558,7 +558,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class AppFactoryDeleteParams:
Expand All @@ -576,7 +576,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
18 changes: 15 additions & 3 deletions examples/nested/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def _init_dataclass(cls: type, data: dict) -> object:
field_value = data.get(field.name)
# Check if the field expects another dataclass and the value is a dict.
if dataclasses.is_dataclass(field.type) and isinstance(field_value, dict):
field_values[field.name] = _init_dataclass(field.type, field_value)
field_values[field.name] = _init_dataclass(typing.cast(type, field.type), field_value)
else:
field_values[field.name] = field_value
return cls(**field_values)
Expand All @@ -70,18 +70,30 @@ class AddArgs:
a: int
b: int

@property
def abi_method_signature(self) -> str:
return "add(uint64,uint64)uint64"

@dataclasses.dataclass(frozen=True, kw_only=True)
class GetPayTxnAmountArgs:
"""Dataclass for get_pay_txn_amount arguments"""
pay_txn: algokit_utils.AppMethodCallTransactionArgument

@property
def abi_method_signature(self) -> str:
return "get_pay_txn_amount(pay)uint64"

@dataclasses.dataclass(frozen=True, kw_only=True)
class NestedMethodCallArgs:
"""Dataclass for nested_method_call arguments"""
_: str
_pay_txn: algokit_utils.AppMethodCallTransactionArgument | None = None
method_call: algokit_utils.AppMethodCallTransactionArgument

@property
def abi_method_signature(self) -> str:
return "nested_method_call(string,pay,appl)byte[]"


class NestedContractParams:
def __init__(self, app_client: algokit_utils.AppClient):
Expand Down Expand Up @@ -678,7 +690,7 @@ def bare(
"""Updates an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_update(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)

class NestedContractFactoryDeleteParams:
Expand All @@ -696,7 +708,7 @@ def bare(
"""Deletes an instance using a bare call"""
params = params or algokit_utils.CommonAppCallCreateParams()
return self.app_factory.params.bare.deploy_delete(
algokit_utils.AppFactoryCreateParams(**dataclasses.asdict(params)),
algokit_utils.AppClientBareCallParams(**dataclasses.asdict(params)),
)


Expand Down
Loading

1 comment on commit 82a1a1c

@github-actions
Copy link

Choose a reason for hiding this comment

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

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit_client_generator
   __main__.py220%1–3
   cli.py48480%1–87
   document.py82791%44, 47, 49–50, 55, 74–75
   generator.py31197%23
   spec.py2071692%86, 116–119, 219–223, 253, 269, 350–351, 395, 410
   utils.py2194878%11, 20, 24, 28, 32, 36, 40, 44, 55, 58, 63–64, 75–76, 82–84, 89–91, 94–96, 99, 102, 105, 108–110, 159–160, 194, 198, 201–202, 218, 220, 231–232, 249, 261–264, 268, 278, 281, 283
src/algokit_client_generator/generators
   composer.py51198%29
   typed_client.py328898%59, 188, 287, 590, 680, 690, 729, 840
   typed_factory.py213399%64, 94, 227
TOTAL125213489% 

Tests Skipped Failures Errors Time
42 0 💤 0 ❌ 0 🔥 19.077s ⏱️

Please sign in to comment.