-
Notifications
You must be signed in to change notification settings - Fork 47
/
utils.py
125 lines (96 loc) · 5.11 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# Cli/Click related helper functions and classes
import typing as t
import click
from algokit.cli.common.constants import ExplorerEntityType
class MutuallyExclusiveOption(click.Option):
"""
A Click option that defines mutually exclusive command line options.
Args:
*args: Positional arguments passed to the parent class constructor.
**kwargs: Keyword arguments passed to the parent class constructor.
not_required_if (list): A list of options that the current option is mutually exclusive with.
Attributes:
not_required_if (list): A list of options that the current option is mutually exclusive with.
Raises:
AssertionError: If the `not_required_if` parameter is not provided.
Example:
```python
@click.command()
@click.option('--option1', help='Option 1')
@click.option('--option2', help='Option 2')
@click.option('--option3', help='Option 3', cls=MutuallyExclusiveOption, not_required_if=['option1', 'option2'])
def my_command(option1, option2, option3):
# Command logic here
pass
```
In the example above, the `MutuallyExclusiveOption` class is used to define the `option3` command line option.
This option is mutually exclusive with `option1` and `option2`,
meaning that if either `option1` or `option2` is provided, `option3` cannot be used.
If `option3` is provided along with `option1` or `option2`, a `click.UsageError` is raised.
"""
def __init__(self, *args: t.Any, **kwargs: t.Any) -> None:
self.not_required_if: list = kwargs.pop("not_required_if")
assert self.not_required_if, "'not_required_if' parameter required"
kwargs["help"] = (
kwargs.get("help", "") + " Option is mutually exclusive with " + ", ".join(self.not_required_if) + "."
).strip()
super().__init__(*args, **kwargs)
def handle_parse_result(
self, ctx: click.Context, opts: t.Mapping[str, t.Any], args: list[str]
) -> tuple[t.Any, list[str]]:
"""
Overrides the `handle_parse_result` method of the `click.Option` class.
This method checks if the current option is present in the provided options (`opts`)
and if any of the mutually exclusive options are also present.
If both the current option and a mutually exclusive option are present, it raises a `click.UsageError`.
Otherwise, it returns the result of the parent `handle_parse_result` method.
Args:
ctx (click.Context): The Click context object.
opts (dict): The dictionary of parsed options.
args (list): The list of remaining arguments.
Returns:
The result of the parent `handle_parse_result` method.
Raises:
click.UsageError: If the current option and a mutually exclusive option are both present.
"""
current_opt: bool = self.name in opts
for mutex_opt in self.not_required_if:
if mutex_opt in opts:
if current_opt:
raise click.UsageError(
"Illegal usage: '" + str(self.name) + "' is mutually exclusive with " + str(mutex_opt) + "."
)
self.prompt = None
return super().handle_parse_result(ctx, opts, args)
def get_explorer_url(identifier: str | int, network: str, entity_type: ExplorerEntityType) -> str:
"""
Returns a URL for exploring a specified type (transaction, asset, address) on the specified network.
Args:
identifier (str | int): The ID of the transaction, asset, or address to explore.
network (str): The name of the network (e.g., "localnet", "testnet", "mainnet").
entity_type (ExplorerEntityType): The type to explore (e.g., ExplorerEntityType.TRANSACTION,
ExplorerEntityType.ASSET, ExplorerEntityType.ADDRESS).
Returns:
str: The URL for exploring the specified type on the specified network.
Raises:
ValueError: If the network or explorer type is invalid.
"""
base_urls: dict[str, dict[str, str]] = {
"testnet": {
ExplorerEntityType.TRANSACTION.value: "https://testnet.explorer.perawallet.app/tx/",
ExplorerEntityType.ASSET.value: "https://testnet.explorer.perawallet.app/asset/",
ExplorerEntityType.ADDRESS.value: "https://testnet.explorer.perawallet.app/address/",
},
"mainnet": {
ExplorerEntityType.TRANSACTION.value: "https://explorer.perawallet.app/tx/",
ExplorerEntityType.ASSET.value: "https://explorer.perawallet.app/asset/",
ExplorerEntityType.ADDRESS.value: "https://explorer.perawallet.app/tx/address/",
},
}
if network == "localnet":
return f"https://app.dappflow.org/setnetwork?name=sandbox&redirect=explorer/{entity_type.value}/{identifier}/"
if network not in base_urls:
raise ValueError(f"Invalid network: {network}")
if entity_type.value not in base_urls[network]:
raise ValueError(f"Invalid explorer type: {entity_type}")
return base_urls[network][entity_type.value] + str(identifier)