From 06327fdc08a5def5687f290ff4f6aef9247f9ba7 Mon Sep 17 00:00:00 2001 From: "Edwin (Ed) Onuonga" Date: Wed, 27 Dec 2023 22:56:30 +0000 Subject: [PATCH] fix(deps): fix `click` & `pydantic` min. versions + fix `feud.typing` versions (#133) --- docs/source/sections/typing/pydantic.rst | 129 ++++++++------- .../sections/typing/pydantic_extra_types.rst | 37 +++-- feud/typing/pydantic.py | 150 ++++++++++-------- feud/typing/pydantic_extra_types.py | 76 ++++++--- pyproject.toml | 6 +- 5 files changed, 239 insertions(+), 159 deletions(-) diff --git a/docs/source/sections/typing/pydantic.rst b/docs/source/sections/typing/pydantic.rst index ec0952c..4cb4dfb 100644 --- a/docs/source/sections/typing/pydantic.rst +++ b/docs/source/sections/typing/pydantic.rst @@ -37,72 +37,76 @@ The following commonly used Pydantic types can be used as type hints for Feud co ---- +The version number indicates the minimum ``pydantic`` version required to use the type. + +If this version requirement is not met, the type is not imported by Feud. + String types ------------ -- :py:obj:`pydantic.types.ImportString` -- :py:obj:`pydantic.types.SecretStr` -- :py:obj:`pydantic.types.StrictStr` -- :py:obj:`pydantic.types.constr` +- :py:obj:`pydantic.types.ImportString` (``>= 2.0.3``) +- :py:obj:`pydantic.types.SecretStr` (``>= 2.0.3``) +- :py:obj:`pydantic.types.StrictStr` (``>= 2.0.3``) +- :py:obj:`pydantic.types.constr` (``>= 2.0.3``) Integer types ------------- -- :py:obj:`pydantic.types.NegativeInt` -- :py:obj:`pydantic.types.NonNegativeInt` -- :py:obj:`pydantic.types.NonPositiveInt` -- :py:obj:`pydantic.types.PositiveInt` -- :py:obj:`pydantic.types.StrictInt` -- :py:obj:`pydantic.types.conint` +- :py:obj:`pydantic.types.NegativeInt` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NonNegativeInt` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NonPositiveInt` (``>= 2.0.3``) +- :py:obj:`pydantic.types.PositiveInt` (``>= 2.0.3``) +- :py:obj:`pydantic.types.StrictInt` (``>= 2.0.3``) +- :py:obj:`pydantic.types.conint` (``>= 2.0.3``) Float types ----------- -- :py:obj:`pydantic.types.FiniteFloat` -- :py:obj:`pydantic.types.NegativeFloat` -- :py:obj:`pydantic.types.NonNegativeFloat` -- :py:obj:`pydantic.types.NonPositiveFloat` -- :py:obj:`pydantic.types.PositiveFloat` -- :py:obj:`pydantic.types.StrictFloat` -- :py:obj:`pydantic.types.confloat` +- :py:obj:`pydantic.types.FiniteFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NegativeFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NonNegativeFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NonPositiveFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.PositiveFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.StrictFloat` (``>= 2.0.3``) +- :py:obj:`pydantic.types.confloat` (``>= 2.0.3``) Sequence types -------------- -- :py:obj:`pydantic.types.confrozenset` -- :py:obj:`pydantic.types.conlist` -- :py:obj:`pydantic.types.conset` +- :py:obj:`pydantic.types.confrozenset` (``>= 2.0.3``) +- :py:obj:`pydantic.types.conlist` (``>= 2.0.3``) +- :py:obj:`pydantic.types.conset` (``>= 2.0.3``) Datetime types -------------- -- :py:obj:`pydantic.types.AwareDatetime` -- :py:obj:`pydantic.types.FutureDate` -- :py:obj:`pydantic.types.FutureDatetime` -- :py:obj:`pydantic.types.NaiveDatetime` -- :py:obj:`pydantic.types.PastDate` -- :py:obj:`pydantic.types.PastDatetime` -- :py:obj:`pydantic.types.condate` +- :py:obj:`pydantic.types.AwareDatetime` (``>= 2.0.3``) +- :py:obj:`pydantic.types.FutureDate` (``>= 2.0.3``) +- :py:obj:`pydantic.types.FutureDatetime` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NaiveDatetime` (``>= 2.0.3``) +- :py:obj:`pydantic.types.PastDate` (``>= 2.0.3``) +- :py:obj:`pydantic.types.PastDatetime` (``>= 2.0.3``) +- :py:obj:`pydantic.types.condate` (``>= 2.0.3``) Path types ---------- -- :py:obj:`pydantic.types.DirectoryPath` -- :py:obj:`pydantic.types.FilePath` -- :py:obj:`pydantic.types.NewPath` +- :py:obj:`pydantic.types.DirectoryPath` (``>= 2.0.3``) +- :py:obj:`pydantic.types.FilePath` (``>= 2.0.3``) +- :py:obj:`pydantic.types.NewPath` (``>= 2.0.3``) Decimal type ------------ -- :py:obj:`pydantic.types.condecimal` +- :py:obj:`pydantic.types.condecimal` (``>= 2.0.3``) URL types --------- -- :py:obj:`pydantic.networks.AnyHttpUrl` -- :py:obj:`pydantic.networks.AnyUrl` -- :py:obj:`pydantic.networks.FileUrl` -- :py:obj:`pydantic.networks.HttpUrl` +- :py:obj:`pydantic.networks.AnyHttpUrl` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.AnyUrl` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.FileUrl` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.HttpUrl` (``>= 2.0.3``) Email types ----------- @@ -116,61 +120,64 @@ Email types $ pip install feud[email] -- :py:obj:`pydantic.networks.EmailStr` -- :py:obj:`pydantic.networks.NameEmail` +- :py:obj:`pydantic.networks.EmailStr` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.NameEmail` (``>= 2.0.3``) Base-64 types ------------- -- :py:obj:`pydantic.types.Base64Bytes` -- :py:obj:`pydantic.types.Base64Str` +- :py:obj:`pydantic.types.Base64Bytes` (``>= 2.0.3``) +- :py:obj:`pydantic.types.Base64Str` (``>= 2.0.3``) +- :py:obj:`pydantic.types.Base64UrlBytes` (``>= 2.4.0``) +- :py:obj:`pydantic.types.Base64UrlStr` (``>= 2.4.0``) Byte types ---------- -- :py:obj:`pydantic.types.ByteSize` -- :py:obj:`pydantic.types.SecretBytes` -- :py:obj:`pydantic.types.StrictBytes` -- :py:obj:`pydantic.types.conbytes` +- :py:obj:`pydantic.types.ByteSize` (``>= 2.0.3``) +- :py:obj:`pydantic.types.SecretBytes` (``>= 2.0.3``) +- :py:obj:`pydantic.types.StrictBytes` (``>= 2.0.3``) +- :py:obj:`pydantic.types.conbytes` (``>= 2.0.3``) JSON type --------- -- :py:obj:`pydantic.types.Json` +- :py:obj:`pydantic.types.Json` (``>= 2.0.3``) +- :py:obj:`pydantic.types.JsonValue` (``>= 2.5.0``) IP address types ---------------- -- :py:obj:`pydantic.networks.IPvAnyAddress` -- :py:obj:`pydantic.networks.IPvAnyInterface` -- :py:obj:`pydantic.networks.IPvAnyNetwork` +- :py:obj:`pydantic.networks.IPvAnyAddress` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.IPvAnyInterface` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.IPvAnyNetwork` (``>= 2.0.3``) Database connection types ------------------------- -- :py:obj:`pydantic.networks.AmqpDsn` -- :py:obj:`pydantic.networks.CockroachDsn` -- :py:obj:`pydantic.networks.KafkaDsn` -- :py:obj:`pydantic.networks.MariaDBDsn` -- :py:obj:`pydantic.networks.MongoDsn` -- :py:obj:`pydantic.networks.MySQLDsn` -- :py:obj:`pydantic.networks.PostgresDsn` -- :py:obj:`pydantic.networks.RedisDsn` +- :py:obj:`pydantic.networks.AmqpDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.CockroachDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.KafkaDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.MariaDBDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.MongoDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.MySQLDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.PostgresDsn` (``>= 2.0.3``) +- :py:obj:`pydantic.networks.RedisDsn` (``>= 2.0.3``) UUID types ---------- -- :py:obj:`pydantic.types.UUID1` -- :py:obj:`pydantic.types.UUID3` -- :py:obj:`pydantic.types.UUID4` -- :py:obj:`pydantic.types.UUID5` +- :py:obj:`pydantic.types.UUID1` (``>= 2.0.3``) +- :py:obj:`pydantic.types.UUID3` (``>= 2.0.3``) +- :py:obj:`pydantic.types.UUID4` (``>= 2.0.3``) +- :py:obj:`pydantic.types.UUID5` (``>= 2.0.3``) Boolean type ------------ -- :py:obj:`pydantic.types.StrictBool` +- :py:obj:`pydantic.types.StrictBool` (``>= 2.0.3``) Other types ----------- -- :py:obj:`pydantic.functional_validators.SkipValidation` +- :py:obj:`pydantic.functional_validators.SkipValidation` (``>= 2.0.3``) diff --git a/docs/source/sections/typing/pydantic_extra_types.rst b/docs/source/sections/typing/pydantic_extra_types.rst index 0e01157..ae92d5e 100644 --- a/docs/source/sections/typing/pydantic_extra_types.rst +++ b/docs/source/sections/typing/pydantic_extra_types.rst @@ -37,44 +37,53 @@ The following types can be used as type hints for Feud commands. ---- +The version number indicates the minimum ``pydantic-extra-types`` version required to use the type. + +If this version requirement is not met, the type is not imported by Feud. + Color type ---------- -- :py:obj:`pydantic_extra_types.color.Color` +- :py:obj:`pydantic_extra_types.color.Color` (``>= 2.1.0``) Coordinate types ---------------- -- :py:obj:`pydantic_extra_types.coordinate.Coordinate` -- :py:obj:`pydantic_extra_types.coordinate.Latitude` -- :py:obj:`pydantic_extra_types.coordinate.Longitude` +- :py:obj:`pydantic_extra_types.coordinate.Coordinate` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.coordinate.Latitude` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.coordinate.Longitude` (``>= 2.1.0``) Country types ------------- -- :py:obj:`pydantic_extra_types.country.CountryAlpha2` -- :py:obj:`pydantic_extra_types.country.CountryAlpha3` -- :py:obj:`pydantic_extra_types.country.CountryNumericCode` -- :py:obj:`pydantic_extra_types.country.CountryOfficialName` -- :py:obj:`pydantic_extra_types.country.CountryShortName` +- :py:obj:`pydantic_extra_types.country.CountryAlpha2` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.country.CountryAlpha3` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.country.CountryNumericCode` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.country.CountryOfficialName` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.country.CountryShortName` (``>= 2.1.0``) Phone number type ----------------- -- :py:obj:`pydantic_extra_types.phone_numbers.PhoneNumber` +- :py:obj:`pydantic_extra_types.phone_numbers.PhoneNumber` (``>= 2.1.0``) Payment types ------------- -- :py:obj:`pydantic_extra_types.payment.PaymentCardBrand` -- :py:obj:`pydantic_extra_types.payment.PaymentCardNumber` +- :py:obj:`pydantic_extra_types.payment.PaymentCardBrand` (``>= 2.1.0``) +- :py:obj:`pydantic_extra_types.payment.PaymentCardNumber` (``>= 2.1.0``) MAC address type ---------------- -- :py:obj:`pydantic_extra_types.mac_address.MacAddress` +- :py:obj:`pydantic_extra_types.mac_address.MacAddress` (``>= 2.1.0``) Routing number type ------------------- -- :py:obj:`pydantic_extra_types.routing_number.ABARoutingNumber` +- :py:obj:`pydantic_extra_types.routing_number.ABARoutingNumber` (``>= 2.1.0``) + +ULID type +--------- + +- :py:obj:`pydantic_extra_types.ulid.ULID` (``>= 2.2.0``) diff --git a/feud/typing/pydantic.py b/feud/typing/pydantic.py index fc9a04d..ec78e38 100644 --- a/feud/typing/pydantic.py +++ b/feud/typing/pydantic.py @@ -5,66 +5,92 @@ """Officially supported types from the ``pydantic`` package.""" -from pydantic import ( - UUID1, - UUID3, - UUID4, - UUID5, - AmqpDsn, - AnyHttpUrl, - AnyUrl, - AwareDatetime, - Base64Bytes, - Base64Str, - ByteSize, - CockroachDsn, - DirectoryPath, - EmailStr, - FilePath, - FileUrl, - FiniteFloat, - FutureDate, - FutureDatetime, - HttpUrl, - ImportString, - IPvAnyAddress, - IPvAnyInterface, - IPvAnyNetwork, - Json, - KafkaDsn, - MariaDBDsn, - MongoDsn, - MySQLDsn, - NaiveDatetime, - NameEmail, - NegativeFloat, - NegativeInt, - NewPath, - NonNegativeFloat, - NonNegativeInt, - NonPositiveFloat, - NonPositiveInt, - PastDate, - PastDatetime, - PositiveFloat, - PositiveInt, - PostgresDsn, - RedisDsn, - SecretBytes, - SecretStr, - SkipValidation, - StrictBool, - StrictBytes, - StrictFloat, - StrictInt, - StrictStr, - conbytes, - condate, - condecimal, - confloat, - confrozenset, - conint, - conlist, - conset, - constr, +from __future__ import annotations + +__all__ = [] + +import packaging.version +import pydantic + +version: packaging.version.Version = packaging.version.parse( + pydantic.__version__, ) + +if version >= packaging.version.parse("2.0.3"): + __all__.extend( + [ + "UUID1", + "UUID3", + "UUID4", + "UUID5", + "AmqpDsn", + "AnyHttpUrl", + "AnyUrl", + "AwareDatetime", + "Base64Bytes", + "Base64Str", + "ByteSize", + "CockroachDsn", + "DirectoryPath", + "EmailStr", + "FilePath", + "FileUrl", + "FiniteFloat", + "FutureDate", + "FutureDatetime", + "HttpUrl", + "ImportString", + "IPvAnyAddress", + "IPvAnyInterface", + "IPvAnyNetwork", + "Json", + "KafkaDsn", + "MariaDBDsn", + "MongoDsn", + "MySQLDsn", + "NaiveDatetime", + "NameEmail", + "NegativeFloat", + "NegativeInt", + "NewPath", + "NonNegativeFloat", + "NonNegativeInt", + "NonPositiveFloat", + "NonPositiveInt", + "PastDate", + "PastDatetime", + "PositiveFloat", + "PositiveInt", + "PostgresDsn", + "RedisDsn", + "SecretBytes", + "SecretStr", + "SkipValidation", + "StrictBool", + "StrictBytes", + "StrictFloat", + "StrictInt", + "StrictStr", + "conbytes", + "condate", + "condecimal", + "confloat", + "confrozenset", + "conint", + "conlist", + "conset", + "constr", + ] + ) + +if version >= packaging.version.parse("2.4.0"): + types: list[str] = ["Base64UrlBytes", "Base64UrlStr"] + + __all__.extend(types) + +if version >= packaging.version.parse("2.5.0"): + types: list[str] = ["JsonValue"] + + __all__.extend(types) + +globals().update({attr: getattr(pydantic, attr) for attr in __all__}) diff --git a/feud/typing/pydantic_extra_types.py b/feud/typing/pydantic_extra_types.py index 3b5ee43..1093984 100644 --- a/feud/typing/pydantic_extra_types.py +++ b/feud/typing/pydantic_extra_types.py @@ -5,26 +5,64 @@ """Officially supported types from the ``pydantic-extra-types`` package.""" +from __future__ import annotations + +__all__ = [] + +from operator import attrgetter + +import packaging.version + + +def split(string: str) -> str: + return string.split(".")[-1] + + try: - from pydantic_extra_types.color import Color - from pydantic_extra_types.coordinate import ( - Coordinate, - Latitude, - Longitude, - ) - from pydantic_extra_types.country import ( - CountryAlpha2, - CountryAlpha3, - CountryNumericCode, - CountryOfficialName, - CountryShortName, - ) - from pydantic_extra_types.mac_address import MacAddress - from pydantic_extra_types.payment import ( - PaymentCardBrand, - PaymentCardNumber, + import pydantic_extra_types + + version: packaging.version.Version = packaging.version.parse( + pydantic_extra_types.__version__, ) - from pydantic_extra_types.phone_numbers import PhoneNumber - from pydantic_extra_types.routing_number import ABARoutingNumber + + if version >= packaging.version.parse("2.1.0"): + import pydantic_extra_types.color + import pydantic_extra_types.coordinate + import pydantic_extra_types.country + import pydantic_extra_types.mac_address + import pydantic_extra_types.payment + import pydantic_extra_types.phone_numbers + import pydantic_extra_types.routing_number + + types: list[str] = [ + "color.Color", + "coordinate.Coordinate", + "coordinate.Latitude", + "coordinate.Longitude", + "country.CountryAlpha2", + "country.CountryAlpha3", + "country.CountryNumericCode", + "country.CountryOfficialName", + "country.CountryShortName", + "mac_address.MacAddress", + "payment.PaymentCardBrand", + "payment.PaymentCardNumber", + "phone_numbers.PhoneNumber", + "routing_number.ABARoutingNumber", + ] + + globals().update( + { + split(attr): attrgetter(attr)(pydantic_extra_types) + for attr in types + } + ) + + __all__.extend(map(split, types)) + + if version >= packaging.version.parse("2.2.0"): + from pydantic_extra_types.ulid import ULID + + __all__.extend(["ULID"]) except ImportError: pass diff --git a/pyproject.toml b/pyproject.toml index 2123de2..9a0fd26 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,10 +61,10 @@ build-backend = 'poetry.core.masonry.api' [tool.poetry.dependencies] python = "^3.11" -pydantic = "^2.0.0" -click = "^8.1.7" +pydantic = "^2.0.3" +click = "^8.1.0" docstring-parser = "^0.15" -Pydantic = { version = "^2.0.0", optional = true, extras = ["email"] } +Pydantic = { version = "^2.0.3", optional = true, extras = ["email"] } rich-click = { version = "^1.6.1", optional = true } pydantic-extra-types = { version = "^2.1.0", optional = true, extras = ["all"] }