Use dateutil parser (#213)
Switch to using `isoparse` from `dateutil.parser` instead of `datetime.fromisoformat` for more robust parsing of dates in from_dict.
This commit is contained in:
		
							
								
								
									
										36
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										36
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							| @@ -559,6 +559,17 @@ pytest = ">=5.0" | |||||||
| [package.extras] | [package.extras] | ||||||
| dev = ["pre-commit", "tox", "pytest-asyncio"] | dev = ["pre-commit", "tox", "pytest-asyncio"] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "python-dateutil" | ||||||
|  | version = "2.8.1" | ||||||
|  | description = "Extensions to the standard Python datetime module" | ||||||
|  | category = "main" | ||||||
|  | optional = false | ||||||
|  | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" | ||||||
|  |  | ||||||
|  | [package.dependencies] | ||||||
|  | six = ">=1.5" | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "pytz" | name = "pytz" | ||||||
| version = "2020.5" | version = "2020.5" | ||||||
| @@ -831,7 +842,7 @@ compiler = ["black", "jinja2", "protobuf"] | |||||||
| [metadata] | [metadata] | ||||||
| lock-version = "1.1" | lock-version = "1.1" | ||||||
| python-versions = "^3.6" | python-versions = "^3.6" | ||||||
| content-hash = "a8e4b87ff691fd815c51637f7fd24606c9ccdfbb7d9466a01c844fdfc58922c0" | content-hash = "5b967c5bfc330b1fa82efdebd8ce61c9d947ebe39c66ee1cd060f6aad45acba1" | ||||||
|  |  | ||||||
| [metadata.files] | [metadata.files] | ||||||
| alabaster = [ | alabaster = [ | ||||||
| @@ -1156,20 +1167,39 @@ markupsafe = [ | |||||||
|     {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, |     {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, |     {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, |     {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, |     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, |     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, |     {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, |     {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, |     {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, |     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, |     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, |     {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, |     {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, |     {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, |     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, |     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, |     {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, | ||||||
|     {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, |     {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"}, | ||||||
|  |     {file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"}, | ||||||
|     {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, |     {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, | ||||||
| ] | ] | ||||||
| more-itertools = [ | more-itertools = [ | ||||||
| @@ -1302,6 +1332,10 @@ pytest-mock = [ | |||||||
|     {file = "pytest-mock-3.5.1.tar.gz", hash = "sha256:a1e2aba6af9560d313c642dae7e00a2a12b022b80301d9d7fc8ec6858e1dd9fc"}, |     {file = "pytest-mock-3.5.1.tar.gz", hash = "sha256:a1e2aba6af9560d313c642dae7e00a2a12b022b80301d9d7fc8ec6858e1dd9fc"}, | ||||||
|     {file = "pytest_mock-3.5.1-py3-none-any.whl", hash = "sha256:379b391cfad22422ea2e252bdfc008edd08509029bcde3c25b2c0bd741e0424e"}, |     {file = "pytest_mock-3.5.1-py3-none-any.whl", hash = "sha256:379b391cfad22422ea2e252bdfc008edd08509029bcde3c25b2c0bd741e0424e"}, | ||||||
| ] | ] | ||||||
|  | python-dateutil = [ | ||||||
|  |     {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, | ||||||
|  |     {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, | ||||||
|  | ] | ||||||
| pytz = [ | pytz = [ | ||||||
|     {file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"}, |     {file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"}, | ||||||
|     {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"}, |     {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"}, | ||||||
|   | |||||||
| @@ -13,12 +13,12 @@ packages = [ | |||||||
|  |  | ||||||
| [tool.poetry.dependencies] | [tool.poetry.dependencies] | ||||||
| python = "^3.6" | python = "^3.6" | ||||||
| backports-datetime-fromisoformat = { version = "^1.0.0", python = "<3.7" } |  | ||||||
| black = { version = ">=19.3b0", optional = true } | black = { version = ">=19.3b0", optional = true } | ||||||
| dataclasses = { version = "^0.7", python = ">=3.6, <3.7" } | dataclasses = { version = "^0.7", python = ">=3.6, <3.7" } | ||||||
| grpclib = "^0.4.1" | grpclib = "^0.4.1" | ||||||
| jinja2 = { version = "^2.11.2", optional = true } | jinja2 = { version = "^2.11.2", optional = true } | ||||||
| protobuf = { version = "^3.12.2", optional = true } | protobuf = { version = "^3.12.2", optional = true } | ||||||
|  | python-dateutil = "^2.8" | ||||||
|  |  | ||||||
| [tool.poetry.dev-dependencies] | [tool.poetry.dev-dependencies] | ||||||
| black = "^20.8b1" | black = "^20.8b1" | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import typing | |||||||
| from abc import ABC | from abc import ABC | ||||||
| from base64 import b64decode, b64encode | from base64 import b64decode, b64encode | ||||||
| from datetime import datetime, timedelta, timezone | from datetime import datetime, timedelta, timezone | ||||||
|  | from dateutil.parser import isoparse | ||||||
| from typing import ( | from typing import ( | ||||||
|     Any, |     Any, | ||||||
|     Callable, |     Callable, | ||||||
| @@ -26,12 +27,6 @@ from ._types import T | |||||||
| from .casing import camel_case, safe_snake_case, snake_case | from .casing import camel_case, safe_snake_case, snake_case | ||||||
| from .grpc.grpclib_client import ServiceStub | from .grpc.grpclib_client import ServiceStub | ||||||
|  |  | ||||||
| if sys.version_info[:2] < (3, 7): |  | ||||||
|     # Apply backport of datetime.fromisoformat from 3.7 |  | ||||||
|     from backports.datetime_fromisoformat import MonkeyPatch |  | ||||||
|  |  | ||||||
|     MonkeyPatch.patch_fromisoformat() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| # Proto 3 data types | # Proto 3 data types | ||||||
| TYPE_ENUM = "enum" | TYPE_ENUM = "enum" | ||||||
| @@ -1051,10 +1046,7 @@ class Message(ABC): | |||||||
|                     if isinstance(v, list): |                     if isinstance(v, list): | ||||||
|                         cls = self._betterproto.cls_by_field[field_name] |                         cls = self._betterproto.cls_by_field[field_name] | ||||||
|                         if cls == datetime: |                         if cls == datetime: | ||||||
|                             v = [ |                             v = [isoparse(item) for item in value[key]] | ||||||
|                                 datetime.fromisoformat(item.replace("Z", "+00:00")) |  | ||||||
|                                 for item in value[key] |  | ||||||
|                             ] |  | ||||||
|                         elif cls == timedelta: |                         elif cls == timedelta: | ||||||
|                             v = [ |                             v = [ | ||||||
|                                 timedelta(seconds=float(item[:-1])) |                                 timedelta(seconds=float(item[:-1])) | ||||||
| @@ -1063,7 +1055,7 @@ class Message(ABC): | |||||||
|                         else: |                         else: | ||||||
|                             v = [cls().from_dict(item) for item in value[key]] |                             v = [cls().from_dict(item) for item in value[key]] | ||||||
|                     elif isinstance(v, datetime): |                     elif isinstance(v, datetime): | ||||||
|                         v = datetime.fromisoformat(value[key].replace("Z", "+00:00")) |                         v = isoparse(value[key]) | ||||||
|                         setattr(self, field_name, v) |                         setattr(self, field_name, v) | ||||||
|                     elif isinstance(v, timedelta): |                     elif isinstance(v, timedelta): | ||||||
|                         v = timedelta(seconds=float(value[key][:-1])) |                         v = timedelta(seconds=float(value[key][:-1])) | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| import betterproto | import betterproto | ||||||
| from dataclasses import dataclass | from dataclasses import dataclass | ||||||
| from typing import Optional, List, Dict | from typing import Optional, List, Dict | ||||||
|  | from datetime import datetime, timedelta | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_has_field(): | def test_has_field(): | ||||||
| @@ -395,3 +396,70 @@ def test_bool(): | |||||||
|     assert t |     assert t | ||||||
|     t.bar = 0 |     t.bar = 0 | ||||||
|     assert not t |     assert not t | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # valid ISO datetimes according to https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ | ||||||
|  | iso_candidates = """2009-12-12T12:34 | ||||||
|  | 2009 | ||||||
|  | 2009-05-19 | ||||||
|  | 2009-05-19 | ||||||
|  | 20090519 | ||||||
|  | 2009123 | ||||||
|  | 2009-05 | ||||||
|  | 2009-123 | ||||||
|  | 2009-222 | ||||||
|  | 2009-001 | ||||||
|  | 2009-W01-1 | ||||||
|  | 2009-W51-1 | ||||||
|  | 2009-W33 | ||||||
|  | 2009W511 | ||||||
|  | 2009-05-19 | ||||||
|  | 2009-05-19 00:00 | ||||||
|  | 2009-05-19 14 | ||||||
|  | 2009-05-19 14:31 | ||||||
|  | 2009-05-19 14:39:22 | ||||||
|  | 2009-05-19T14:39Z | ||||||
|  | 2009-W21-2 | ||||||
|  | 2009-W21-2T01:22 | ||||||
|  | 2009-139 | ||||||
|  | 2009-05-19 14:39:22-06:00 | ||||||
|  | 2009-05-19 14:39:22+0600 | ||||||
|  | 2009-05-19 14:39:22-01 | ||||||
|  | 20090621T0545Z | ||||||
|  | 2007-04-06T00:00 | ||||||
|  | 2007-04-05T24:00 | ||||||
|  | 2010-02-18T16:23:48.5 | ||||||
|  | 2010-02-18T16:23:48,444 | ||||||
|  | 2010-02-18T16:23:48,3-06:00 | ||||||
|  | 2010-02-18T16:23:00.4 | ||||||
|  | 2010-02-18T16:23:00,25 | ||||||
|  | 2010-02-18T16:23:00.33+0600 | ||||||
|  | 2010-02-18T16:00:00.23334444 | ||||||
|  | 2010-02-18T16:00:00,2283 | ||||||
|  | 2009-05-19 143922 | ||||||
|  | 2009-05-19 1439""".split( | ||||||
|  |     "\n" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_iso_datetime(): | ||||||
|  |     @dataclass | ||||||
|  |     class Envelope(betterproto.Message): | ||||||
|  |         ts: datetime = betterproto.message_field(1) | ||||||
|  |  | ||||||
|  |     msg = Envelope() | ||||||
|  |  | ||||||
|  |     for _, candidate in enumerate(iso_candidates): | ||||||
|  |         msg.from_dict({"ts": candidate}) | ||||||
|  |         assert isinstance(msg.ts, datetime) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_iso_datetime_list(): | ||||||
|  |     @dataclass | ||||||
|  |     class Envelope(betterproto.Message): | ||||||
|  |         timestamps: List[datetime] = betterproto.message_field(1) | ||||||
|  |  | ||||||
|  |     msg = Envelope() | ||||||
|  |  | ||||||
|  |     msg.from_dict({"timestamps": iso_candidates}) | ||||||
|  |     assert all([isinstance(item, datetime) for item in msg.timestamps]) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user