serdes
¶
Utilities for type translation, serialization, and deserialization.
Typical Usage
>>> import datetime
>>> from typelib import serdes
>>>
>>> serdes.unixtime(datetime.datetime(2020, 1, 1))
1577854800.0
>>> serdes.isoformat(datetime.timedelta(hours=1))
'PT1H'
>>> import dataclasses
>>> @dataclasses.dataclass
... class Class:
... attr: str
...
>>> instance = Class(attr="value")
>>> dict(serdes.iteritems(instance))
{'attr': 'value'}
MarshalledValueT
module-attribute
¶
MarshalledValueT: TypeAlias = 'PythonPrimitiveT | dict[PythonPrimitiveT, MarshalledValueT] | list[MarshalledValueT]'
Type alias for a Python value which is ready for over-the-wire serialization.
PythonPrimitiveT
module-attribute
¶
PythonPrimitiveT: TypeAlias = 'bool | int | float | str | None'
Type alias for serializable, non-container Python types.
PythonValueT
module-attribute
¶
PythonValueT: TypeAlias = 'PythonPrimitiveT | dict[PythonPrimitiveT, PythonValueT] | list[PythonValueT] | tuple[PythonValueT, ...] | set[PythonValueT]'
Type alias for any Python builtin type.
dateparse
¶
Parse a date string into a datetime object.
Examples:
>>> import datetime
>>> from typelib import serdes
>>> serdes.dateparse("1970-01-01",t=datetime.datetime)
DateTime(1970, 1, 1, 0, 0, 0, tzinfo=Timezone('UTC'))
Parameters:
Returns:
-
DateTimeT
–The parsed datetime object.
Raises:
-
ValueError
–If
val
is not a date string or does not resolve to an instance of the target datetime type.
Source code in src/typelib/serdes.py
decode
¶
Decode a bytes-like object into a str.
Note
If a non-bytes-like object is passed, it will be returned unchanged.
Examples:
>>> from typelib import serdes
>>> serdes.decode(b"abc")
'abc'
>>> serdes.decode(memoryview(b"abc"))
'abc'
Parameters:
-
val
(Any
) –The object to be decoded.
-
encoding
(str
, default:DEFAULT_ENCODING
) –The encoding to use when decoding the object (defaults "utf8").
Source code in src/typelib/serdes.py
get_items_iter
¶
Given a type, return a callable which will produce an iterator over (field, value) pairs.
Examples:
>>> import dataclasses
>>> from typelib import serdes
>>>
>>> @dataclasses.dataclass
... class Class:
... attr: str
...
>>> instance = Class(attr="value")
>>> iteritems = get_items_iter(Class)
>>> next(iteritems(instance))
('attr', 'value')
Parameters:
-
tp
(type
) –The type to create an iterator for.
Source code in src/typelib/serdes.py
isoformat
¶
Format any date/time object into an ISO-8601 string.
Note
While the standard library includes isoformat()
methods for
datetime.date
, datetime.time
, &
datetime.datetime
, they do not include a method for serializing
datetime.timedelta
, even though durations are included in the
ISO 8601 specification. This function fills that gap.
Examples:
>>> import datetime
>>> from typelib import serdes
>>> serdes.isoformat(datetime.date(1970, 1, 1))
'1970-01-01'
>>> serdes.isoformat(datetime.time())
'00:00:00'
>>> serdes.isoformat(datetime.datetime(1970, 1, 1))
'1970-01-01T00:00:00'
>>> serdes.isoformat(datetime.timedelta(hours=1))
'PT1H'
Source code in src/typelib/serdes.py
iteritems
¶
Iterate over (field, value) pairs for any object.
Examples:
>>> import dataclasses
>>> from typelib import serdes
>>>
>>> @dataclasses.dataclass
... class Class:
... attr: str
...
>>> instance = Class(attr="value")
>>> [*serdes.iteritems(instance)]
[('attr', 'value')]
>>> [*serdes.iteritems("string")]
[(0, 's'), (1, 't'), (2, 'r'), (3, 'i'), (4, 'n'), (5, 'g')]
>>> [*serdes.iteritems(serdes.iteritems(instance))]
[('attr', 'value')]
Note
If the given item is detected to be an iterable of pairs (e.g., [('a', 1), ('b', 2)]
),
we will iterate directly over that.
Otherwise, we will create an iterator over (field, value) pairs with the following strategy:
- For mappings ->
((key, value), ...)
- For structured objects (user-defined classes) ->
((field, value), ...)
- For all other iterables ->
((index, value), ...)
.
Parameters:
-
val
(Any
) –The object to iterate over.
Source code in src/typelib/serdes.py
itervalues
¶
Iterate over the contained values for any object.
Examples:
>>> import dataclasses
>>> from typelib import serdes
>>>
>>> @dataclasses.dataclass
... class Class:
... attr: str
...
>>> instance = Class(attr="value")
>>> [*serdes.itervalues(instance)]
['value']
Parameters:
-
val
(Any
) –The object to iterate over.
Source code in src/typelib/serdes.py
load
¶
load(val: _T) -> PythonValueT | _T
Attempt to decode val
if it is a text-like object.
Otherwise, return val
unchanged.
Examples:
>>> from typelib import serdes
>>> serdes.load(1)
1
>>> serdes.load("1")
1
>>> serdes.load("1,2")
(1, 2)
>>> serdes.load(b'{"a": 1, "b": 2}')
{'a': 1, 'b': 2}
Parameters:
-
val
(_T
) –The value to decode.
Source code in src/typelib/serdes.py
strload
¶
strload(val: str | bytes | bytearray | memoryview) -> PythonValueT
Attempt to decode a string-like input into a Python value.
Examples:
>>> from typelib import serdes
>>> serdes.strload("1")
1
>>> serdes.strload("1,2")
(1, 2)
>>> serdes.strload(b'{"a": 1, "b": 2}')
{'a': 1, 'b': 2}
Tip
This function is memoized and only safe for text-type inputs.
See Also
Parameters:
-
val
(str | bytes | bytearray | memoryview
) –The string-like input to be decoded.
Source code in src/typelib/serdes.py
unixtime
¶
Convert a date/time object to a unix timestamp.
Note
Time is messy. Here is how we've decided to make this work:
datetime.datetime
instances will preserve the current tzinfo (even if naive).datetime.time
instances will default to today, preserving the tzinfo (even if naive).datetime.date
instances will assume UTC.datetime.timedelta
instances be reflected as total seconds since epoch (January 1, 1970).
If you find yourself in a situation where this does not work for you, your best bet is to stop using tz-naive date/time objects. It's always best to keep your time explicit!
Parameters:
Examples:
>>> import datetime
>>> from typelib import serdes
>>>
>>> serdes.unixtime(datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc))
0.0
>>> serdes.unixtime(datetime.date(1970, 1, 1))
0.0