web3 7.0.0b1__py3-none-any.whl → 7.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ens/__init__.py +13 -2
- ens/_normalization.py +4 -4
- ens/async_ens.py +31 -21
- ens/base_ens.py +3 -1
- ens/contract_data.py +2 -2
- ens/ens.py +14 -11
- ens/exceptions.py +16 -29
- ens/specs/nf.json +1 -1
- ens/specs/normalization_spec.json +1 -1
- ens/utils.py +33 -41
- web3/__init__.py +23 -12
- web3/_utils/abi.py +162 -274
- web3/_utils/async_transactions.py +34 -20
- web3/_utils/batching.py +217 -0
- web3/_utils/blocks.py +6 -2
- web3/_utils/caching/__init__.py +12 -0
- web3/_utils/caching/caching_utils.py +433 -0
- web3/_utils/caching/request_caching_validation.py +287 -0
- web3/_utils/compat/__init__.py +2 -3
- web3/_utils/contract_sources/compile_contracts.py +1 -1
- web3/_utils/contract_sources/contract_data/ambiguous_function_contract.py +42 -0
- web3/_utils/contract_sources/contract_data/arrays_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/bytes_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/constructor_contracts.py +7 -7
- web3/_utils/contract_sources/contract_data/contract_caller_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/emitter_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/event_contracts.py +50 -5
- web3/_utils/contract_sources/contract_data/extended_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/fallback_function_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/function_name_tester_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/math_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_lookup.py +3 -3
- web3/_utils/contract_sources/contract_data/offchain_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/panic_errors_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/payable_tester.py +3 -3
- web3/_utils/contract_sources/contract_data/receive_function_contracts.py +5 -5
- web3/_utils/contract_sources/contract_data/reflector_contracts.py +3 -3
- web3/_utils/contract_sources/contract_data/revert_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/simple_resolver.py +3 -3
- web3/_utils/contract_sources/contract_data/storage_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/string_contract.py +3 -3
- web3/_utils/contract_sources/contract_data/tuple_contracts.py +5 -5
- web3/_utils/contracts.py +172 -220
- web3/_utils/datatypes.py +5 -1
- web3/_utils/decorators.py +6 -1
- web3/_utils/empty.py +1 -1
- web3/_utils/encoding.py +16 -12
- web3/_utils/error_formatters_utils.py +5 -3
- web3/_utils/events.py +78 -72
- web3/_utils/fee_utils.py +1 -3
- web3/_utils/filters.py +24 -22
- web3/_utils/formatters.py +2 -2
- web3/_utils/http.py +8 -2
- web3/_utils/http_session_manager.py +314 -0
- web3/_utils/math.py +14 -15
- web3/_utils/method_formatters.py +161 -34
- web3/_utils/module.py +2 -1
- web3/_utils/module_testing/__init__.py +3 -2
- web3/_utils/module_testing/eth_module.py +736 -583
- web3/_utils/module_testing/go_ethereum_debug_module.py +128 -0
- web3/_utils/module_testing/module_testing_utils.py +81 -24
- web3/_utils/module_testing/persistent_connection_provider.py +702 -220
- web3/_utils/module_testing/utils.py +114 -33
- web3/_utils/module_testing/web3_module.py +438 -17
- web3/_utils/normalizers.py +13 -11
- web3/_utils/rpc_abi.py +10 -22
- web3/_utils/threads.py +8 -7
- web3/_utils/transactions.py +32 -25
- web3/_utils/type_conversion.py +5 -1
- web3/_utils/validation.py +20 -17
- web3/beacon/__init__.py +5 -0
- web3/beacon/api_endpoints.py +3 -0
- web3/beacon/async_beacon.py +29 -6
- web3/beacon/beacon.py +24 -6
- web3/contract/__init__.py +7 -0
- web3/contract/async_contract.py +285 -82
- web3/contract/base_contract.py +556 -258
- web3/contract/contract.py +295 -84
- web3/contract/utils.py +251 -55
- web3/datastructures.py +56 -41
- web3/eth/__init__.py +7 -0
- web3/eth/async_eth.py +89 -69
- web3/eth/base_eth.py +7 -3
- web3/eth/eth.py +43 -66
- web3/exceptions.py +158 -83
- web3/gas_strategies/time_based.py +8 -6
- web3/geth.py +53 -184
- web3/main.py +77 -43
- web3/manager.py +368 -101
- web3/method.py +43 -15
- web3/middleware/__init__.py +26 -8
- web3/middleware/attrdict.py +12 -22
- web3/middleware/base.py +55 -2
- web3/middleware/filter.py +45 -23
- web3/middleware/formatting.py +6 -3
- web3/middleware/names.py +4 -1
- web3/middleware/signing.py +15 -6
- web3/middleware/stalecheck.py +2 -1
- web3/module.py +62 -26
- web3/providers/__init__.py +21 -0
- web3/providers/async_base.py +93 -38
- web3/providers/base.py +85 -40
- web3/providers/eth_tester/__init__.py +5 -0
- web3/providers/eth_tester/defaults.py +2 -55
- web3/providers/eth_tester/main.py +57 -35
- web3/providers/eth_tester/middleware.py +16 -17
- web3/providers/ipc.py +42 -18
- web3/providers/legacy_websocket.py +27 -2
- web3/providers/persistent/__init__.py +7 -0
- web3/providers/persistent/async_ipc.py +61 -121
- web3/providers/persistent/persistent.py +324 -17
- web3/providers/persistent/persistent_connection.py +54 -5
- web3/providers/persistent/request_processor.py +136 -56
- web3/providers/persistent/subscription_container.py +56 -0
- web3/providers/persistent/subscription_manager.py +233 -0
- web3/providers/persistent/websocket.py +29 -92
- web3/providers/rpc/__init__.py +5 -0
- web3/providers/rpc/async_rpc.py +73 -18
- web3/providers/rpc/rpc.py +73 -30
- web3/providers/rpc/utils.py +1 -13
- web3/scripts/install_pre_releases.py +33 -0
- web3/scripts/parse_pygeth_version.py +16 -0
- web3/testing.py +4 -4
- web3/tracing.py +9 -5
- web3/types.py +141 -74
- web3/utils/__init__.py +64 -5
- web3/utils/abi.py +790 -10
- web3/utils/address.py +8 -0
- web3/utils/async_exception_handling.py +20 -11
- web3/utils/caching.py +34 -4
- web3/utils/exception_handling.py +9 -12
- web3/utils/subscriptions.py +285 -0
- {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/LICENSE +1 -1
- web3-7.7.0.dist-info/METADATA +130 -0
- web3-7.7.0.dist-info/RECORD +171 -0
- {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/WHEEL +1 -1
- {web3-7.0.0b1.dist-info → web3-7.7.0.dist-info}/top_level.txt +0 -1
- ethpm/__init__.py +0 -20
- ethpm/_utils/__init__.py +0 -0
- ethpm/_utils/backend.py +0 -93
- ethpm/_utils/cache.py +0 -44
- ethpm/_utils/chains.py +0 -119
- ethpm/_utils/contract.py +0 -35
- ethpm/_utils/deployments.py +0 -145
- ethpm/_utils/ipfs.py +0 -116
- ethpm/_utils/protobuf/__init__.py +0 -0
- ethpm/_utils/protobuf/ipfs_file_pb2.py +0 -33
- ethpm/_utils/registry.py +0 -29
- ethpm/assets/__init__.py +0 -0
- ethpm/assets/ens/v3.json +0 -1
- ethpm/assets/escrow/with_bytecode_v3.json +0 -1
- ethpm/assets/ipfs_file.proto +0 -32
- ethpm/assets/owned/output_v3.json +0 -1
- ethpm/assets/owned/with_contract_type_v3.json +0 -1
- ethpm/assets/registry/contracts/Authority.sol +0 -156
- ethpm/assets/registry/contracts/IndexedOrderedSetLib.sol +0 -106
- ethpm/assets/registry/contracts/PackageDB.sol +0 -225
- ethpm/assets/registry/contracts/PackageRegistry.sol +0 -361
- ethpm/assets/registry/contracts/PackageRegistryInterface.sol +0 -97
- ethpm/assets/registry/contracts/ReleaseDB.sol +0 -309
- ethpm/assets/registry/contracts/ReleaseValidator.sol +0 -152
- ethpm/assets/registry/solc_input.json +0 -1
- ethpm/assets/registry/solc_output.json +0 -1
- ethpm/assets/registry/v3.json +0 -1
- ethpm/assets/safe-math-lib/v3-strict-no-deployments.json +0 -1
- ethpm/assets/simple-registry/contracts/Ownable.sol +0 -63
- ethpm/assets/simple-registry/contracts/PackageRegistry.sol +0 -373
- ethpm/assets/simple-registry/contracts/PackageRegistryInterface.sol +0 -96
- ethpm/assets/simple-registry/solc_input.json +0 -33
- ethpm/assets/simple-registry/solc_output.json +0 -1
- ethpm/assets/simple-registry/v3.json +0 -1
- ethpm/assets/standard-token/output_v3.json +0 -1
- ethpm/assets/standard-token/with_bytecode_v3.json +0 -1
- ethpm/assets/vyper_registry/0.1.0.json +0 -1
- ethpm/assets/vyper_registry/registry.vy +0 -216
- ethpm/assets/vyper_registry/registry_with_delete.vy +0 -244
- ethpm/backends/__init__.py +0 -0
- ethpm/backends/base.py +0 -43
- ethpm/backends/http.py +0 -108
- ethpm/backends/ipfs.py +0 -219
- ethpm/backends/registry.py +0 -154
- ethpm/constants.py +0 -17
- ethpm/contract.py +0 -187
- ethpm/dependencies.py +0 -58
- ethpm/deployments.py +0 -80
- ethpm/ethpm-spec/examples/escrow/1.0.0-pretty.json +0 -146
- ethpm/ethpm-spec/examples/escrow/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/escrow/contracts/Escrow.sol +0 -32
- ethpm/ethpm-spec/examples/escrow/contracts/SafeSendLib.sol +0 -20
- ethpm/ethpm-spec/examples/escrow/v3-pretty.json +0 -171
- ethpm/ethpm-spec/examples/escrow/v3.json +0 -1
- ethpm/ethpm-spec/examples/owned/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/owned/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/owned/contracts/Owned.sol +0 -12
- ethpm/ethpm-spec/examples/owned/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/owned/v3.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/1.0.0-pretty.json +0 -31
- ethpm/ethpm-spec/examples/piper-coin/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/piper-coin/v3-pretty.json +0 -21
- ethpm/ethpm-spec/examples/piper-coin/v3.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0-pretty.json +0 -85
- ethpm/ethpm-spec/examples/safe-math-lib/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/safe-math-lib/contracts/SafeMathLib.sol +0 -24
- ethpm/ethpm-spec/examples/safe-math-lib/v3-pretty.json +0 -117
- ethpm/ethpm-spec/examples/safe-math-lib/v3.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/1.0.0-pretty.json +0 -55
- ethpm/ethpm-spec/examples/standard-token/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/standard-token/contracts/AbstractToken.sol +0 -20
- ethpm/ethpm-spec/examples/standard-token/contracts/StandardToken.sol +0 -84
- ethpm/ethpm-spec/examples/standard-token/v3-pretty.json +0 -460
- ethpm/ethpm-spec/examples/standard-token/v3.json +0 -1
- ethpm/ethpm-spec/examples/transferable/1.0.0-pretty.json +0 -21
- ethpm/ethpm-spec/examples/transferable/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/transferable/contracts/Transferable.sol +0 -14
- ethpm/ethpm-spec/examples/transferable/v3-pretty.json +0 -27
- ethpm/ethpm-spec/examples/transferable/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet/1.0.0-pretty.json +0 -120
- ethpm/ethpm-spec/examples/wallet/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet/contracts/Wallet.sol +0 -41
- ethpm/ethpm-spec/examples/wallet/v3-pretty.json +0 -181
- ethpm/ethpm-spec/examples/wallet/v3.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0-pretty.json +0 -135
- ethpm/ethpm-spec/examples/wallet-with-send/1.0.0.json +0 -1
- ethpm/ethpm-spec/examples/wallet-with-send/contracts/WalletWithSend.sol +0 -18
- ethpm/ethpm-spec/examples/wallet-with-send/v3-pretty.json +0 -207
- ethpm/ethpm-spec/examples/wallet-with-send/v3.json +0 -1
- ethpm/ethpm-spec/spec/package.spec.json +0 -379
- ethpm/ethpm-spec/spec/v3.spec.json +0 -483
- ethpm/exceptions.py +0 -68
- ethpm/package.py +0 -438
- ethpm/tools/__init__.py +0 -4
- ethpm/tools/builder.py +0 -930
- ethpm/tools/checker.py +0 -312
- ethpm/tools/get_manifest.py +0 -19
- ethpm/uri.py +0 -141
- ethpm/validation/__init__.py +0 -0
- ethpm/validation/manifest.py +0 -146
- ethpm/validation/misc.py +0 -39
- ethpm/validation/package.py +0 -80
- ethpm/validation/uri.py +0 -163
- web3/_utils/caching.py +0 -155
- web3/_utils/contract_sources/contract_data/address_reflector.py +0 -29
- web3/_utils/module_testing/go_ethereum_personal_module.py +0 -300
- web3/_utils/request.py +0 -265
- web3/pm.py +0 -602
- web3/tools/__init__.py +0 -4
- web3/tools/benchmark/__init__.py +0 -0
- web3/tools/benchmark/main.py +0 -185
- web3/tools/benchmark/node.py +0 -126
- web3/tools/benchmark/reporting.py +0 -39
- web3/tools/benchmark/utils.py +0 -69
- web3/tools/pytest_ethereum/__init__.py +0 -0
- web3/tools/pytest_ethereum/_utils.py +0 -145
- web3/tools/pytest_ethereum/deployer.py +0 -48
- web3/tools/pytest_ethereum/exceptions.py +0 -22
- web3/tools/pytest_ethereum/linker.py +0 -128
- web3/tools/pytest_ethereum/plugins.py +0 -33
- web3-7.0.0b1.dist-info/METADATA +0 -114
- web3-7.0.0b1.dist-info/RECORD +0 -280
- web3-7.0.0b1.dist-info/entry_points.txt +0 -2
- /web3/_utils/{function_identifiers.py → abi_element_identifiers.py} +0 -0
ethpm/backends/ipfs.py
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
from abc import (
|
|
2
|
-
abstractmethod,
|
|
3
|
-
)
|
|
4
|
-
import os
|
|
5
|
-
from pathlib import (
|
|
6
|
-
Path,
|
|
7
|
-
)
|
|
8
|
-
from typing import (
|
|
9
|
-
Dict,
|
|
10
|
-
List,
|
|
11
|
-
Type,
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
from eth_utils import (
|
|
15
|
-
import_string,
|
|
16
|
-
to_bytes,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
from ethpm import (
|
|
20
|
-
get_ethpm_spec_dir,
|
|
21
|
-
)
|
|
22
|
-
from ethpm._utils.ipfs import (
|
|
23
|
-
dummy_ipfs_pin,
|
|
24
|
-
extract_ipfs_path_from_uri,
|
|
25
|
-
generate_file_hash,
|
|
26
|
-
is_ipfs_uri,
|
|
27
|
-
)
|
|
28
|
-
from ethpm.backends.base import (
|
|
29
|
-
BaseURIBackend,
|
|
30
|
-
)
|
|
31
|
-
from ethpm.constants import (
|
|
32
|
-
DEFAULT_IPFS_BACKEND,
|
|
33
|
-
INFURA_GATEWAY_MULTIADDR,
|
|
34
|
-
IPFS_GATEWAY_PREFIX,
|
|
35
|
-
)
|
|
36
|
-
from ethpm.exceptions import (
|
|
37
|
-
CannotHandleURI,
|
|
38
|
-
EthPMValidationError,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
try:
|
|
42
|
-
# `ipfshttpclient` backend is optional. This is only imported if the "web3[ipfs]"
|
|
43
|
-
# install extra is installed
|
|
44
|
-
import ipfshttpclient
|
|
45
|
-
except ImportError:
|
|
46
|
-
pass
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class BaseIPFSBackend(BaseURIBackend):
|
|
50
|
-
"""
|
|
51
|
-
Base class for all URIs with an IPFS scheme.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
def can_resolve_uri(self, uri: str) -> bool:
|
|
55
|
-
"""
|
|
56
|
-
Return a bool indicating whether or not this backend
|
|
57
|
-
is capable of serving the content located at the URI.
|
|
58
|
-
"""
|
|
59
|
-
return is_ipfs_uri(uri)
|
|
60
|
-
|
|
61
|
-
def can_translate_uri(self, uri: str) -> bool:
|
|
62
|
-
"""
|
|
63
|
-
Return False. IPFS URIs cannot be used to point
|
|
64
|
-
to another content-addressed URI.
|
|
65
|
-
"""
|
|
66
|
-
return False
|
|
67
|
-
|
|
68
|
-
@abstractmethod
|
|
69
|
-
def pin_assets(self, file_or_dir_path: Path) -> List[Dict[str, str]]:
|
|
70
|
-
"""
|
|
71
|
-
Pin assets found at `file_or_dir_path` and return a
|
|
72
|
-
list containing pinned asset data.
|
|
73
|
-
"""
|
|
74
|
-
pass
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
class IPFSOverHTTPBackend(BaseIPFSBackend):
|
|
78
|
-
"""
|
|
79
|
-
Base class for all IPFS URIs served over an http connection.
|
|
80
|
-
All subclasses must implement: base_uri
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
def __init__(self) -> None:
|
|
84
|
-
self.client = ipfshttpclient.connect(self.base_uri)
|
|
85
|
-
|
|
86
|
-
def fetch_uri_contents(self, uri: str) -> bytes:
|
|
87
|
-
ipfs_hash = extract_ipfs_path_from_uri(uri)
|
|
88
|
-
contents = self.client.cat(ipfs_hash)
|
|
89
|
-
# Local validation of hashed contents only works for non-chunked files ~< 256kb
|
|
90
|
-
# Improved validation WIP @ https://github.com/ethpm/py-ethpm/pull/165
|
|
91
|
-
if len(contents) <= 262144:
|
|
92
|
-
validation_hash = generate_file_hash(contents)
|
|
93
|
-
if validation_hash != ipfs_hash:
|
|
94
|
-
raise EthPMValidationError(
|
|
95
|
-
f"Hashed IPFS contents retrieved from uri: {uri} "
|
|
96
|
-
"do not match its content hash."
|
|
97
|
-
)
|
|
98
|
-
return contents
|
|
99
|
-
|
|
100
|
-
@property
|
|
101
|
-
@abstractmethod
|
|
102
|
-
def base_uri(self) -> str:
|
|
103
|
-
pass
|
|
104
|
-
|
|
105
|
-
def pin_assets(self, file_or_dir_path: Path) -> List[Dict[str, str]]:
|
|
106
|
-
if file_or_dir_path.is_dir():
|
|
107
|
-
dir_data = self.client.add(str(file_or_dir_path), recursive=True)
|
|
108
|
-
return dir_data
|
|
109
|
-
elif file_or_dir_path.is_file():
|
|
110
|
-
file_data = self.client.add(str(file_or_dir_path), recursive=False)
|
|
111
|
-
return [file_data]
|
|
112
|
-
else:
|
|
113
|
-
raise TypeError(
|
|
114
|
-
f"{file_or_dir_path} is not a valid file or directory path."
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class IPFSGatewayBackend(IPFSOverHTTPBackend):
|
|
119
|
-
"""
|
|
120
|
-
Backend class for all IPFS URIs served over the IPFS gateway.
|
|
121
|
-
"""
|
|
122
|
-
|
|
123
|
-
# todo update this gateway to work r&w
|
|
124
|
-
# https://discuss.ipfs.io/t/writeable-http-gateways/210
|
|
125
|
-
@property
|
|
126
|
-
def base_uri(self) -> str:
|
|
127
|
-
return IPFS_GATEWAY_PREFIX
|
|
128
|
-
|
|
129
|
-
def pin_assets(self, file_or_dir_path: Path) -> List[Dict[str, str]]:
|
|
130
|
-
raise CannotHandleURI(
|
|
131
|
-
"IPFS gateway is currently disabled, please use a different IPFS backend."
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
def fetch_uri_contents(self, uri: str) -> bytes:
|
|
135
|
-
raise CannotHandleURI(
|
|
136
|
-
"IPFS gateway is currently disabled, please use a different IPFS backend."
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
class InfuraIPFSBackend(IPFSOverHTTPBackend):
|
|
141
|
-
"""
|
|
142
|
-
Backend class for all IPFS URIs served over the Infura IFPS gateway.
|
|
143
|
-
"""
|
|
144
|
-
|
|
145
|
-
@property
|
|
146
|
-
def base_uri(self) -> str:
|
|
147
|
-
return INFURA_GATEWAY_MULTIADDR
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
class LocalIPFSBackend(IPFSOverHTTPBackend):
|
|
151
|
-
"""
|
|
152
|
-
Backend class for all IPFS URIs served through a direct connection to an IPFS node.
|
|
153
|
-
Default IPFS port = 5001
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
@property
|
|
157
|
-
def base_uri(self) -> str:
|
|
158
|
-
return "/ip4/127.0.0.1/tcp/5001"
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
MANIFEST_URIS = {
|
|
162
|
-
"ipfs://QmQNffBrmbB3TuBCtYfYsJWJVLssatWXa3H6CkGeyNUySA": "standard-token",
|
|
163
|
-
"ipfs://QmWnPsiS3Xb8GvCDEBFnnKs8Yk4HaAX6rCqJAaQXGbCoPk": "safe-math-lib",
|
|
164
|
-
"ipfs://QmcxvhkJJVpbxEAa6cgW3B6XwPJb79w9GpNUv2P2THUzZR": "owned",
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
class DummyIPFSBackend(BaseIPFSBackend):
|
|
169
|
-
"""
|
|
170
|
-
Backend class to serve IPFS URIs without having to make an HTTP request.
|
|
171
|
-
Used primarily for testing purposes, returns a locally stored manifest or contract.
|
|
172
|
-
---
|
|
173
|
-
`ipfs_uri` can either be:
|
|
174
|
-
- Valid IPFS URI -> safe-math-lib manifest (ALWAYS)
|
|
175
|
-
- Path to manifest/contract in ethpm_spec_dir -> defined manifest/contract
|
|
176
|
-
"""
|
|
177
|
-
|
|
178
|
-
def fetch_uri_contents(self, ipfs_uri: str) -> bytes:
|
|
179
|
-
pkg_name = MANIFEST_URIS[ipfs_uri]
|
|
180
|
-
ethpm_spec_dir = get_ethpm_spec_dir()
|
|
181
|
-
pkg_contents = (ethpm_spec_dir / "examples" / pkg_name / "v3.json").read_text()
|
|
182
|
-
return to_bytes(text=pkg_contents)
|
|
183
|
-
|
|
184
|
-
def can_resolve_uri(self, uri: str) -> bool:
|
|
185
|
-
return uri in MANIFEST_URIS
|
|
186
|
-
|
|
187
|
-
def pin_assets(self, file_or_dir_path: Path) -> List[Dict[str, str]]:
|
|
188
|
-
"""
|
|
189
|
-
Return a dict containing the IPFS hash, file name, and size of a file.
|
|
190
|
-
"""
|
|
191
|
-
if file_or_dir_path.is_dir():
|
|
192
|
-
asset_data = [dummy_ipfs_pin(path) for path in file_or_dir_path.glob("*")]
|
|
193
|
-
elif file_or_dir_path.is_file():
|
|
194
|
-
asset_data = [dummy_ipfs_pin(file_or_dir_path)]
|
|
195
|
-
else:
|
|
196
|
-
raise FileNotFoundError(
|
|
197
|
-
f"{file_or_dir_path} is not a valid file or directory path."
|
|
198
|
-
)
|
|
199
|
-
return asset_data
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def get_ipfs_backend(import_path: str = None) -> BaseIPFSBackend:
|
|
203
|
-
"""
|
|
204
|
-
Return the `BaseIPFSBackend` class specified by import_path,
|
|
205
|
-
default, or env variable.
|
|
206
|
-
"""
|
|
207
|
-
backend_class = get_ipfs_backend_class(import_path)
|
|
208
|
-
return backend_class()
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
def get_ipfs_backend_class(import_path: str = None) -> Type[BaseIPFSBackend]:
|
|
212
|
-
if import_path is None:
|
|
213
|
-
import_path = os.environ.get("ETHPM_IPFS_BACKEND_CLASS", DEFAULT_IPFS_BACKEND)
|
|
214
|
-
if not import_path:
|
|
215
|
-
raise CannotHandleURI(
|
|
216
|
-
"Please provide an import class or set "
|
|
217
|
-
"`ETHPM_IPFS_BACKEND_CLASS` environment variable."
|
|
218
|
-
)
|
|
219
|
-
return import_string(import_path)
|
ethpm/backends/registry.py
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
from collections import (
|
|
2
|
-
namedtuple,
|
|
3
|
-
)
|
|
4
|
-
from typing import (
|
|
5
|
-
Optional,
|
|
6
|
-
Tuple,
|
|
7
|
-
)
|
|
8
|
-
from urllib import (
|
|
9
|
-
parse,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
from eth_typing import (
|
|
13
|
-
URI,
|
|
14
|
-
)
|
|
15
|
-
from eth_utils import (
|
|
16
|
-
is_address,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
from ens import (
|
|
20
|
-
ENS,
|
|
21
|
-
)
|
|
22
|
-
from ethpm._utils.registry import (
|
|
23
|
-
fetch_standard_registry_abi,
|
|
24
|
-
)
|
|
25
|
-
from ethpm.backends.base import (
|
|
26
|
-
BaseURIBackend,
|
|
27
|
-
)
|
|
28
|
-
from ethpm.exceptions import (
|
|
29
|
-
CannotHandleURI,
|
|
30
|
-
EthPMValidationError,
|
|
31
|
-
)
|
|
32
|
-
from ethpm.validation.uri import (
|
|
33
|
-
validate_registry_uri,
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
# TODO: Update registry ABI once ERC is finalized.
|
|
37
|
-
REGISTRY_ABI = fetch_standard_registry_abi()
|
|
38
|
-
RegistryURI = namedtuple(
|
|
39
|
-
"RegistryURI", ["address", "chain_id", "name", "version", "namespaced_asset", "ens"]
|
|
40
|
-
)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class RegistryURIBackend(BaseURIBackend):
|
|
44
|
-
"""
|
|
45
|
-
Backend class to handle Registry URIs.
|
|
46
|
-
|
|
47
|
-
A Registry URI must resolve to a resolvable content-addressed URI.
|
|
48
|
-
"""
|
|
49
|
-
|
|
50
|
-
def __init__(self) -> None:
|
|
51
|
-
from web3 import (
|
|
52
|
-
LegacyWebSocketProvider,
|
|
53
|
-
Web3,
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
w3 = Web3(LegacyWebSocketProvider())
|
|
57
|
-
|
|
58
|
-
self.w3 = w3
|
|
59
|
-
|
|
60
|
-
def can_translate_uri(self, uri: str) -> bool:
|
|
61
|
-
return is_valid_registry_uri(uri)
|
|
62
|
-
|
|
63
|
-
def can_resolve_uri(self, uri: str) -> bool:
|
|
64
|
-
return False
|
|
65
|
-
|
|
66
|
-
def fetch_uri_contents(self, uri: str) -> URI:
|
|
67
|
-
"""
|
|
68
|
-
Return content-addressed URI stored at registry URI.
|
|
69
|
-
"""
|
|
70
|
-
address, chain_id, pkg_name, pkg_version, _, _ = parse_registry_uri(uri)
|
|
71
|
-
if chain_id != "1":
|
|
72
|
-
# todo: support all testnets
|
|
73
|
-
raise CannotHandleURI("Currently only mainnet registry uris are supported.")
|
|
74
|
-
self.w3.enable_unstable_package_management_api()
|
|
75
|
-
self.w3.pm.set_registry(address)
|
|
76
|
-
_, _, manifest_uri = self.w3.pm.get_release_data(pkg_name, pkg_version)
|
|
77
|
-
return URI(manifest_uri)
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
def is_valid_registry_uri(uri: str) -> bool:
|
|
81
|
-
"""
|
|
82
|
-
Return a boolean indicating whether `uri` argument
|
|
83
|
-
conforms to the Registry URI scheme.
|
|
84
|
-
"""
|
|
85
|
-
try:
|
|
86
|
-
validate_registry_uri(uri)
|
|
87
|
-
except EthPMValidationError:
|
|
88
|
-
return False
|
|
89
|
-
else:
|
|
90
|
-
return True
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
def parse_registry_uri(uri: str) -> RegistryURI:
|
|
94
|
-
"""
|
|
95
|
-
Validate and return (authority, chain_id, pkg_name, version)
|
|
96
|
-
from a valid registry URI.
|
|
97
|
-
"""
|
|
98
|
-
from web3 import (
|
|
99
|
-
LegacyWebSocketProvider,
|
|
100
|
-
Web3,
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
w3 = Web3(LegacyWebSocketProvider())
|
|
104
|
-
|
|
105
|
-
validate_registry_uri(uri)
|
|
106
|
-
parsed_uri = parse.urlparse(uri)
|
|
107
|
-
if ":" in parsed_uri.netloc:
|
|
108
|
-
address_or_ens, chain_id = parsed_uri.netloc.split(":")
|
|
109
|
-
else:
|
|
110
|
-
address_or_ens, chain_id = parsed_uri.netloc, "1"
|
|
111
|
-
ns = ENS.from_web3(w3)
|
|
112
|
-
if is_address(address_or_ens):
|
|
113
|
-
address = address_or_ens
|
|
114
|
-
ens = None
|
|
115
|
-
elif ns.address(address_or_ens):
|
|
116
|
-
address = ns.address(address_or_ens)
|
|
117
|
-
ens = address_or_ens
|
|
118
|
-
else:
|
|
119
|
-
raise CannotHandleURI(f"Invalid address or ENS domain found in uri: {uri}.")
|
|
120
|
-
pkg_name, pkg_version, namespaced_asset = _process_pkg_path(parsed_uri.path)
|
|
121
|
-
return RegistryURI(address, chain_id, pkg_name, pkg_version, namespaced_asset, ens)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
def _process_pkg_path(
|
|
125
|
-
raw_pkg_path: str,
|
|
126
|
-
) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
|
127
|
-
pkg_path = raw_pkg_path.strip("/")
|
|
128
|
-
if not pkg_path:
|
|
129
|
-
return None, None, None
|
|
130
|
-
|
|
131
|
-
pkg_id, namespaced_asset = _parse_pkg_path(pkg_path)
|
|
132
|
-
pkg_name, pkg_version = _parse_pkg_id(pkg_id)
|
|
133
|
-
if not pkg_version and namespaced_asset:
|
|
134
|
-
raise EthPMValidationError(
|
|
135
|
-
"Invalid registry URI, missing package version."
|
|
136
|
-
"Version is required if namespaced assets are defined."
|
|
137
|
-
)
|
|
138
|
-
return pkg_name, pkg_version, namespaced_asset
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
def _parse_pkg_path(pkg_path: str) -> Tuple[str, Optional[str]]:
|
|
142
|
-
if "/" in pkg_path:
|
|
143
|
-
pkg_id, _, namespaced_asset = pkg_path.partition("/")
|
|
144
|
-
return pkg_id, namespaced_asset
|
|
145
|
-
else:
|
|
146
|
-
return pkg_path, None
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def _parse_pkg_id(pkg_id: str) -> Tuple[str, Optional[str]]:
|
|
150
|
-
if "@" not in pkg_id:
|
|
151
|
-
return pkg_id, None
|
|
152
|
-
pkg_name, _, safe_pkg_version = pkg_id.partition("@")
|
|
153
|
-
pkg_version = parse.unquote(safe_pkg_version)
|
|
154
|
-
return pkg_name, pkg_version
|
ethpm/constants.py
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
REGISTRY_URI_SCHEMES = ("erc1319", "ethpm")
|
|
2
|
-
|
|
3
|
-
PACKAGE_NAME_REGEX = "^[a-zA-Z][-_a-zA-Z0-9]{0,255}$"
|
|
4
|
-
|
|
5
|
-
DEFAULT_IPFS_BACKEND = "ethpm.backends.ipfs.InfuraIPFSBackend"
|
|
6
|
-
|
|
7
|
-
IPFS_GATEWAY_PREFIX = "https://ipfs.io/ipfs/"
|
|
8
|
-
|
|
9
|
-
INFURA_GATEWAY_MULTIADDR = "/dns4/ipfs.infura.io/tcp/5001/https/"
|
|
10
|
-
|
|
11
|
-
GITHUB_API_AUTHORITY = "api.github.com"
|
|
12
|
-
|
|
13
|
-
SUPPORTED_CHAIN_IDS = {
|
|
14
|
-
1: "mainnet",
|
|
15
|
-
5: "goerli",
|
|
16
|
-
11155111: "sepolia",
|
|
17
|
-
}
|
ethpm/contract.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
from typing import (
|
|
2
|
-
TYPE_CHECKING,
|
|
3
|
-
Any,
|
|
4
|
-
Dict,
|
|
5
|
-
List,
|
|
6
|
-
Optional,
|
|
7
|
-
Tuple,
|
|
8
|
-
Type,
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
from eth_utils import (
|
|
12
|
-
combomethod,
|
|
13
|
-
is_canonical_address,
|
|
14
|
-
to_bytes,
|
|
15
|
-
to_canonical_address,
|
|
16
|
-
)
|
|
17
|
-
from eth_utils.toolz import (
|
|
18
|
-
assoc,
|
|
19
|
-
curry,
|
|
20
|
-
pipe,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
from ethpm.exceptions import (
|
|
24
|
-
BytecodeLinkingError,
|
|
25
|
-
EthPMValidationError,
|
|
26
|
-
)
|
|
27
|
-
from ethpm.validation.misc import (
|
|
28
|
-
validate_empty_bytes,
|
|
29
|
-
)
|
|
30
|
-
from web3._utils.compat import (
|
|
31
|
-
Self,
|
|
32
|
-
)
|
|
33
|
-
from web3._utils.validation import (
|
|
34
|
-
validate_address,
|
|
35
|
-
)
|
|
36
|
-
from web3.contract import (
|
|
37
|
-
Contract,
|
|
38
|
-
ContractConstructor,
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
if TYPE_CHECKING:
|
|
42
|
-
from web3 import Web3 # noqa: F401
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class LinkableContract(Contract):
|
|
46
|
-
"""
|
|
47
|
-
A subclass of web3.contract.Contract that is capable of handling
|
|
48
|
-
contract factories with link references in their package's manifest.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
unlinked_references: Optional[Tuple[Dict[str, Any]]] = None
|
|
52
|
-
linked_references: Optional[Tuple[Dict[str, Any]]] = None
|
|
53
|
-
needs_bytecode_linking = None
|
|
54
|
-
|
|
55
|
-
def __init__(self, address: bytes, **kwargs: Any) -> None:
|
|
56
|
-
if self.needs_bytecode_linking:
|
|
57
|
-
raise BytecodeLinkingError(
|
|
58
|
-
"Contract cannot be instantiated until its bytecode is linked."
|
|
59
|
-
)
|
|
60
|
-
validate_address(address)
|
|
61
|
-
# type ignored to allow for undefined **kwargs on `Contract` base class __init__
|
|
62
|
-
super().__init__(address=address, **kwargs) # type: ignore
|
|
63
|
-
|
|
64
|
-
@classmethod
|
|
65
|
-
def factory(cls, w3: "Web3", class_name: str = None, **kwargs: Any) -> Type[Self]:
|
|
66
|
-
dep_link_refs = kwargs.get("unlinked_references")
|
|
67
|
-
bytecode = kwargs.get("bytecode")
|
|
68
|
-
needs_bytecode_linking = False
|
|
69
|
-
if dep_link_refs and bytecode:
|
|
70
|
-
if not is_prelinked_bytecode(to_bytes(hexstr=bytecode), dep_link_refs):
|
|
71
|
-
needs_bytecode_linking = True
|
|
72
|
-
kwargs = assoc(kwargs, "needs_bytecode_linking", needs_bytecode_linking)
|
|
73
|
-
return super().factory(w3, class_name, **kwargs)
|
|
74
|
-
|
|
75
|
-
@classmethod
|
|
76
|
-
def constructor(cls, *args: Any, **kwargs: Any) -> ContractConstructor:
|
|
77
|
-
if cls.needs_bytecode_linking:
|
|
78
|
-
raise BytecodeLinkingError(
|
|
79
|
-
"Contract cannot be deployed until its bytecode is linked."
|
|
80
|
-
)
|
|
81
|
-
return super().constructor(*args, **kwargs)
|
|
82
|
-
|
|
83
|
-
@classmethod
|
|
84
|
-
def link_bytecode(cls, attr_dict: Dict[str, str]) -> Type["LinkableContract"]:
|
|
85
|
-
"""
|
|
86
|
-
Return a cloned contract factory with the deployment / runtime bytecode linked.
|
|
87
|
-
|
|
88
|
-
:attr_dict: Dict[`ContractType`: `Address`] for all deployment and runtime
|
|
89
|
-
link references.
|
|
90
|
-
"""
|
|
91
|
-
if not cls.unlinked_references and not cls.linked_references:
|
|
92
|
-
raise BytecodeLinkingError("Contract factory has no linkable bytecode.")
|
|
93
|
-
if not cls.needs_bytecode_linking:
|
|
94
|
-
raise BytecodeLinkingError(
|
|
95
|
-
"Bytecode for this contract factory does not require bytecode linking."
|
|
96
|
-
)
|
|
97
|
-
cls.validate_attr_dict(attr_dict)
|
|
98
|
-
bytecode = apply_all_link_refs(cls.bytecode, cls.unlinked_references, attr_dict)
|
|
99
|
-
runtime = apply_all_link_refs(
|
|
100
|
-
cls.bytecode_runtime, cls.linked_references, attr_dict
|
|
101
|
-
)
|
|
102
|
-
linked_class = cls.factory(cls.w3, bytecode_runtime=runtime, bytecode=bytecode)
|
|
103
|
-
if linked_class.needs_bytecode_linking:
|
|
104
|
-
raise BytecodeLinkingError(
|
|
105
|
-
"Expected class to be fully linked, but class "
|
|
106
|
-
"still needs bytecode linking."
|
|
107
|
-
)
|
|
108
|
-
return linked_class
|
|
109
|
-
|
|
110
|
-
@combomethod
|
|
111
|
-
def validate_attr_dict(self, attr_dict: Dict[str, str]) -> None:
|
|
112
|
-
"""
|
|
113
|
-
Validates that ContractType keys in attr_dict reference existing
|
|
114
|
-
manifest ContractTypes.
|
|
115
|
-
"""
|
|
116
|
-
attr_dict_names = attr_dict.keys()
|
|
117
|
-
|
|
118
|
-
if not self.unlinked_references and not self.linked_references:
|
|
119
|
-
raise BytecodeLinkingError(
|
|
120
|
-
"Unable to validate attr dict, this contract has no "
|
|
121
|
-
"linked/unlinked references."
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
unlinked_refs = self.unlinked_references or ({},)
|
|
125
|
-
linked_refs = self.linked_references or ({},)
|
|
126
|
-
all_link_refs = unlinked_refs + linked_refs
|
|
127
|
-
|
|
128
|
-
all_link_names = {ref["name"] for ref in all_link_refs if ref}
|
|
129
|
-
if attr_dict_names != all_link_names:
|
|
130
|
-
raise BytecodeLinkingError(
|
|
131
|
-
"All link references must be defined when calling "
|
|
132
|
-
"`link_bytecode` on a contract factory."
|
|
133
|
-
)
|
|
134
|
-
for address in attr_dict.values():
|
|
135
|
-
validate_address(address)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def is_prelinked_bytecode(bytecode: bytes, link_refs: List[Dict[str, Any]]) -> bool:
|
|
139
|
-
"""
|
|
140
|
-
Returns False if all expected link_refs are unlinked, otherwise returns True.
|
|
141
|
-
todo support partially pre-linked bytecode (currently all or nothing)
|
|
142
|
-
"""
|
|
143
|
-
for link_ref in link_refs:
|
|
144
|
-
for offset in link_ref["offsets"]:
|
|
145
|
-
try:
|
|
146
|
-
validate_empty_bytes(offset, link_ref["length"], bytecode)
|
|
147
|
-
except EthPMValidationError:
|
|
148
|
-
return True
|
|
149
|
-
return False
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def apply_all_link_refs(
|
|
153
|
-
bytecode: bytes, link_refs: List[Dict[str, Any]], attr_dict: Dict[str, str]
|
|
154
|
-
) -> bytes:
|
|
155
|
-
"""
|
|
156
|
-
Applies all link references corresponding to a valid attr_dict to the bytecode.
|
|
157
|
-
"""
|
|
158
|
-
if link_refs is None:
|
|
159
|
-
return bytecode
|
|
160
|
-
link_fns = (
|
|
161
|
-
apply_link_ref(offset, ref["length"], attr_dict[ref["name"]])
|
|
162
|
-
for ref in link_refs
|
|
163
|
-
for offset in ref["offsets"]
|
|
164
|
-
)
|
|
165
|
-
linked_bytecode = pipe(bytecode, *link_fns)
|
|
166
|
-
return linked_bytecode
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
@curry
|
|
170
|
-
def apply_link_ref(offset: int, length: int, value: bytes, bytecode: bytes) -> bytes:
|
|
171
|
-
"""
|
|
172
|
-
Returns the new bytecode with `value` put into the location indicated by
|
|
173
|
-
`offset` and `length`.
|
|
174
|
-
"""
|
|
175
|
-
try:
|
|
176
|
-
validate_empty_bytes(offset, length, bytecode)
|
|
177
|
-
except EthPMValidationError:
|
|
178
|
-
raise BytecodeLinkingError("Link references cannot be applied to bytecode")
|
|
179
|
-
|
|
180
|
-
address = value if is_canonical_address(value) else to_canonical_address(value)
|
|
181
|
-
new_bytes = (
|
|
182
|
-
# Ignore linting error b/c conflict b/w black & flake8
|
|
183
|
-
bytecode[:offset]
|
|
184
|
-
+ address
|
|
185
|
-
+ bytecode[offset + length :] # noqa: E201, E203
|
|
186
|
-
)
|
|
187
|
-
return new_bytes
|
ethpm/dependencies.py
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
from typing import (
|
|
2
|
-
Dict,
|
|
3
|
-
List,
|
|
4
|
-
Tuple,
|
|
5
|
-
)
|
|
6
|
-
|
|
7
|
-
from ethpm.validation.package import (
|
|
8
|
-
validate_package_name,
|
|
9
|
-
)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class Dependencies:
|
|
13
|
-
"""
|
|
14
|
-
Class to manage the `Package` instances of a Package's `buildDependencies`.
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
|
-
# ignoring Package type here and below to avoid a circular dependency
|
|
18
|
-
def __init__(
|
|
19
|
-
self, build_dependencies: Dict[str, "Package"] # type: ignore # noqa: F821
|
|
20
|
-
) -> None:
|
|
21
|
-
self.build_dependencies = build_dependencies
|
|
22
|
-
|
|
23
|
-
def __getitem__(self, key: str) -> "Package": # type: ignore # noqa: F821
|
|
24
|
-
return self.build_dependencies.get(key)
|
|
25
|
-
|
|
26
|
-
def __contains__(self, key: str) -> bool:
|
|
27
|
-
return key in self.build_dependencies
|
|
28
|
-
|
|
29
|
-
def _validate_name(self, name: str) -> None:
|
|
30
|
-
validate_package_name(name)
|
|
31
|
-
if name not in self.build_dependencies:
|
|
32
|
-
raise KeyError(f"Package name: {name} not found in build dependencies.")
|
|
33
|
-
|
|
34
|
-
def items(self) -> Tuple[Tuple[str, "Package"], ...]: # type: ignore # noqa: F821
|
|
35
|
-
"""
|
|
36
|
-
Return an iterable containing package name and
|
|
37
|
-
corresponding `Package` instance that are available.
|
|
38
|
-
"""
|
|
39
|
-
item_dict = {
|
|
40
|
-
name: self.build_dependencies.get(name) for name in self.build_dependencies
|
|
41
|
-
}
|
|
42
|
-
return tuple(item_dict.items())
|
|
43
|
-
|
|
44
|
-
def values(self) -> List["Package"]: # type: ignore # noqa: F821
|
|
45
|
-
"""
|
|
46
|
-
Return an iterable of the available `Package` instances.
|
|
47
|
-
"""
|
|
48
|
-
values = [self.build_dependencies.get(name) for name in self.build_dependencies]
|
|
49
|
-
return values
|
|
50
|
-
|
|
51
|
-
def get_dependency_package(
|
|
52
|
-
self, package_name: str
|
|
53
|
-
) -> "Package": # type: ignore # noqa: F821
|
|
54
|
-
"""
|
|
55
|
-
Return the dependency Package for a given package name.
|
|
56
|
-
"""
|
|
57
|
-
self._validate_name(package_name)
|
|
58
|
-
return self.build_dependencies.get(package_name)
|