diff --git a/Makefile b/Makefile index 1590f14..34da47d 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ -all: black ruff mypy test -format: black ruff isort -lint: ruff mypy +all: black ruff pyright mypy test +format: black ruff +lint: pyright mypy checkruff check: checkblack checkruff black: @@ -15,6 +15,9 @@ checkruff: checkblack: poetry run black --check . +pyright: + poetry run pyright . + mypy: poetry run mypy . diff --git a/lnurl/core.py b/lnurl/core.py index 929fb6b..b524344 100644 --- a/lnurl/core.py +++ b/lnurl/core.py @@ -48,4 +48,4 @@ def handle( if lnurl.is_login: return LnurlAuthResponse(callback=lnurl.url, k1=lnurl.url.query_params["k1"]) - return get(lnurl.url, response_class=response_class) + return get(str(lnurl.url), response_class=response_class, verify=verify) diff --git a/lnurl/models.py b/lnurl/models.py index 14d8995..271c70b 100644 --- a/lnurl/models.py +++ b/lnurl/models.py @@ -1,7 +1,7 @@ import math from typing import List, Literal, Optional, Union -from pydantic import BaseModel, Field, validator +from pydantic import BaseModel, ConfigDict, Field, field_validator from .exceptions import LnurlResponseException from .types import ( @@ -45,16 +45,15 @@ class UrlAction(LnurlPaySuccessAction): class LnurlResponseModel(BaseModel): - class Config: - allow_population_by_field_name = True + model_config = ConfigDict(populate_by_name=True) def dict(self, **kwargs): kwargs.setdefault("by_alias", True) - return super().dict(**kwargs) + return super().model_dump(**kwargs) def json(self, **kwargs): kwargs.setdefault("by_alias", True) - return super().json(**kwargs) + return super().model_dump_json(**kwargs) @property def ok(self) -> bool: @@ -95,7 +94,7 @@ class LnurlHostedChannelResponse(LnurlResponseModel): tag: Literal["hostedChannelRequest"] = "hostedChannelRequest" uri: LightningNodeUri k1: str - alias: Optional[str] + alias: Optional[str] = None class LnurlPayResponse(LnurlResponseModel): @@ -105,8 +104,8 @@ class LnurlPayResponse(LnurlResponseModel): max_sendable: MilliSatoshi = Field(..., alias="maxSendable") metadata: LnurlPayMetadata - @validator("max_sendable") - def max_less_than_min(cls, value, values, **kwargs): # noqa + @field_validator("max_sendable") + def max_less_than_min(cls, value, values, **_): if "min_sendable" in values and value < values["min_sendable"]: raise ValueError("`max_sendable` cannot be less than `min_sendable`.") return value @@ -147,8 +146,8 @@ class LnurlWithdrawResponse(LnurlResponseModel): max_withdrawable: MilliSatoshi = Field(..., alias="maxWithdrawable") default_description: str = Field("", alias="defaultDescription") - @validator("max_withdrawable") - def max_less_than_min(cls, value, values, **kwargs): # noqa + @field_validator("max_withdrawable") + def max_less_than_min(cls, value, values, **_): if "min_withdrawable" in values and value < values["min_withdrawable"]: raise ValueError("`max_withdrawable` cannot be less than `min_withdrawable`.") return value diff --git a/lnurl/types.py b/lnurl/types.py index 8c269ee..8f28158 100644 --- a/lnurl/types.py +++ b/lnurl/types.py @@ -2,39 +2,15 @@ import os import re from hashlib import sha256 -from typing import List, Optional, Tuple, Union -from urllib.parse import parse_qs +from typing import Annotated, List, Optional, Tuple, Union -from pydantic import ( - ConstrainedStr, - HttpUrl, - Json, - PositiveInt, - ValidationError, - parse_obj_as, -) -from pydantic.errors import UrlHostTldError, UrlSchemeError -from pydantic.networks import Parts -from pydantic.validators import str_validator +from pydantic import Field, HttpUrl, Json, PositiveInt, TypeAdapter, UrlConstraints, ValidationError +from pydantic.functional_validators import AfterValidator from .exceptions import InvalidLnurlPayMetadata from .helpers import _bech32_decode, _lnurl_clean, _lnurl_decode -def ctrl_characters_validator(value: str) -> str: - """Checks for control characters (unicode blocks C0 and C1, plus DEL).""" - if re.compile(r"[\u0000-\u001f\u007f-\u009f]").search(value): - raise ValueError - return value - - -def strict_rfc3986_validator(value: str) -> str: - """Checks for RFC3986 compliance.""" - if re.compile(r"[^]a-zA-Z0-9._~:/?#[@!$&'()*+,;=-]").search(value): - raise ValueError - return value - - class ReprMixin: def __repr__(self) -> str: attrs = [ # type: ignore @@ -62,10 +38,10 @@ def __init__(self, bech32: str, *, hrp: Optional[str] = None, data: Optional[Lis def __get_data__(cls, bech32: str) -> Tuple[str, List[int]]: return _bech32_decode(bech32) - @classmethod - def __get_validators__(cls): - yield str_validator - yield cls.validate + # @classmethod + # def __get_validators__(cls): + # # yield str_validator + # yield cls.validate @classmethod def validate(cls, value: str) -> "Bech32": @@ -73,58 +49,69 @@ def validate(cls, value: str) -> "Bech32": return cls(value, hrp=hrp, data=data) -class Url(HttpUrl): - """URL with extra validations over pydantic's `HttpUrl`.""" - - max_length = 2047 # https://stackoverflow.com/questions/417142/ - - @classmethod - def __get_validators__(cls): - yield ctrl_characters_validator - if os.environ.get("LNURL_STRICT_RFC3986", "0") == "1": - yield strict_rfc3986_validator - yield cls.validate - - @property - def base(self) -> str: - hostport = f"{self.host}:{self.port}" if self.port else self.host - return f"{self.scheme}://{hostport}{self.path}" +def ctrl_characters_validator(value: str) -> str: + """Checks for control characters (unicode blocks C0 and C1, plus DEL).""" + if re.compile(r"[\u0000-\u001f\u007f-\u009f]").search(value): + raise ValidationError + return value - @property - def query_params(self) -> dict: - return {k: v[0] for k, v in parse_qs(self.query).items()} +def strict_rfc3986_validator(value: str) -> str: + """Checks for RFC3986 compliance.""" + if os.environ.get("LNURL_STRICT_RFC3986", "0") == "1": + if re.compile(r"[^]a-zA-Z0-9._~:/?#[@!$&'()*+,;=-]").search(value): + raise ValidationError + return value -class DebugUrl(Url): - """Unsecure web URL, to make developers life easier.""" - allowed_schemes = {"http"} +# Secure web URL +ClearnetUrl = Annotated[ + HttpUrl, + UrlConstraints( + max_length=2047, # https://stackoverflow.com/questions/417142/ + allowed_schemes=["https"], + ), + AfterValidator(ctrl_characters_validator), + AfterValidator(strict_rfc3986_validator), +] - @classmethod - def validate_host(cls, parts: Parts) -> Tuple[str, Optional[str], str, bool]: - host, tld, host_type, rebuild = super().validate_host(parts) - if host not in ["127.0.0.1", "0.0.0.0"]: - raise UrlSchemeError() - return host, tld, host_type, rebuild +def onion_validator(value: str) -> None: + """checks if it is a valid onion address""" + if not value.endswith(".onion"): + raise ValidationError -class ClearnetUrl(Url): - """Secure web URL.""" - allowed_schemes = {"https"} +# Tor anonymous onion service +OnionUrl = Annotated[ + HttpUrl, + UrlConstraints( + max_length=2047, # https://stackoverflow.com/questions/417142/ + allowed_schemes=["http"], + ), + AfterValidator(ctrl_characters_validator), + AfterValidator(strict_rfc3986_validator), + AfterValidator(onion_validator), +] -class OnionUrl(Url): - """Tor anonymous onion service.""" +def localhost_validator(value: str) -> None: + # host, tld, host_type, rebuild = super().validate_host(parts) + if not value.find("127.0.0.1") or not value.find("0.0.0.0"): + raise ValidationError - allowed_schemes = {"https", "http"} - @classmethod - def validate_host(cls, parts: Parts) -> Tuple[str, Optional[str], str, bool]: - host, tld, host_type, rebuild = super().validate_host(parts) - if tld != "onion": - raise UrlHostTldError() - return host, tld, host_type, rebuild +# Unsecure web URL, to make developers life easier +DebugUrl = Annotated[ + HttpUrl, + UrlConstraints( + max_length=2047, # https://stackoverflow.com/questions/417142/ + allowed_schemes=["http"], + ), + AfterValidator(ctrl_characters_validator), + AfterValidator(strict_rfc3986_validator), + AfterValidator(localhost_validator), +] class LightningInvoice(Bech32): @@ -146,31 +133,31 @@ def h(self): class LightningNodeUri(ReprMixin, str): """Remote node address of form `node_key@ip_address:port_number`.""" - __slots__ = ("key", "ip", "port") + # __slots__ = ("key", "ip", "port") - def __new__(cls, uri: str, **kwargs) -> "LightningNodeUri": - return str.__new__(cls, uri) + # def __new__(cls, uri: str, **_) -> "LightningNodeUri": + # return str.__new__(cls, uri) - def __init__(self, uri: str, *, key: Optional[str] = None, ip: Optional[str] = None, port: Optional[str] = None): - str.__init__(uri) - self.key = key - self.ip = ip - self.port = port + # def __init__(self, uri: str, *, key: Optional[str] = None, ip: Optional[str] = None, port: Optional[str] = None): + # str.__init__(uri) + # self.key = key + # self.ip = ip + # self.port = port - @classmethod - def __get_validators__(cls): - yield str_validator - yield cls.validate + # @classmethod + # def __get_validators__(cls): + # yield str_validator + # yield cls.validate - @classmethod - def validate(cls, value: str) -> "LightningNodeUri": - try: - key, netloc = value.split("@") - ip, port = netloc.split(":") - except Exception: - raise ValueError + # @classmethod + # def validate(cls, value: str) -> "LightningNodeUri": + # try: + # key, netloc = value.split("@") + # ip, port = netloc.split(":") + # except Exception: + # raise ValueError - return cls(value, key=key, ip=ip, port=port) + # return cls(value, key=key, ip=ip, port=port) class Lnurl(ReprMixin, str): @@ -188,12 +175,13 @@ def __init__(self, lightning: str, *, url: Optional[Union[OnionUrl, ClearnetUrl, @classmethod def __get_url__(cls, bech32: str) -> Union[OnionUrl, ClearnetUrl, DebugUrl]: url: str = _lnurl_decode(bech32) - return parse_obj_as(Union[OnionUrl, ClearnetUrl, DebugUrl], url) # type: ignore + adapter = TypeAdapter(Union[OnionUrl, ClearnetUrl, DebugUrl]) + return adapter.validate_python(url) - @classmethod - def __get_validators__(cls): - yield str_validator - yield cls.validate + # @classmethod + # def __get_validators__(cls): + # yield str_validator + # yield cls.validate @classmethod def validate(cls, value: str) -> "Lnurl": @@ -201,7 +189,8 @@ def validate(cls, value: str) -> "Lnurl": @property def is_login(self) -> bool: - return "tag" in self.url.query_params and self.url.query_params["tag"] == "login" + params = {k: v for k, v in self.url.query_params()} + return params.get("tag") == "login" class LnurlPayMetadata(ReprMixin, str): @@ -209,7 +198,7 @@ class LnurlPayMetadata(ReprMixin, str): __slots__ = ("_list",) - def __new__(cls, json_str: str, **kwargs) -> "LnurlPayMetadata": + def __new__(cls, json_str: str, **_) -> "LnurlPayMetadata": return str.__new__(cls, json_str) def __init__(self, json_str: str, *, json_obj: Optional[List] = None): @@ -219,7 +208,8 @@ def __init__(self, json_str: str, *, json_obj: Optional[List] = None): @classmethod def __validate_metadata__(cls, json_str: str) -> List[Tuple[str, str]]: try: - parse_obj_as(Json[List[Tuple[str, str]]], json_str) + adapter = TypeAdapter(Json[List[Tuple[str, str]]]) + adapter.validate_python(json_str) data = [(str(item[0]), str(item[1])) for item in json.loads(json_str)] except ValidationError: raise InvalidLnurlPayMetadata @@ -233,10 +223,10 @@ def __validate_metadata__(cls, json_str: str) -> List[Tuple[str, str]]: return clean_data - @classmethod - def __get_validators__(cls): - yield str_validator - yield cls.validate + # @classmethod + # def __get_validators__(cls): + # yield str_validator + # yield cls.validate @classmethod def validate(cls, value: str) -> "LnurlPayMetadata": @@ -265,13 +255,8 @@ def list(self) -> List[Tuple[str, str]]: return self._list -class InitializationVector(ConstrainedStr): - min_length = 24 - max_length = 24 - - -class Max144Str(ConstrainedStr): - max_length = 144 +InitializationVector = Annotated[str, Field(max_length=24, min_length=24)] +Max144Str = Annotated[str, Field(max_length=144)] class MilliSatoshi(PositiveInt): diff --git a/poetry.lock b/poetry.lock index 723a2cf..fb6d296 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,16 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +[[package]] +name = "annotated-types" +version = "0.5.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.7" +files = [ + {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, + {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, +] + [[package]] name = "bech32" version = "1.2.0" @@ -474,55 +485,153 @@ virtualenv = ">=20.10.0" [[package]] name = "pydantic" -version = "1.10.12" -description = "Data validation and settings management using python type hints" +version = "2.1.1" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-2.1.1-py3-none-any.whl", hash = "sha256:43bdbf359d6304c57afda15c2b95797295b702948082d4c23851ce752f21da70"}, + {file = "pydantic-2.1.1.tar.gz", hash = "sha256:22d63db5ce4831afd16e7c58b3192d3faf8f79154980d9397d9867254310ba4b"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.4.0" +typing-extensions = ">=4.6.1" + +[package.extras] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.4.0" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.4.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:2ca4687dd996bde7f3c420def450797feeb20dcee2b9687023e3323c73fc14a2"}, + {file = "pydantic_core-2.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:782fced7d61469fd1231b184a80e4f2fa7ad54cd7173834651a453f96f29d673"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6213b471b68146af97b8551294e59e7392c2117e28ffad9c557c65087f4baee3"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63797499a219d8e81eb4e0c42222d0a4c8ec896f5c76751d4258af95de41fdf1"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_armv7l.whl", hash = "sha256:0455876d575a35defc4da7e0a199596d6c773e20d3d42fa1fc29f6aa640369ed"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:8c938c96294d983dcf419b54dba2d21056959c22911d41788efbf949a29ae30d"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_24_s390x.whl", hash = "sha256:878a5017d93e776c379af4e7b20f173c82594d94fa073059bcc546789ad50bf8"}, + {file = "pydantic_core-2.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:69159afc2f2dc43285725f16143bc5df3c853bc1cb7df6021fce7ef1c69e8171"}, + {file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:54df7df399b777c1fd144f541c95d351b3aa110535a6810a6a569905d106b6f3"}, + {file = "pydantic_core-2.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e412607ca89a0ced10758dfb8f9adcc365ce4c1c377e637c01989a75e9a9ec8a"}, + {file = "pydantic_core-2.4.0-cp310-none-win32.whl", hash = "sha256:853f103e2b9a58832fdd08a587a51de8b552ae90e1a5d167f316b7eabf8d7dde"}, + {file = "pydantic_core-2.4.0-cp310-none-win_amd64.whl", hash = "sha256:3ba2c9c94a9176f6321a879c8b864d7c5b12d34f549a4c216c72ce213d7d953c"}, + {file = "pydantic_core-2.4.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:a8b7acd04896e8f161e1500dc5f218017db05c1d322f054e89cbd089ce5d0071"}, + {file = "pydantic_core-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:16468bd074fa4567592d3255bf25528ed41e6b616d69bf07096bdb5b66f947d1"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cba5ad5eef02c86a1f3da00544cbc59a510d596b27566479a7cd4d91c6187a11"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7206e41e04b443016e930e01685bab7a308113c0b251b3f906942c8d4b48fcb"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_armv7l.whl", hash = "sha256:c1375025f0bfc9155286ebae8eecc65e33e494c90025cda69e247c3ccd2bab00"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_ppc64le.whl", hash = "sha256:3534118289e33130ed3f1cc487002e8d09b9f359be48b02e9cd3de58ce58fba9"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_24_s390x.whl", hash = "sha256:94d2b36a74623caab262bf95f0e365c2c058396082bd9d6a9e825657d0c1e7fa"}, + {file = "pydantic_core-2.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:af24ad4fbaa5e4a2000beae0c3b7fd1c78d7819ab90f9370a1cfd8998e3f8a3c"}, + {file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bf10963d8aed8bbe0165b41797c9463d4c5c8788ae6a77c68427569be6bead41"}, + {file = "pydantic_core-2.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68199ada7c310ddb8c76efbb606a0de656b40899388a7498954f423e03fc38be"}, + {file = "pydantic_core-2.4.0-cp311-none-win32.whl", hash = "sha256:6f855bcc96ed3dd56da7373cfcc9dcbabbc2073cac7f65c185772d08884790ce"}, + {file = "pydantic_core-2.4.0-cp311-none-win_amd64.whl", hash = "sha256:de39eb3bab93a99ddda1ac1b9aa331b944d8bcc4aa9141148f7fd8ee0299dafc"}, + {file = "pydantic_core-2.4.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:f773b39780323a0499b53ebd91a28ad11cde6705605d98d999dfa08624caf064"}, + {file = "pydantic_core-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a297c0d6c61963c5c3726840677b798ca5b7dfc71bc9c02b9a4af11d23236008"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:546064c55264156b973b5e65e5fafbe5e62390902ce3cf6b4005765505e8ff56"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36ba9e728588588f0196deaf6751b9222492331b5552f865a8ff120869d372e0"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_armv7l.whl", hash = "sha256:57a53a75010c635b3ad6499e7721eaa3b450e03f6862afe2dbef9c8f66e46ec8"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_ppc64le.whl", hash = "sha256:4b262bbc13022f2097c48a21adcc360a81d83dc1d854c11b94953cd46d7d3c07"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_24_s390x.whl", hash = "sha256:01947ad728f426fa07fcb26457ebf90ce29320259938414bc0edd1476e75addb"}, + {file = "pydantic_core-2.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b2799c2eaf182769889761d4fb4d78b82bc47dae833799fedbf69fc7de306faa"}, + {file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a08fd490ba36d1fbb2cd5dcdcfb9f3892deb93bd53456724389135712b5fc735"}, + {file = "pydantic_core-2.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1e8a7c62d15a5c4b307271e4252d76ebb981d6251c6ecea4daf203ef0179ea4f"}, + {file = "pydantic_core-2.4.0-cp312-none-win32.whl", hash = "sha256:9206c14a67c38de7b916e486ae280017cf394fa4b1aa95cfe88621a4e1d79725"}, + {file = "pydantic_core-2.4.0-cp312-none-win_amd64.whl", hash = "sha256:884235507549a6b2d3c4113fb1877ae263109e787d9e0eb25c35982ab28d0399"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:4cbe929efa77a806e8f1a97793f2dc3ea3475ae21a9ed0f37c21320fe93f6f50"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:9137289de8fe845c246a8c3482dd0cb40338846ba683756d8f489a4bd8fddcae"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d8e764b5646623e57575f624f8ebb8f7a9f7fd1fae682ef87869ca5fec8dcf"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fba0aff4c407d0274e43697e785bcac155ad962be57518d1c711f45e72da70f"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_armv7l.whl", hash = "sha256:30527d173e826f2f7651f91c821e337073df1555e3b5a0b7b1e2c39e26e50678"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:bd7d1dde70ff3e09e4bc7a1cbb91a7a538add291bfd5b3e70ef1e7b45192440f"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_24_s390x.whl", hash = "sha256:72f1216ca8cef7b8adacd4c4c6b89c3b0c4f97503197f5284c80f36d6e4edd30"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b013c7861a7c7bfcec48fd709513fea6f9f31727e7a0a93ca0dd12e056740717"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:478f5f6d7e32bd4a04d102160efb2d389432ecf095fe87c555c0a6fc4adfc1a4"}, + {file = "pydantic_core-2.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d9610b47b5fe4aacbbba6a9cb5f12cbe864eec99dbfed5710bd32ef5dd8a5d5b"}, + {file = "pydantic_core-2.4.0-cp37-none-win32.whl", hash = "sha256:ff246c0111076c8022f9ba325c294f2cb5983403506989253e04dbae565e019b"}, + {file = "pydantic_core-2.4.0-cp37-none-win_amd64.whl", hash = "sha256:d0c2b713464a8e263a243ae7980d81ce2de5ac59a9f798a282e44350b42dc516"}, + {file = "pydantic_core-2.4.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:12ef6838245569fd60a179fade81ca4b90ae2fa0ef355d616f519f7bb27582db"}, + {file = "pydantic_core-2.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:49db206eb8fdc4b4f30e6e3e410584146d813c151928f94ec0db06c4f2595538"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a507d7fa44688bbac76af6521e488b3da93de155b9cba6f2c9b7833ce243d59"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffe18407a4d000c568182ce5388bbbedeb099896904e43fc14eee76cfae6dec5"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_armv7l.whl", hash = "sha256:fa8e48001b39d54d97d7b380a0669fa99fc0feeb972e35a2d677ba59164a9a22"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:394f12a2671ff8c4dfa2e85be6c08be0651ad85bc1e6aa9c77c21671baaf28cd"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_24_s390x.whl", hash = "sha256:2f9ea0355f90db2a76af530245fa42f04d98f752a1236ed7c6809ec484560d5b"}, + {file = "pydantic_core-2.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:61d4e713f467abcdd59b47665d488bb898ad3dd47ce7446522a50e0cbd8e8279"}, + {file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:453862ab268f6326b01f067ed89cb3a527d34dc46f6f4eeec46a15bbc706d0da"}, + {file = "pydantic_core-2.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:56a85fa0dab1567bd0cac10f0c3837b03e8a0d939e6a8061a3a420acd97e9421"}, + {file = "pydantic_core-2.4.0-cp38-none-win32.whl", hash = "sha256:0d726108c1c0380b88b6dd4db559f0280e0ceda9e077f46ff90bc85cd4d03e77"}, + {file = "pydantic_core-2.4.0-cp38-none-win_amd64.whl", hash = "sha256:047580388644c473b934d27849f8ed8dbe45df0adb72104e78b543e13bf69762"}, + {file = "pydantic_core-2.4.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:867d3eea954bea807cabba83cfc939c889a18576d66d197c60025b15269d7cc0"}, + {file = "pydantic_core-2.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:664402ef0c238a7f8a46efb101789d5f2275600fb18114446efec83cfadb5b66"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64e8012ad60a5f0da09ed48725e6e923d1be25f2f091a640af6079f874663813"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac2b680de398f293b68183317432b3d67ab3faeba216aec18de0c395cb5e3060"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_armv7l.whl", hash = "sha256:8efc1be43b036c2b6bcfb1451df24ee0ddcf69c31351003daf2699ed93f5687b"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:d93aedbc4614cc21b9ab0d0c4ccd7143354c1f7cffbbe96ae5216ad21d1b21b5"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_24_s390x.whl", hash = "sha256:af788b64e13d52fc3600a68b16d31fa8d8573e3ff2fc9a38f8a60b8d94d1f012"}, + {file = "pydantic_core-2.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97c6349c81cee2e69ef59eba6e6c08c5936e6b01c2d50b9e4ac152217845ae09"}, + {file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cc086ddb6dc654a15deeed1d1f2bcb1cb924ebd70df9dca738af19f64229b06c"}, + {file = "pydantic_core-2.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e953353180bec330c3b830891d260b6f8e576e2d18db3c78d314e56bb2276066"}, + {file = "pydantic_core-2.4.0-cp39-none-win32.whl", hash = "sha256:6feb4b64d11d5420e517910d60a907d08d846cacaf4e029668725cd21d16743c"}, + {file = "pydantic_core-2.4.0-cp39-none-win_amd64.whl", hash = "sha256:153a61ac4030fa019b70b31fb7986461119230d3ba0ab661c757cfea652f4332"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3fcf529382b282a30b466bd7af05be28e22aa620e016135ac414f14e1ee6b9e1"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2edef05b63d82568b877002dc4cb5cc18f8929b59077120192df1e03e0c633f8"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da055a1b0bfa8041bb2ff586b2cb0353ed03944a3472186a02cc44a557a0e661"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:77dadc764cf7c5405e04866181c5bd94a447372a9763e473abb63d1dfe9b7387"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a4ea23b07f29487a7bef2a869f68c7ee0e05424d81375ce3d3de829314c6b5ec"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:382f0baa044d674ad59455a5eff83d7965572b745cc72df35c52c2ce8c731d37"}, + {file = "pydantic_core-2.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:08f89697625e453421401c7f661b9d1eb4c9e4c0a12fd256eeb55b06994ac6af"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:43a405ce520b45941df9ff55d0cd09762017756a7b413bbad3a6e8178e64a2c2"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584a7a818c84767af16ce8bda5d4f7fedb37d3d231fc89928a192f567e4ef685"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04922fea7b13cd480586fa106345fe06e43220b8327358873c22d8dfa7a711c7"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17156abac20a9feed10feec867fddd91a80819a485b0107fe61f09f2117fe5f3"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4e562cc63b04636cde361fd47569162f1daa94c759220ff202a8129902229114"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:90f3785146f701e053bb6b9e8f53acce2c919aca91df88bd4975be0cb926eb41"}, + {file = "pydantic_core-2.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e40b1e97edd3dc127aa53d8a5e539a3d0c227d71574d3f9ac1af02d58218a122"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:b27f3e67f6e031f6620655741b7d0d6bebea8b25d415924b3e8bfef2dd7bd841"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be86c2eb12fb0f846262ace9d8f032dc6978b8cb26a058920ecb723dbcb87d05"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4665f7ed345012a8d2eddf4203ef145f5f56a291d010382d235b94e91813f88a"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:79262be5a292d1df060f29b9a7cdd66934801f987a817632d7552534a172709a"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:5fd905a69ac74eaba5041e21a1e8b1a479dab2b41c93bdcc4c1cede3c12a8d86"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:2ad538b7e07343001934417cdc8584623b4d8823c5b8b258e75ec8d327cec969"}, + {file = "pydantic_core-2.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:dd2429f7635ad4857b5881503f9c310be7761dc681c467a9d27787b674d1250a"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:efff8b6761a1f6e45cebd1b7a6406eb2723d2d5710ff0d1b624fe11313693989"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32a1e0352558cd7ccc014ffe818c7d87b15ec6145875e2cc5fa4bb7351a1033d"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a027f41c5008571314861744d83aff75a34cf3a07022e0be32b214a5bc93f7f1"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1927f0e15d190f11f0b8344373731e28fd774c6d676d8a6cfadc95c77214a48b"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7aa82d483d5fb867d4fb10a138ffd57b0f1644e99f2f4f336e48790ada9ada5e"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b85778308bf945e9b33ac604e6793df9b07933108d20bdf53811bc7c2798a4af"}, + {file = "pydantic_core-2.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3ded19dcaefe2f6706d81e0db787b59095f4ad0fbadce1edffdf092294c8a23f"}, + {file = "pydantic_core-2.4.0.tar.gz", hash = "sha256:ec3473c9789cc00c7260d840c3db2c16dbfc816ca70ec87a00cddfa3e1a1cdd5"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pyright" +version = "1.1.323" +description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, - {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, - {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, - {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, - {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, - {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, - {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, - {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, - {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, - {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, - {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, - {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, - {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, - {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, - {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, - {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, - {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, - {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, - {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, - {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, - {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, - {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, - {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, + {file = "pyright-1.1.323-py3-none-any.whl", hash = "sha256:23ce9eca401fda311be273784ebf128850d43a17f9e87dc299ffcdc0ffe91f75"}, + {file = "pyright-1.1.323.tar.gz", hash = "sha256:f3029bfe96a3436a505464d28e3433fafe23ac5f86f52edab9a26cd66685825e"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +nodeenv = ">=1.6.0" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +all = ["twine (>=3.4.1)"] +dev = ["twine (>=3.4.1)"] [[package]] name = "pytest" @@ -763,4 +872,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a519afabd47fcb23e0d83ce22f1563d8ae90c546790fe949b4f9b26f31a52403" +content-hash = "5bcf58a3a82fdea38106940a0348f92dd26a765dfbe9ed60e56384fc80d38380" diff --git a/pyproject.toml b/pyproject.toml index ec0bfca..73402b7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ lnurl = "lnurl.cli:main" [tool.poetry.dependencies] python = "^3.9" requests = "^2.31.0" -pydantic = "^1" +pydantic = "^2.1.1" bech32 = "^1.2.0" [tool.poetry.group.dev.dependencies] @@ -27,6 +27,7 @@ types-requests = "^2.31.0.2" mypy = "^1.5.1" ruff = "^0.0.284" pre-commit = "^3.3.3" +pyright = "^1.1.323" [build-system] requires = ["poetry-core"] diff --git a/tests/test_core.py b/tests/test_core.py index 6d848bb..acd5467 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -10,7 +10,7 @@ LnurlPaySuccessAction, LnurlWithdrawResponse, ) -from lnurl.types import Lnurl, Url +from lnurl.types import ClearnetUrl, Lnurl class TestDecode: @@ -28,7 +28,7 @@ class TestDecode: ) def test_decode(self, bech32, url): decoded_url = decode(bech32) - assert isinstance(decoded_url, Url) + assert isinstance(decoded_url, ClearnetUrl) assert decoded_url == str(decoded_url) == url assert decoded_url.host == "service.io" diff --git a/tests/test_types.py b/tests/test_types.py index b33e8cd..fbd24ef 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -1,7 +1,7 @@ from typing import Union import pytest -from pydantic import ValidationError, parse_obj_as +from pydantic import TypeAdapter, ValidationError from lnurl.helpers import _lnurl_clean from lnurl.types import ( @@ -22,10 +22,20 @@ class TestUrl: ["service.io:443", "service.io:9000"], ) def test_parameters(self, hostport): - url = parse_obj_as(Union[DebugUrl, OnionUrl, ClearnetUrl], f"https://{hostport}/?q=3fc3645b439ce8e7&test=ok") + adapter = TypeAdapter(Union[DebugUrl, OnionUrl, ClearnetUrl]) + url = adapter.validate_python(f"https://{hostport}/?q=3fc3645b439ce8e7&test=ok") assert url.host == "service.io" - assert url.base == f"https://{hostport}/" - assert url.query_params == {"q": "3fc3645b439ce8e7", "test": "ok"} + # assert url.base == f"https://{hostport}/" + assert url.query_params() == [ + ( + "q", + "3fc3645b439ce8e7", + ), + ( + "test", + "ok", + ), + ] @pytest.mark.parametrize( "url", @@ -41,7 +51,8 @@ def test_parameters(self, hostport): ], ) def test_valid(self, url): - url = parse_obj_as(Union[OnionUrl, DebugUrl, ClearnetUrl], url) + adapter = TypeAdapter(Union[DebugUrl, OnionUrl, ClearnetUrl]) + url = adapter.validate_python(url) assert isinstance(url, (OnionUrl, DebugUrl, ClearnetUrl)) @pytest.mark.parametrize( @@ -57,7 +68,8 @@ def test_valid(self, url): ) def test_invalid_data(self, url): with pytest.raises(ValidationError): - parse_obj_as(Union[DebugUrl, OnionUrl, ClearnetUrl], url) + adapter = TypeAdapter(Union[DebugUrl, OnionUrl, ClearnetUrl]) + adapter.validate_python(url) @pytest.mark.parametrize( "url", @@ -69,7 +81,8 @@ def test_invalid_data(self, url): def test_strict_rfc3986(self, monkeypatch, url): monkeypatch.setenv("LNURL_STRICT_RFC3986", "1") with pytest.raises(ValidationError): - parse_obj_as(ClearnetUrl, url) + adapter = TypeAdapter(ClearnetUrl) + adapter.validate_python(url) class TestLightningInvoice: @@ -92,7 +105,8 @@ class TestLightningInvoice: ) def test_valid(self, bech32, hrp, prefix, amount, h): invoice = LightningInvoice(bech32) - assert invoice == parse_obj_as(LightningInvoice, bech32) + adapter = TypeAdapter(LightningInvoice) + assert invoice == adapter.validate_python(bech32) assert invoice.hrp == hrp assert invoice.prefix == prefix assert invoice.amount == amount @@ -101,7 +115,8 @@ def test_valid(self, bech32, hrp, prefix, amount, h): class TestLightningNode: def test_valid(self): - node = parse_obj_as(LightningNodeUri, "node_key@ip_address:port_number") + adapter = TypeAdapter(LightningNodeUri) + node = adapter.validate_python("node_key@ip_address:port_number") assert node.key == "node_key" assert node.ip == "ip_address" assert node.port == "port_number" @@ -109,7 +124,8 @@ def test_valid(self): @pytest.mark.parametrize("uri", ["https://service.io/node", "node_key@ip_address", "ip_address:port_number"]) def test_invalid_data(self, uri): with pytest.raises(ValidationError): - parse_obj_as(LightningNodeUri, uri) + adapter = TypeAdapter(LightningNodeUri) + adapter.validate_python(uri) class TestLnurl: @@ -134,10 +150,11 @@ class TestLnurl: ) def test_valid(self, lightning, url): lnurl = Lnurl(lightning) - assert lnurl == lnurl.bech32 == _lnurl_clean(lightning) == parse_obj_as(Lnurl, lightning) + adapter = TypeAdapter(Lnurl) + assert lnurl == lnurl.bech32 == _lnurl_clean(lightning) == adapter.validate_python(lightning) assert lnurl.bech32.hrp == "lnurl" assert lnurl.url == url - assert lnurl.url.base == "https://service.io:443/" + # assert lnurl.url.base == "https://service.io:443/" assert lnurl.url.query_params == {"q": "3fc3645b439ce8e7f2553a69e5267081d96dcd340693afabe04be7b0ccd178df"} assert lnurl.is_login is False @@ -151,7 +168,8 @@ def test_valid(self, lightning, url): ) def test_decode_nolnurl(self, bech32): with pytest.raises(ValidationError): - parse_obj_as(Lnurl, bech32) + adapter = TypeAdapter(Lnurl) + adapter.validate_python(bech32) class TestLnurlPayMetadata: @@ -164,7 +182,9 @@ class TestLnurlPayMetadata: ], ) def test_valid(self, metadata, image_type): - m = parse_obj_as(LnurlPayMetadata, metadata) + adapter = TypeAdapter(LnurlPayMetadata) + m = adapter.validate_python(metadata) + assert m.text == "main text" if m.images: @@ -184,4 +204,5 @@ def test_valid(self, metadata, image_type): ) def test_invalid_data(self, metadata): with pytest.raises(ValidationError): - parse_obj_as(LnurlPayMetadata, metadata) + adapter = TypeAdapter(LnurlPayMetadata) + adapter.validate_python(metadata)