From d696b379f3b1e7924da9724e82a1098a0c9f4c89 Mon Sep 17 00:00:00 2001 From: xncbf Date: Mon, 22 Jan 2024 16:22:46 +0900 Subject: [PATCH] fix: mypy --- poetry.lock | 244 +++++++++++-------------------------- pyproject.toml | 30 +++-- rcs_pydantic/main.py | 26 ++-- rcs_pydantic/scheme.py | 41 +++---- tests/test_rcs_pydantic.py | 34 ++---- 5 files changed, 131 insertions(+), 244 deletions(-) diff --git a/poetry.lock b/poetry.lock index fea4662..f8af70e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -11,73 +11,49 @@ typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "anyio" -version = "3.6.1" +version = "4.2.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8" [package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} idna = ">=2.8" sniffio = ">=1.1" +typing-extensions = {version = ">=4.1", markers = "python_version < \"3.11\""} [package.extras] -doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] - -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "attrs" -version = "22.1.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.5" - -[package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] -docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] +doc = ["packaging", "Sphinx (>=7)", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.23)"] [[package]] name = "black" -version = "21.11b1" +version = "23.12.1" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.8" [package.dependencies] -click = ">=7.1.2" +click = ">=8.0.0" mypy-extensions = ">=0.4.3" -pathspec = ">=0.9.0,<1" +packaging = ">=22.0" +pathspec = ">=0.9.0" platformdirs = ">=2" -regex = ">=2021.4.4" -tomli = ">=0.2.6,<2.0.0" -typing-extensions = [ - {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}, - {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""}, -] +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4,!=3.9.0)", "aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -python2 = ["typed-ast (>=1.4.3)"] uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "click" -version = "8.1.3" +version = "8.1.7" description = "Composable command line interface toolkit" category = "dev" optional = false @@ -88,11 +64,11 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "coverage" @@ -108,19 +84,30 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1 [package.extras] toml = ["tomli"] +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "factory-boy" -version = "3.2.1" +version = "3.3.0" description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] Faker = ">=0.7.0" [package.extras] -dev = ["coverage", "django", "flake8", "isort", "pillow", "sqlalchemy", "mongoengine", "wheel (>=0.32.0)", "tox", "zest.releaser"] +dev = ["coverage", "django", "flake8", "isort", "pillow", "sqlalchemy", "sqlalchemy-utils", "mongoengine", "wheel (>=0.32.0)", "tox", "zest.releaser"] doc = ["sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"] [[package]] @@ -151,19 +138,6 @@ typing-extensions = ">=4.8.0" [package.extras] all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] -[[package]] -name = "flake8" -version = "4.0.1" -description = "the modular source code checker: pep8 pyflakes and co" -category = "dev" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.8.0,<2.9.0" -pyflakes = ">=2.4.0,<2.5.0" - [[package]] name = "h11" version = "0.14.0" @@ -174,7 +148,7 @@ python-versions = ">=3.7" [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" category = "dev" optional = false @@ -182,118 +156,90 @@ python-versions = ">=3.5" [[package]] name = "iniconfig" -version = "1.1.1" -description = "iniconfig: brain-dead simple config-ini parsing" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" [[package]] name = "isort" -version = "5.10.1" +version = "5.13.2" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.6.1,<4.0" +python-versions = ">=3.8.0" [package.extras] -pipfile_deprecated_finder = ["pipreqs", "requirementslib"] -requirements_deprecated_finder = ["pipreqs", "pip-api"] -colors = ["colorama (>=0.4.3,<0.5.0)"] -plugins = ["setuptools"] - -[[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" -category = "dev" -optional = false -python-versions = "*" +colors = ["colorama (>=0.4.6)"] [[package]] name = "mypy" -version = "0.931" +version = "1.8.0" description = "Optional static typing for Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [package.dependencies] -mypy-extensions = ">=0.4.3" -tomli = ">=1.1.0" -typing-extensions = ">=3.10" +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" [package.extras] dmypy = ["psutil (>=4.0)"] -python2 = ["typed-ast (>=1.4.0,<2)"] +install-types = ["pip"] +mypyc = ["setuptools (>=50)"] +reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.5" [[package]] name = "packaging" -version = "21.3" +version = "23.2" description = "Core utilities for Python packages" category = "dev" optional = false -python-versions = ">=3.6" - -[package.dependencies] -pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +python-versions = ">=3.7" [[package]] name = "pathspec" -version = "0.10.1" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "4.1.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] -test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.24)", "sphinx (>=7.1.1)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest (>=7.4)"] [[package]] name = "pluggy" -version = "1.0.0" +version = "1.3.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - -[[package]] -name = "pycodestyle" -version = "2.8.0" -description = "Python style guide checker" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - [[package]] name = "pydantic" version = "2.5.3" @@ -321,53 +267,32 @@ python-versions = ">=3.7" [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" -[[package]] -name = "pyflakes" -version = "2.4.0" -description = "passive checker of Python programs" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[[package]] -name = "pyparsing" -version = "3.0.9" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" -optional = false -python-versions = ">=3.6.8" - -[package.extras] -diagrams = ["railroad-diagrams", "jinja2"] - [[package]] name = "pytest" -version = "6.2.5" +version = "7.4.4" description = "pytest: simple powerful testing with Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "3.0.0" +version = "4.1.0" description = "Pytest plugin for measuring coverage." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] coverage = {version = ">=5.2.1", extras = ["toml"]} @@ -387,14 +312,6 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" [package.dependencies] six = ">=1.5" -[[package]] -name = "regex" -version = "2022.9.13" -description = "Alternative regular expression module, to replace re." -category = "dev" -optional = false -python-versions = ">=3.6" - [[package]] name = "ruff" version = "0.1.14" @@ -442,21 +359,13 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -category = "dev" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" - [[package]] name = "tomli" -version = "1.2.3" +version = "2.0.1" description = "A lil' TOML parser" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "typing-extensions" @@ -484,48 +393,39 @@ standard = ["colorama (>=0.4)", "httptools (>=0.4.0)", "python-dotenv (>=0.13)", [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "7ffb4f59c30411a27f163bf2c05ef284bd4d329895a36964452199eb57f16166" +content-hash = "c9b5ce64682863a8122ada94810f2908ac2f5405394896a38719d0abb43b4e9e" [metadata.files] annotated-types = [] anyio = [] -atomicwrites = [] -attrs = [] black = [] click = [] colorama = [] coverage = [] +exceptiongroup = [] factory-boy = [] faker = [] fastapi = [] -flake8 = [] h11 = [] idna = [] iniconfig = [] isort = [] -mccabe = [] mypy = [] mypy-extensions = [] packaging = [] pathspec = [] platformdirs = [] pluggy = [] -py = [] -pycodestyle = [] pydantic = [] pydantic-core = [] -pyflakes = [] -pyparsing = [] pytest = [] pytest-cov = [] python-dateutil = [] -regex = [] ruff = [] six = [] sniffio = [] starlette = [] text-unidecode = [] -toml = [] tomli = [] typing-extensions = [] uvicorn = [] diff --git a/pyproject.toml b/pyproject.toml index b5abd1a..ae962ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "rcs-pydantic" -version = "1.0.0" +version = "2.0.0" description = "" authors = ["xncbf "] keywords = ["pydantic", "rcs", "fastapi"] @@ -14,12 +14,11 @@ python = "^3.8" pydantic = "^2.0.0" [tool.poetry.dev-dependencies] -pytest-cov = "^3.0.0" -pytest = "^6.2.5" -black = "21.11b1" -flake8 = "^4.0.1" -mypy = "^0.931" -isort = "^5.10.1" +pytest-cov = "*" +pytest = "*" +black = "*" +mypy = "*" +isort = "*" Faker = "^11.3.0" factory-boy = "^3.2.1" fastapi = "^0.109.0" @@ -37,9 +36,24 @@ extend-exclude = ''' ''' [tool.mypy] -python_version = '3.8' +plugins = [ + "pydantic.mypy" +] +python_version = '3.10' ignore_missing_imports = 'True' +follow_imports = "silent" +warn_redundant_casts = true +warn_unused_ignores = true +check_untyped_defs = true +no_implicit_reexport = true + + +[tool.pydantic-mypy] +init_forbid_extra = true +init_typed = true +warn_required_dynamic_aliases = true + [tool.isort] profile = "black" line_length = 120 diff --git a/rcs_pydantic/main.py b/rcs_pydantic/main.py index 8bd33d5..a7fe37d 100644 --- a/rcs_pydantic/main.py +++ b/rcs_pydantic/main.py @@ -77,17 +77,21 @@ def make_common_info(self, message_info: scheme.MessageInfo) -> dict: else: msg_service_type = enums.MessageServiceTypeEnum.RCS - common = { - "msgId": str(uuid.uuid4()), - "userContact": message_info.userContact, - "scheduleType": 0, - "msgServiceType": msg_service_type, - } - if self.message_group_id: - common["msgGroupId"] = self.message_group_id - - return scheme.CommonInfo(**common).dict(exclude_unset=True) + return scheme.CommonInfo( + msgId=str(uuid.uuid4()), + userContact=str(message_info.userContact), + scheduleType=enums.ScheduleTypeEnum.IMMEDIATE, + msgServiceType=msg_service_type, + msgGroupId=self.message_group_id, + ).model_dump(exclude_unset=True) + else: + return scheme.CommonInfo( + msgId=str(uuid.uuid4()), + userContact=str(message_info.userContact), + scheduleType=enums.ScheduleTypeEnum.IMMEDIATE, + msgServiceType=msg_service_type, + ).model_dump(exclude_unset=True) def make_rcs_info(self, message_info: scheme.MessageInfo) -> dict: rcs_info = scheme.RcsInfo( @@ -117,7 +121,7 @@ def make_rcs_info(self, message_info: scheme.MessageInfo) -> dict: rcs_info.chipList = self.chips if message_info.replyId: rcs_info.replyId = message_info.replyId - return rcs_info.dict(exclude_unset=True) + return rcs_info.model_dump(exclude_unset=True) def send(self): self.send_info diff --git a/rcs_pydantic/scheme.py b/rcs_pydantic/scheme.py index 86cc0c8..4b80713 100644 --- a/rcs_pydantic/scheme.py +++ b/rcs_pydantic/scheme.py @@ -1,24 +1,11 @@ from typing import Dict, List, Optional, Union from pydantic import BaseModel, Field, validator +from typing_extensions import Never from . import enums -class EmptyDict(BaseModel): - @classmethod - def __get_validators__(cls): - yield cls.validate - - @classmethod - def validate(cls, v): - if not isinstance(v, dict): - raise TypeError("dict required") - if len(v.keys()) > 0: - raise ValueError("dict must be empty") - return {} - - class RcsSMSBody(BaseModel): title: Optional[str] = Field(max_length=30) description: str = Field(max_length=100) @@ -272,13 +259,13 @@ class CommonInfo(BaseModel): msgId: str = Field(max_length=40) userContact: str = Field(max_length=40) scheduleType: Optional[enums.ScheduleTypeEnum] - msgGroupId: Optional[str] = Field(max_length=20) + msgGroupId: Optional[str] = Field(max_length=20, default=None) msgServiceType: enums.MessageServiceTypeEnum class RcsInfo(BaseModel): chatbotId: str = Field(max_length=40) - agencyId: Optional[str] = Field(max_length=20) + agencyId: Optional[str] = Field(max_length=20, default=None) """ # agencyId 대행사 ID @@ -303,7 +290,7 @@ class RcsInfo(BaseModel): messagebaseId: Union[enums.MessageEnum, enums.RCSMessageEnum, str] serviceType: enums.ServiceTypeEnum - expiryOption: Optional[enums.ExpiryOptionEnum] + expiryOption: Optional[enums.ExpiryOptionEnum] = None """ # expiryOption 메시지 처리 옵션 enum: [1, 2] @@ -316,7 +303,7 @@ class RcsInfo(BaseModel): """ header: enums.HeaderEnum - footer: Optional[str] = Field(max_length=20, regex=r"^[\d-]*$") + footer: Optional[str] = Field(max_length=20, pattern=r"^[\d-]*$", default=None) """ # footer 수신거부 전화번호 (숫자, - 만 가능, Max: 20 자리) @@ -332,7 +319,7 @@ def footer_validator(cls, v, values, **kwargs): raise ValueError("If header is 1 then footer should be provided.") return v - cdrId: Optional[str] + cdrId: Optional[str] = None """ # cdrId 청약 ID 기록시 기록한 ID로 과금 처리 된다. @@ -383,7 +370,7 @@ def footer_validator(cls, v, values, **kwargs): - "media" :"maapfile://{fileId}" """ - buttons: Optional[List[Union[ButtonInfo, EmptyDict]]] + buttons: Optional[List[Union[ButtonInfo, Dict[Never, Never]]]] = None """ # buttons GSMA RCC.07의3.6.10.4의 ‘suggestions’ 규격에 준하여 버튼을 구성 @@ -397,7 +384,7 @@ def footer_validator(cls, v, values, **kwargs): 버튼의 변수부를 등록 하여 사용하며, 해당 필드 허용하지 않음. """ - chipList: Optional[List[SuggestionInfo]] + chipList: Optional[List[SuggestionInfo]] = None """ # chipList GSMA RCC.07의3.6.10.4의 ‘suggestion’ 규격에 따라 chiplist를 구성(RCC.07의 기준 버전 확인 필요) @@ -405,7 +392,7 @@ def footer_validator(cls, v, values, **kwargs): * Chiplist는 최대 11개까지 사용 가능하다 """ - replyId: Optional[str] = Field(max_length=40) + replyId: Optional[str] = Field(max_length=40, default=None) """ # replyId 양기업의 양방향 momsg를 수신할 때 포함된 replyID를 그대로 넣어서 전송한다 @@ -502,11 +489,11 @@ class StatusInfo(BaseModel): status: enums.MessageStatusEnum serviceType: Union[enums.ServiceTypeEnum, enums.LegacyServiceTypeEnum, None] mnoInfo: Optional[enums.MnoInfoEnum] - sentTime: Optional[str] = Field(regex=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") + sentTime: Optional[str] = Field(pattern=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") reason: Optional[ReasonInfo] error: Optional[ErrorInfo] legacyError: Optional[LegacyErrorInfo] - timestamp: str = Field(regex=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") + timestamp: str = Field(pattern=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") autoReplyMsgId: Optional[str] = Field(max_length=40) postbackId: Optional[str] = Field(max_length=40) chatbotId: Optional[str] = Field(max_length=40) @@ -607,13 +594,13 @@ def check_message_body(cls, v, values, **kwargs): userContact: str = Field(max_length=40) chatbotId: str = Field(max_length=40) - timestamp: str = Field(regex=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") + timestamp: str = Field(pattern=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") class SendInfo(BaseModel): common: CommonInfo rcs: RcsInfo - legacy: Optional[LegacyInfo] + legacy: Optional[LegacyInfo] = None class TokenInfo(BaseModel): @@ -638,5 +625,5 @@ class FileInfo(BaseModel): mimeType: str status: enums.FileStatusEnum size: Optional[int] - expiryDate: str = Field(regex=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") + expiryDate: str = Field(pattern=r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}\+\d{2}$") url: str diff --git a/tests/test_rcs_pydantic.py b/tests/test_rcs_pydantic.py index 9cba2d5..fc562c6 100644 --- a/tests/test_rcs_pydantic.py +++ b/tests/test_rcs_pydantic.py @@ -1,12 +1,10 @@ import pytest from faker import Faker -from pydantic import BaseModel from rcs_pydantic import enums from rcs_pydantic.errors import ErrorCodeEnum, KTErrorCodeEnum, MaaPErrorCodeEnum, RcsBizCenterErrorCodeEnum from rcs_pydantic.exceptions import MessageException from rcs_pydantic.main import RcsMessage -from rcs_pydantic.scheme import EmptyDict from . import factory @@ -21,8 +19,8 @@ def test_rcs_message(): agency_id="abc", agency_key="abc", brand_key="abc", - expiry_option=2, - header="1", + expiry_option=enums.ExpiryOptionEnum.AFTER_SETTING_TIMES, + header=enums.HeaderEnum.ADVERTISE, footer="010-0000-0000", cdr_id="abc", copy_allowed=True, @@ -39,8 +37,8 @@ def test_rcs_chat_message(): agency_id="abc", agency_key="abc", brand_key="abc", - expiry_option=2, - header="1", + expiry_option=enums.ExpiryOptionEnum.AFTER_SETTING_TIMES, + header=enums.HeaderEnum.ADVERTISE, footer="010-0000-0000", cdr_id="abc", copy_allowed=True, @@ -58,8 +56,8 @@ def test_rcs_message_with_empty_button(): agency_id="abc", agency_key="abc", brand_key="abc", - expiry_option=2, - header="1", + expiry_option=enums.ExpiryOptionEnum.AFTER_SETTING_TIMES, + header=enums.HeaderEnum.ADVERTISE, footer="010-0000-0000", cdr_id="abc", copy_allowed=True, @@ -104,22 +102,6 @@ def test_unknown_error_code_message_exception(): raise MessageException(123) -def test_empty_dict(): - class C(BaseModel): - item: EmptyDict - - C(item={}) - - with pytest.raises(ValueError): - C(item=None) - - with pytest.raises(ValueError): - C(item=[]) - - with pytest.raises(ValueError): - C(item={"a": 1}) - - def test_rcs_legacy_message(): rcs_message = RcsMessage( factory.MessageInfoFactory(), @@ -128,8 +110,8 @@ def test_rcs_legacy_message(): agency_id="abc", agency_key="abc", brand_key="abc", - expiry_option=2, - header="1", + expiry_option=enums.ExpiryOptionEnum.AFTER_SETTING_TIMES, + header=enums.HeaderEnum.ADVERTISE, footer="010-0000-0000", cdr_id="abc", copy_allowed=True,