Add support for encoding pathlib.Path

This commit is contained in:
Dave Shawley 2021-11-04 07:15:34 -04:00
parent c2c2408786
commit b15f131df1
No known key found for this signature in database
GPG key ID: F41A8A99298F8EED
4 changed files with 29 additions and 3 deletions

View file

@ -7,6 +7,7 @@ Version History
- Add support for encoding :class:`decimal.Decimal`
- Add support for encoding :func:`dataclasses.dataclass` decorated classes
- Add support for encoding :class:`ipaddress.IPv4Address` and :class:`ipaddress.IPv6Address`
- Add support for encoding :class:`pathlib.Path`
- Add type annotations (see :ref:`type-info`)
- Return a "406 Not Acceptable" if the :http:header:`Accept` header values cannot be matched
and there is no default content type configured

View file

@ -11,6 +11,7 @@ import dataclasses
import decimal
import ipaddress
import json
import pathlib
import string
import typing
import urllib.parse
@ -119,9 +120,11 @@ class JSONTranscoder(handlers.TextContentHandler):
| :class:`ipaddress.IPv4Address` | Same as ``str(value.exploded)`` |
| :class:`ipaddress.IPv6Address` | |
+--------------------------------+------------------------------------+
| :class:`pathlib.Path` | Same as ``str(value)`` |
+--------------------------------+------------------------------------+
"""
if isinstance(obj, uuid.UUID):
if isinstance(obj, (pathlib.Path, uuid.UUID)):
return str(obj)
if hasattr(obj, 'isoformat'):
return typing.cast(type_info.SupportsIsoFormat, obj).isoformat()
@ -218,6 +221,8 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
| Dataclasses | `map family`_ after calling |
| | :func:`dataclasses.asdict` |
+-----------------------------------+-------------------------------+
| :class:`pathlib.Path` | Same as ``str(value)`` |
+-----------------------------------+-------------------------------+
.. _nil byte: https://github.com/msgpack/msgpack/blob/
0b8f5ac67cdd130f4d4d4fe6afb839b989fdb86a/spec.md#formats-nil
@ -249,7 +254,7 @@ class MsgPackTranscoder(handlers.BinaryContentHandler):
if isinstance(datum, self.PACKABLE_TYPES):
return datum
if isinstance(datum, uuid.UUID):
if isinstance(datum, (pathlib.Path, uuid.UUID)):
datum = str(datum)
if isinstance(datum, bytearray):
@ -345,6 +350,8 @@ class FormUrlEncodedTranscoder:
| :class:`ipaddress.IPv4Address` | ``str(v.exploded)`` |
| :class:`ipaddress.IPv6Address` | |
+--------------------------------+---------------------------------------+
| :class:`pathlib.Path` | Same as ``str(value)`` |
+--------------------------------+---------------------------------------+
https://url.spec.whatwg.org/#application/x-www-form-urlencoded

View file

@ -1,5 +1,6 @@
import decimal
import ipaddress
import pathlib
import typing
import uuid
@ -40,7 +41,8 @@ Serializable = typing.Union[SupportsIsoFormat, None, bool, bytearray, bytes,
float, int, memoryview, str, typing.Mapping,
typing.Sequence, typing.Set, uuid.UUID,
decimal.Decimal, SupportsDataclassFields,
ipaddress.IPv4Address, ipaddress.IPv6Address]
ipaddress.IPv4Address, ipaddress.IPv6Address,
pathlib.Path]
"""Types that can be serialized by this library.
This is the set of types that

View file

@ -6,6 +6,7 @@ import ipaddress
import json
import math
import os
import pathlib
import pickle
import struct
import typing
@ -373,6 +374,11 @@ class JSONTranscoderTests(unittest.TestCase):
dumped = self.transcoder.dumps({'addr': datum})
self.assertEqual(dumped, '{"addr":"%s"}' % (datum.exploded, ))
def test_that_paths_are_supported(self):
p = pathlib.Path(__file__)
dumped = self.transcoder.dumps({'path': p})
self.assertEqual(dumped, '{"path":"%s"}' % (p, ))
class ContentSettingsTests(unittest.TestCase):
def test_that_handler_listed_in_available_content_types(self):
@ -611,6 +617,11 @@ class MsgPackTranscoderTests(unittest.TestCase):
dumped = self.transcoder.packb(datum)
self.assertEqual(pack_string(datum.exploded), dumped)
def test_that_paths_are_supported(self):
p = pathlib.Path(__file__)
dumped = self.transcoder.packb(p)
self.assertEqual(pack_string(str(p)), dumped)
class FormUrlEncodingTranscoderTests(unittest.TestCase):
transcoder: type_info.Transcoder
@ -777,3 +788,8 @@ class FormUrlEncodingTranscoderTests(unittest.TestCase):
_, result = self.transcoder.to_bytes({'addr': datum})
self.assertEqual(
f'addr={datum.exploded}'.replace(':', '%3A').encode(), result)
def test_that_paths_are_supported(self):
p = pathlib.Path(__file__)
_, result = self.transcoder.to_bytes({'path': p})
self.assertEqual(f'path={str(p)}'.replace('/', '%2F').encode(), result)