diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8dfa57d88752957c015b83103664f2dc29e71721..648a89363ca2c3bf1c101f95e84b935eb23007c6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -108,11 +108,6 @@ pre-commit:hooks: - poetry install - poetry run pytest -tests:3.8: - extends: .tests - variables: - PYTHON_VERSION: "3.8" - tests:3.9: extends: .tests variables: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4b214b83aa19d7763bf127f111f3fd72abc4cd90..ef7f75990004cd2475eca04ef6e8ead1914942d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: rev: v3.15.0 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py39-plus] - repo: https://github.com/Lucas-C/pre-commit-hooks rev: v1.5.4 hooks: diff --git a/README.md b/README.md index 82ed31e0e19c5222c749342f3cd1f7b4e2fb5661..757cf61cce7be1a8a0dfd600324c8876f7b8d08e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ It is currently used by following programs: ## Requirements -- Python >= 3.8.0 +- Python >= 3.9.0 - [graphql-core](https://pypi.org/project/graphql-core) - [websocket-client](https://pypi.org/project/websocket-client) - [jsonschema](https://pypi.org/project/jsonschema) diff --git a/docs/index.rst b/docs/index.rst index 2468ca16423d3814f19d1e8e66667981ae2c69be..aa103b3b88239fc8b22ca637ad13137adcbd3d6c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -16,7 +16,7 @@ DuniterPy helps to handle the following problem: Requirements ------------ -DuniterPy requires Python 3.8.0 minimum. +DuniterPy requires Python 3.9.0 minimum. Installation ------------ diff --git a/duniterpy/api/endpoint.py b/duniterpy/api/endpoint.py index 4fb0fd08aa1143a4799ae17c9f7ca7057d181bac..c4eb05342760191689323348cf762af61da8759f 100644 --- a/duniterpy/api/endpoint.py +++ b/duniterpy/api/endpoint.py @@ -15,7 +15,7 @@ import re from ipaddress import ip_address -from typing import Any, Dict, Optional, Tuple, Type, TypeVar +from typing import Any, Dict, Optional, TypeVar from duniterpy import constants as const @@ -61,7 +61,7 @@ EndpointType = TypeVar("EndpointType", bound="Endpoint") class Endpoint: @classmethod - def from_inline(cls: Type[EndpointType], inline: str) -> EndpointType: + def from_inline(cls: type[EndpointType], inline: str) -> EndpointType: raise NotImplementedError("from_inline(..) is not implemented") def inline(self) -> str: @@ -89,7 +89,7 @@ class UnknownEndpoint(Endpoint): self.properties = properties @classmethod - def from_inline(cls: Type[UnknownEndpointType], inline: str) -> UnknownEndpointType: + def from_inline(cls: type[UnknownEndpointType], inline: str) -> UnknownEndpointType: """ Return UnknownEndpoint instance from endpoint string @@ -161,7 +161,7 @@ class BMAEndpoint(Endpoint): self.port = port @classmethod - def from_inline(cls: Type[BMAEndpointType], inline: str) -> BMAEndpointType: + def from_inline(cls: type[BMAEndpointType], inline: str) -> BMAEndpointType: """ Return BMAEndpoint instance from endpoint string @@ -252,7 +252,7 @@ class SecuredBMAEndpoint(BMAEndpoint): @classmethod def from_inline( - cls: Type[SecuredBMAEndpointType], inline: str + cls: type[SecuredBMAEndpointType], inline: str ) -> SecuredBMAEndpointType: """ Return SecuredBMAEndpoint instance from endpoint string @@ -325,7 +325,7 @@ class WS2PEndpoint(Endpoint): self.path = path @classmethod - def from_inline(cls: Type[WS2PEndpointType], inline: str) -> WS2PEndpointType: + def from_inline(cls: type[WS2PEndpointType], inline: str) -> WS2PEndpointType: """ Return WS2PEndpoint instance from endpoint string @@ -402,7 +402,7 @@ class ESCoreEndpoint(Endpoint): self.port = port @classmethod - def from_inline(cls: Type[ESCoreEndpointType], inline: str) -> ESCoreEndpointType: + def from_inline(cls: type[ESCoreEndpointType], inline: str) -> ESCoreEndpointType: """ Return ESCoreEndpoint instance from endpoint string @@ -461,7 +461,7 @@ class ESUserEndpoint(Endpoint): self.port = port @classmethod - def from_inline(cls: Type[ESUserEndpointType], inline: str) -> ESUserEndpointType: + def from_inline(cls: type[ESUserEndpointType], inline: str) -> ESUserEndpointType: """ Return ESUserEndpoint instance from endpoint string @@ -523,7 +523,7 @@ class ESSubscribtionEndpoint(Endpoint): @classmethod def from_inline( - cls: Type[ESSubscribtionEndpointType], inline: str + cls: type[ESSubscribtionEndpointType], inline: str ) -> ESSubscribtionEndpointType: """ Return ESSubscribtionEndpoint instance from endpoint string @@ -604,7 +604,7 @@ class GVAEndpoint(Endpoint): self.path = path @classmethod - def from_inline(cls: Type[GVAEndpointType], inline: str) -> GVAEndpointType: + def from_inline(cls: type[GVAEndpointType], inline: str) -> GVAEndpointType: """ Return GVAEndpoint instance from endpoint string @@ -729,7 +729,7 @@ def endpoint(value: Any) -> Any: return result -def fix_host_ipv4_mix_up(host: str, ipv4: str) -> Tuple[str, str]: +def fix_host_ipv4_mix_up(host: str, ipv4: str) -> tuple[str, str]: mixed_up = False try: mixed_up = ip_address(host).version == 4 and not ipv4 diff --git a/duniterpy/documents/block.py b/duniterpy/documents/block.py index 52c9c8c0e9d3a5a7c07579ed1066b055fe9a2c0a..e199a33d19a44f60a251fbf1e6812768fef7c7bf 100644 --- a/duniterpy/documents/block.py +++ b/duniterpy/documents/block.py @@ -16,7 +16,8 @@ import base64 import hashlib import re -from typing import List, Optional, Sequence, Type, TypeVar +from collections.abc import Sequence +from typing import Optional, TypeVar from ..constants import BLOCK_HASH_REGEX, G1_CURRENCY_CODENAME, PUBKEY_REGEX @@ -162,14 +163,14 @@ class Block(Document): prev_issuer: Optional[str], parameters: Optional[Sequence[str]], members_count: int, - identities: List[Identity], - joiners: List[Membership], - actives: List[Membership], - leavers: List[Membership], - revokations: List[Revocation], - excluded: List[str], - certifications: List[Certification], - transactions: List[Transaction], + identities: list[Identity], + joiners: list[Membership], + actives: list[Membership], + leavers: list[Membership], + revokations: list[Revocation], + excluded: list[str], + certifications: list[Certification], + transactions: list[Transaction], inner_hash: str, nonce: int, signing_key: Optional[SigningKey] = None, @@ -258,7 +259,7 @@ class Block(Document): return BlockID(self.number, self.proof_of_work()) @classmethod - def from_parsed_json(cls: Type[BlockType], parsed_json_block: dict) -> BlockType: + def from_parsed_json(cls: type[BlockType], parsed_json_block: dict) -> BlockType: """ Return a Block instance from the python dict produced when parsing json @@ -351,7 +352,7 @@ class Block(Document): return block @classmethod - def from_signed_raw(cls: Type[BlockType], signed_raw: str) -> BlockType: + def from_signed_raw(cls: type[BlockType], signed_raw: str) -> BlockType: """ Create Block instance from signed raw format string diff --git a/duniterpy/documents/block_id.py b/duniterpy/documents/block_id.py index d415fe26b089856fa606e192e11f5962667b2c55..5371417d7c5ab32e3ea57c063eed9b9ce92195e0 100644 --- a/duniterpy/documents/block_id.py +++ b/duniterpy/documents/block_id.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Type, TypeVar, Union +from typing import TypeVar, Union from ..constants import BLOCK_HASH_REGEX, BLOCK_NUMBER_REGEX, EMPTY_HASH from .document import MalformedDocumentError @@ -38,11 +38,11 @@ class BlockID: self.sha_hash = sha_hash @classmethod - def empty(cls: Type[BlockIDType]) -> BlockIDType: + def empty(cls: type[BlockIDType]) -> BlockIDType: return cls(0, EMPTY_HASH) @classmethod - def from_str(cls: Type[BlockIDType], blockid: str) -> BlockIDType: + def from_str(cls: type[BlockIDType], blockid: str) -> BlockIDType: """ :param blockid: The block id """ diff --git a/duniterpy/documents/certification.py b/duniterpy/documents/certification.py index 766f8597ec5cce764f52adeaeda27ddef1aaa729..90fbe5b382bb957b1062be8986fc89d10f29e3ae 100644 --- a/duniterpy/documents/certification.py +++ b/duniterpy/documents/certification.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Any, Optional, Type, TypeVar, Union +from typing import Any, Optional, TypeVar, Union from ..constants import ( BLOCK_ID_REGEX, @@ -107,7 +107,7 @@ class Certification(Document): @classmethod def from_signed_raw( - cls: Type[CertificationType], signed_raw: str + cls: type[CertificationType], signed_raw: str ) -> CertificationType: """ Return Certification instance from signed raw document @@ -149,7 +149,7 @@ class Certification(Document): @classmethod def from_inline( - cls: Type[CertificationType], + cls: type[CertificationType], block_hash: Optional[str], inline: str, version: int = VERSION, diff --git a/duniterpy/documents/document.py b/duniterpy/documents/document.py index f7856641c4aa415e6c0f26e2ed0358aadfdf1fd3..4f90137fe89151ec1311872b77065e0371f54205 100644 --- a/duniterpy/documents/document.py +++ b/duniterpy/documents/document.py @@ -17,7 +17,8 @@ import base64 import hashlib import logging import re -from typing import Any, Dict, Optional, Pattern, Type, TypeVar +from re import Pattern +from typing import Any, Optional, TypeVar from ..constants import SIGNATURE_REGEX from ..key import SigningKey, VerifyingKey @@ -50,7 +51,7 @@ class Document: re_currency = re.compile("Currency: ([^\n]+)\n") re_signature = re.compile(f"({SIGNATURE_REGEX})\n") - fields_parsers: Dict[str, Pattern] = { + fields_parsers: dict[str, Pattern] = { "Version": re_version, "Currency": re_currency, "Signature": re_signature, @@ -89,7 +90,7 @@ class Document: ) @classmethod - def parse_field(cls: Type[DocumentType], field_name: str, line: str) -> Any: + def parse_field(cls: type[DocumentType], field_name: str, line: str) -> Any: """ Parse a document field with regular expression and return the value diff --git a/duniterpy/documents/identity.py b/duniterpy/documents/identity.py index 3f9ca96441492d07ea1d95a51857ff5a33559c08..42f1797f7456d172e872a63ba96560b58ce6ee7b 100644 --- a/duniterpy/documents/identity.py +++ b/duniterpy/documents/identity.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Any, Optional, Type, TypeVar +from typing import Any, Optional, TypeVar from ..constants import ( BLOCK_ID_REGEX, @@ -127,7 +127,7 @@ class Identity(Document): @classmethod def from_inline( - cls: Type[IdentityType], + cls: type[IdentityType], inline: str, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, @@ -155,7 +155,7 @@ class Identity(Document): return identity @classmethod - def from_signed_raw(cls: Type[IdentityType], signed_raw: str) -> IdentityType: + def from_signed_raw(cls: type[IdentityType], signed_raw: str) -> IdentityType: """ Return Identity instance from a signed_raw string @@ -214,7 +214,7 @@ Timestamp: {self.block_id}\n" @classmethod def from_certification_raw( - cls: Type[IdentityType], certification_raw: str + cls: type[IdentityType], certification_raw: str ) -> IdentityType: """ Return Identity instance from certification_raw @@ -248,7 +248,7 @@ Timestamp: {self.block_id}\n" @classmethod def from_revocation_raw( - cls: Type[IdentityType], revocation_raw: str + cls: type[IdentityType], revocation_raw: str ) -> IdentityType: """ Return Identity instance from revocation_raw @@ -282,7 +282,7 @@ Timestamp: {self.block_id}\n" @classmethod def from_bma_lookup_response( - cls: Type[IdentityType], + cls: type[IdentityType], currency: str, pubkey: str, lookup_response: dict, diff --git a/duniterpy/documents/membership.py b/duniterpy/documents/membership.py index 214dd4e91ef30d36c15e32087704441d085a0955..2677421420f8b534895687ae895e18b758440a2b 100644 --- a/duniterpy/documents/membership.py +++ b/duniterpy/documents/membership.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Any, Optional, Type, TypeVar +from typing import Any, Optional, TypeVar from ..constants import ( BLOCK_ID_REGEX, @@ -136,7 +136,7 @@ class Membership(Document): @classmethod def from_inline( - cls: Type[MembershipType], + cls: type[MembershipType], inline: str, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, @@ -174,7 +174,7 @@ class Membership(Document): return membership @classmethod - def from_signed_raw(cls: Type[MembershipType], signed_raw: str) -> MembershipType: + def from_signed_raw(cls: type[MembershipType], signed_raw: str) -> MembershipType: """ Return Membership instance from signed raw format diff --git a/duniterpy/documents/peer.py b/duniterpy/documents/peer.py index a4bc301b3306a1ed4e017b2ffd59d728096b27b8..39b6c415e88f31a107452717962a1eb4ebc14cd5 100644 --- a/duniterpy/documents/peer.py +++ b/duniterpy/documents/peer.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import List, Optional, Type, TypeVar +from typing import Optional, TypeVar from duniterpy.api.endpoint import Endpoint, endpoint @@ -66,7 +66,7 @@ class Peer(Document): self, pubkey: str, block_id: BlockID, - endpoints: List[Endpoint], + endpoints: list[Endpoint], signing_key: Optional[SigningKey] = None, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, @@ -85,13 +85,13 @@ class Peer(Document): self.pubkey = pubkey self.block_id = block_id - self.endpoints: List[Endpoint] = endpoints + self.endpoints: list[Endpoint] = endpoints if signing_key is not None: self.sign(signing_key) @classmethod - def from_signed_raw(cls: Type[PeerType], raw: str) -> PeerType: + def from_signed_raw(cls: type[PeerType], raw: str) -> PeerType: """ Return a Peer instance from a signed raw format string @@ -154,7 +154,7 @@ Endpoints:\n" return doc @classmethod - def from_bma(cls: Type[PeerType], data: dict) -> PeerType: + def from_bma(cls: type[PeerType], data: dict) -> PeerType: # get Peer Document from bma dict version = data["version"] currency = data["currency"] diff --git a/duniterpy/documents/revocation.py b/duniterpy/documents/revocation.py index dcb82813af2c316c5122b2a506396a0eca820da5..4aab07588d68429690318d20048fbd0c5de6a18d 100644 --- a/duniterpy/documents/revocation.py +++ b/duniterpy/documents/revocation.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import re -from typing import Any, Optional, Type, TypeVar, Union +from typing import Any, Optional, TypeVar, Union from ..constants import ( BLOCK_ID_REGEX, @@ -99,7 +99,7 @@ class Revocation(Document): @classmethod def from_inline( - cls: Type[RevocationType], + cls: type[RevocationType], inline: str, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, @@ -127,7 +127,7 @@ class Revocation(Document): return revocation @classmethod - def from_signed_raw(cls: Type[RevocationType], signed_raw: str) -> RevocationType: + def from_signed_raw(cls: type[RevocationType], signed_raw: str) -> RevocationType: """ Return Revocation document instance from a signed raw string diff --git a/duniterpy/documents/transaction.py b/duniterpy/documents/transaction.py index 9ef56cc52c1e0e74272adc2ae96e497f695f3251..6ac1577148c40ab7c9a648de1b649e5db1dfbbf7 100644 --- a/duniterpy/documents/transaction.py +++ b/duniterpy/documents/transaction.py @@ -16,7 +16,7 @@ import base64 import logging import re -from typing import Any, Dict, List, Optional, Tuple, Type, TypeVar, Union +from typing import Any, Optional, TypeVar, Union import pypeg2 @@ -37,7 +37,7 @@ from .document import Document, MalformedDocumentError VERSION = 10 -def reduce_base(amount: int, base: int) -> Tuple[int, int]: +def reduce_base(amount: int, base: int) -> tuple[int, int]: """ Compute the reduced base of the given parameters @@ -119,7 +119,7 @@ class InputSource: return hash((self.amount, self.base, self.source, self.origin_id, self.index)) @classmethod - def from_inline(cls: Type[InputSourceType], inline: str) -> InputSourceType: + def from_inline(cls: type[InputSourceType], inline: str) -> InputSourceType: """ Return Transaction instance from inline string format @@ -191,7 +191,7 @@ class OutputSource: return hash((self.amount, self.base, self.condition)) @classmethod - def from_inline(cls: Type[OutputSourceType], inline: str) -> OutputSourceType: + def from_inline(cls: type[OutputSourceType], inline: str) -> OutputSourceType: """ Return OutputSource instance from inline string format @@ -272,7 +272,7 @@ class SIGParameter: @classmethod def from_parameter( - cls: Type[SIGParameterType], parameter: str + cls: type[SIGParameterType], parameter: str ) -> Optional[SIGParameterType]: """ Return a SIGParameter instance from an index parameter @@ -328,7 +328,7 @@ class XHXParameter: @classmethod def from_parameter( - cls: Type[XHXParameterType], parameter: str + cls: type[XHXParameterType], parameter: str ) -> Optional[XHXParameterType]: """ Return a XHXParameter instance from an index parameter @@ -362,7 +362,7 @@ UnlockParameterType = TypeVar("UnlockParameterType", bound="UnlockParameter") class UnlockParameter: @classmethod def from_parameter( - cls: Type[UnlockParameterType], parameter: str + cls: type[UnlockParameterType], parameter: str ) -> Optional[Union[SIGParameter, XHXParameter]]: """ Return UnlockParameter instance from parameter string @@ -397,7 +397,7 @@ class Unlock: re_inline = re.compile("([0-9]+):((?:SIG\\([0-9]+\\)|XHX\\([0-9]+\\)|\\s)+)") def __init__( - self, index: int, parameters: List[Union[SIGParameter, XHXParameter]] + self, index: int, parameters: list[Union[SIGParameter, XHXParameter]] ) -> None: """ Init Unlock instance @@ -425,7 +425,7 @@ class Unlock: return hash((self.index, self.parameters)) @classmethod - def from_inline(cls: Type[UnlockType], inline: str) -> UnlockType: + def from_inline(cls: type[UnlockType], inline: str) -> UnlockType: """ Return an Unlock instance from inline string format @@ -535,13 +535,13 @@ class Transaction(Document): self, block_id: Optional[BlockID], locktime: int, - issuers: List[str], - inputs: List[InputSource], - unlocks: List[Unlock], - outputs: List[OutputSource], + issuers: list[str], + inputs: list[InputSource], + unlocks: list[Unlock], + outputs: list[OutputSource], comment: str, time: Optional[int] = None, - signing_keys: Optional[Union[SigningKey, List[SigningKey]]] = None, + signing_keys: Optional[Union[SigningKey, list[SigningKey]]] = None, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, ) -> None: @@ -569,7 +569,7 @@ class Transaction(Document): self.outputs = outputs self.comment = comment self.time = time - self.signatures: List[str] = [] + self.signatures: list[str] = [] if signing_keys: self.multi_sign(signing_keys) @@ -612,7 +612,7 @@ class Transaction(Document): @classmethod def from_bma_history( - cls: Type[TransactionType], tx_data: Dict, currency: str = G1_CURRENCY_CODENAME + cls: type[TransactionType], tx_data: dict, currency: str = G1_CURRENCY_CODENAME ) -> TransactionType: """ Get the transaction instance from json @@ -649,7 +649,7 @@ Comment: {comment} @classmethod def from_compact( - cls: Type[TransactionType], compact: str, currency: str = G1_CURRENCY_CODENAME + cls: type[TransactionType], compact: str, currency: str = G1_CURRENCY_CODENAME ) -> TransactionType: """ Return Transaction instance from compact string format @@ -738,7 +738,7 @@ Comment: {comment} @classmethod def from_signed_raw( - cls: Type[TransactionType], raw: str, time: int = 0 + cls: type[TransactionType], raw: str, time: int = 0 ) -> TransactionType: """ Return a Transaction instance from a raw string format @@ -925,7 +925,7 @@ Currency: {self.currency}\n" """ self.multi_sign(key) - def multi_sign(self, keys: Union[SigningKey, List[SigningKey]]) -> None: + def multi_sign(self, keys: Union[SigningKey, list[SigningKey]]) -> None: """ Add signature(s) to the document from one key or a list of multiple keys @@ -948,7 +948,7 @@ Currency: {self.currency}\n" """ return self.check_signatures(pubkey) - def check_signatures(self, pubkeys: Union[str, List[str]]) -> bool: + def check_signatures(self, pubkeys: Union[str, list[str]]) -> bool: """ Check if the signatures matches a public key or a list of public keys @@ -989,11 +989,11 @@ class SimpleTransaction(Transaction): locktime: int, issuer: str, single_input: InputSource, - unlocks: List[Unlock], - outputs: List[OutputSource], + unlocks: list[Unlock], + outputs: list[OutputSource], comment: str, time: int = 0, - signing_keys: Optional[Union[SigningKey, List[SigningKey]]] = None, + signing_keys: Optional[Union[SigningKey, list[SigningKey]]] = None, version: int = VERSION, currency: str = G1_CURRENCY_CODENAME, ) -> None: diff --git a/duniterpy/grammars/output.py b/duniterpy/grammars/output.py index b648a7638f9814d990741b46fb771ae4e077bb3c..398e30b575d6d24351a8ad5161afd8a440b84a16 100644 --- a/duniterpy/grammars/output.py +++ b/duniterpy/grammars/output.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -from typing import Any, Optional, Type, TypeVar, Union +from typing import Any, Optional, TypeVar, Union from pypeg2 import Enum, K, Keyword, attr, contiguous, maybe_some, re, whitespace @@ -79,7 +79,7 @@ class SIG: return hash((self.value, self.pubkey)) @classmethod - def token(cls: Type[SIGType], pubkey: str) -> SIGType: + def token(cls: type[SIGType], pubkey: str) -> SIGType: """ Return SIG instance from pubkey @@ -139,7 +139,7 @@ class CSV: return hash((self.value, self.time)) @classmethod - def token(cls: Type[CSVType], time: int) -> CSVType: + def token(cls: type[CSVType], time: int) -> CSVType: """ Return CSV instance from time @@ -198,7 +198,7 @@ class CLTV: return hash((self.value, self.timestamp)) @classmethod - def token(cls: Type[CLTVType], timestamp: int) -> CLTVType: + def token(cls: type[CLTVType], timestamp: int) -> CLTVType: """ Return CLTV instance from timestamp @@ -257,7 +257,7 @@ class XHX: return hash((self.value, self.sha_hash)) @classmethod - def token(cls: Type[XHXType], sha_hash: str) -> XHXType: + def token(cls: type[XHXType], sha_hash: str) -> XHXType: """ Return XHX instance from sha_hash @@ -294,7 +294,7 @@ class Operator(Keyword): regex = re.compile(r"[&&|\|\||\w]+") @classmethod - def token(cls: Type[OperatorType], keyword: str) -> OperatorType: + def token(cls: type[OperatorType], keyword: str) -> OperatorType: """ Return Operator instance from keyword @@ -361,7 +361,7 @@ class Condition: @classmethod def token( - cls: Type[ConditionType], + cls: type[ConditionType], left: Any, op: Optional[Any] = None, right: Optional[Any] = None, diff --git a/duniterpy/helpers/network.py b/duniterpy/helpers/network.py index 692c41d4206f1bc2f323104d0c59f127bc93dccf..047bee6a854bf85bda533e55ec704946538885f0 100644 --- a/duniterpy/helpers/network.py +++ b/duniterpy/helpers/network.py @@ -14,7 +14,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. from itertools import groupby -from typing import Any, Dict, List +from typing import Any from duniterpy.api import bma from duniterpy.api.client import Client @@ -22,7 +22,7 @@ from duniterpy.documents.peer import MalformedDocumentError, Peer from duniterpy.documents.ws2p.heads import HeadV2 -def get_available_nodes(client: Client) -> List[List[Dict[str, Any]]]: +def get_available_nodes(client: Client) -> list[list[dict[str, Any]]]: """ Get available nodes grouped and sorted by descending block_id diff --git a/duniterpy/key/ascii_armor.py b/duniterpy/key/ascii_armor.py index c1973d305196dff9472c5f5a316aa56759bd5d5c..0b5952c9e5a4ffac0937f5298b261b8d84552bb1 100644 --- a/duniterpy/key/ascii_armor.py +++ b/duniterpy/key/ascii_armor.py @@ -16,7 +16,7 @@ import base64 import importlib.metadata import re -from typing import Any, Dict, List, Optional +from typing import Any, Optional import libnacl @@ -86,7 +86,7 @@ class AsciiArmor: def create( message: str, pubkey: Optional[str] = None, - signing_keys: Optional[List[SigningKey]] = None, + signing_keys: Optional[list[SigningKey]] = None, message_comment: Optional[str] = None, signatures_comment: Optional[str] = None, ) -> str: @@ -260,7 +260,7 @@ class AsciiArmor: def parse( ascii_armor_message: str, signing_key: Optional[SigningKey] = None, - sender_pubkeys: Optional[List[str]] = None, + sender_pubkeys: Optional[list[str]] = None, ) -> dict: """ Return a dict with parsed content (decrypted message, signature validation) :: @@ -298,7 +298,7 @@ class AsciiArmor: parsed_result = { "message": {"fields": {}, "content": ""}, "signatures": [], - } # type: Dict[str, Any] + } # type: dict[str, Any] cursor_status = 0 message = "" signatures_index = 0 diff --git a/duniterpy/key/crc_pubkey.py b/duniterpy/key/crc_pubkey.py index 3f8cbd9d8f5caf301827db4ddb3ad011713ab2fa..b5d69acf84086ffa8205056df443bb039b4251d3 100644 --- a/duniterpy/key/crc_pubkey.py +++ b/duniterpy/key/crc_pubkey.py @@ -15,7 +15,7 @@ import hashlib import re -from typing import Type, TypeVar +from typing import TypeVar import base58 @@ -48,7 +48,7 @@ class CRCPubkey: self.crc = crc @classmethod - def from_str(cls: Type[CRCPubkeyType], crc_pubkey: str) -> CRCPubkeyType: + def from_str(cls: type[CRCPubkeyType], crc_pubkey: str) -> CRCPubkeyType: """ Return CRCPubkey instance from CRC public key string @@ -63,7 +63,7 @@ class CRCPubkey: return cls(pubkey, crc) @classmethod - def from_pubkey(cls: Type[CRCPubkeyType], pubkey: str) -> CRCPubkeyType: + def from_pubkey(cls: type[CRCPubkeyType], pubkey: str) -> CRCPubkeyType: """ Return CRCPubkey instance from public key string diff --git a/duniterpy/key/signing_key.py b/duniterpy/key/signing_key.py index db49f77ccd5bc91fe71c339fae7bac1580d1387b..4e3983acfe9921983592bcbc7af55fa48e6f6fac 100644 --- a/duniterpy/key/signing_key.py +++ b/duniterpy/key/signing_key.py @@ -18,7 +18,7 @@ import os import re from hashlib import scrypt, sha256 from pathlib import Path -from typing import Optional, Type, TypeVar, Union +from typing import Optional, TypeVar, Union import libnacl.sign import pyaes @@ -57,7 +57,7 @@ class SigningKey(libnacl.sign.Signer): @classmethod def from_credentials( - cls: Type[SigningKeyType], + cls: type[SigningKeyType], salt: Union[str, bytes], password: Union[str, bytes], scrypt_params: Optional[ScryptParams] = None, @@ -87,7 +87,7 @@ class SigningKey(libnacl.sign.Signer): @classmethod def from_credentials_file( - cls: Type[SigningKeyType], + cls: type[SigningKeyType], path: Union[Path, str], scrypt_params: Optional[ScryptParams] = None, ) -> SigningKeyType: @@ -120,7 +120,7 @@ class SigningKey(libnacl.sign.Signer): fh.write(seedhex) @staticmethod - def from_seedhex_file(path: Union[Path, str]) -> Type[SigningKeyType]: + def from_seedhex_file(path: Union[Path, str]) -> type[SigningKeyType]: """ Return SigningKey instance from Seedhex file @@ -131,7 +131,7 @@ class SigningKey(libnacl.sign.Signer): return SigningKey.from_seedhex(seedhex) @classmethod - def from_seedhex(cls: Type[SigningKeyType], seedhex: str) -> SigningKeyType: + def from_seedhex(cls: type[SigningKeyType], seedhex: str) -> SigningKeyType: """ Return SigningKey instance from Seedhex @@ -154,7 +154,7 @@ class SigningKey(libnacl.sign.Signer): self.save(path) @staticmethod - def from_private_key(path: Union[Path, str]) -> Type[SigningKeyType]: + def from_private_key(path: Union[Path, str]) -> type[SigningKeyType]: """ Read authentication file Add public key attribute @@ -181,7 +181,7 @@ class SigningKey(libnacl.sign.Signer): @classmethod def from_pubsec_file( - cls: Type[SigningKeyType], path: Union[Path, str] + cls: type[SigningKeyType], path: Union[Path, str] ) -> SigningKeyType: """ Return SigningKey instance from Duniter WIF file @@ -240,7 +240,7 @@ sec: {base58_signing_key}" @staticmethod def from_wif_or_ewif_file( path: Union[Path, str], password: Optional[str] = None - ) -> Type[SigningKeyType]: + ) -> type[SigningKeyType]: """ Return SigningKey instance from Duniter WIF or EWIF file @@ -263,7 +263,7 @@ sec: {base58_signing_key}" @staticmethod def from_wif_or_ewif_hex( wif_hex: str, password: Optional[str] = None - ) -> Type[SigningKeyType]: + ) -> type[SigningKeyType]: """ Return SigningKey instance from Duniter WIF or EWIF in hexadecimal format @@ -286,7 +286,7 @@ sec: {base58_signing_key}" return result @staticmethod - def from_wif_file(path: Union[Path, str]) -> Type[SigningKeyType]: + def from_wif_file(path: Union[Path, str]) -> type[SigningKeyType]: """ Return SigningKey instance from Duniter WIF file @@ -306,7 +306,7 @@ sec: {base58_signing_key}" return SigningKey.from_wif_hex(wif_hex) @classmethod - def from_wif_hex(cls: Type[SigningKeyType], wif_hex: str) -> SigningKeyType: + def from_wif_hex(cls: type[SigningKeyType], wif_hex: str) -> SigningKeyType: """ Return SigningKey instance from Duniter WIF in hexadecimal format @@ -360,7 +360,7 @@ Data: {wif_key}" fh.write(content) @staticmethod - def from_ewif_file(path: Union[Path, str], password: str) -> Type[SigningKeyType]: + def from_ewif_file(path: Union[Path, str], password: str) -> type[SigningKeyType]: """ Return SigningKey instance from Duniter EWIF file @@ -382,7 +382,7 @@ Data: {wif_key}" @classmethod def from_ewif_hex( - cls: Type[SigningKeyType], ewif_hex: str, password: str + cls: type[SigningKeyType], ewif_hex: str, password: str ) -> SigningKeyType: """ Return SigningKey instance from Duniter EWIF in hexadecimal format @@ -490,7 +490,7 @@ Data: {ewif_key}" fh.write(content) @classmethod - def from_ssb_file(cls: Type[SigningKeyType], path: str) -> SigningKeyType: + def from_ssb_file(cls: type[SigningKeyType], path: str) -> SigningKeyType: """ Return SigningKey instance from ScuttleButt .ssb/secret file @@ -518,7 +518,7 @@ Data: {ewif_key}" @classmethod def from_dubp_mnemonic( - cls: Type[SigningKeyType], + cls: type[SigningKeyType], mnemonic: str, scrypt_params: Optional[ScryptParams] = None, ) -> SigningKeyType: diff --git a/examples/send_transaction.py b/examples/send_transaction.py index cb45153748065b15a68787d70920d034fbd30b6f..8bd005b90b247394da51c7144d12b8113545d7b2 100644 --- a/examples/send_transaction.py +++ b/examples/send_transaction.py @@ -15,7 +15,7 @@ import getpass import urllib -from typing import List, Union +from typing import Union from duniterpy.api import bma from duniterpy.api.client import Client @@ -43,7 +43,7 @@ def get_transaction_document( source: dict, from_pubkey: str, to_pubkey: str, - signing_keys: Union[SigningKey, List[SigningKey]], + signing_keys: Union[SigningKey, list[SigningKey]], ) -> Transaction: """ Return a Transaction document diff --git a/pyproject.toml b/pyproject.toml index ad1d933a7053d577d6deb432d75fb9bcad365787..b967370054befab1853a7be1d54f46239e933577 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.dependencies] -python = "^3.8.0" +python = "^3.9.0" graphql-core = "^3.2.3" websocket-client = "^1.5.2" jsonschema = "^4.17.3"