Skip to content

Commit

Permalink
Strict typing and link issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Avasam committed Aug 29, 2024
1 parent 3980400 commit f17baf1
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ database.
One may simply encode and decode Python objects to MongoDB
BSON-friendly representations::

class MyObject(object):
class MyObject:
def __init__(self, val):
self.val = val

Expand Down
13 changes: 8 additions & 5 deletions jaraco/modb/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from __future__ import annotations

import datetime as dt
from typing import Any

import jsonpickle.pickler
import jsonpickle.unpickler

# override the default pickler/unpickler to better handle some types


class Pickler(jsonpickle.pickler.Pickler):
def _flatten(self, obj):
class Pickler(jsonpickle.pickler.Pickler): # type: ignore[misc] # jsonpickle/jsonpickle#441
def _flatten(self, obj: object) -> Any | None:
if isinstance(obj, dt.datetime) and not obj.utcoffset():
# naive datetimes or UTC datetimes can be stored directly
return obj
Expand All @@ -16,13 +19,13 @@ def _flatten(self, obj):
return super(Pickler, self)._flatten(obj)


class Unpickler(jsonpickle.unpickler.Unpickler):
class Unpickler(jsonpickle.unpickler.Unpickler): # type: ignore[misc] # jsonpickle/jsonpickle#441
pass


def encode(value):
def encode(value: object) -> Any | None:
return Pickler().flatten(value)


def decode(value):
def decode(value: object) -> Any | None:
return Unpickler().restore(value)
Empty file added jaraco/modb/py.typed
Empty file.
6 changes: 5 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[mypy]
# Is the project well-typed?
strict = False
strict = True

# Early opt-in even when strict = False
warn_unused_ignores = True
Expand All @@ -12,3 +12,7 @@ explicit_package_bases = True

# Disable overload-overlap due to many false-positives
disable_error_code = overload-overlap

# jsonpickle/jsonpickle#441
[mypy-jsonpickle.*]
ignore_missing_imports = True
1 change: 1 addition & 0 deletions newsfragments/3.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Complete annotations and add ``py.typed`` marker -- by :user:`Avasam`
4 changes: 0 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,3 @@ type = [


[tool.setuptools_scm]


[tool.pytest-enabler.mypy]
# Disabled due to jaraco/skeleton#143
18 changes: 10 additions & 8 deletions tests/test_handlers.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,40 @@
import importlib
from __future__ import annotations

import collections
import decimal
import importlib

import jsonpickle


def setup_module():
def setup_module() -> None:
importlib.import_module('jaraco.modb')


def roundtrip(ob):
def roundtrip(ob: object) -> None:
encoded = jsonpickle.encode(ob)
print('encoded is', encoded)
decoded = jsonpickle.decode(encoded)
assert decoded == ob


def test_OrderedDict():
def test_OrderedDict() -> None:
d = collections.OrderedDict(y=3)
roundtrip(d)


def test_Decimal():
def test_Decimal() -> None:
roundtrip(decimal.Decimal(1.0))
roundtrip(decimal.Decimal(1000))


class MyText(str):
def __reduce__(self):
def __reduce__(self) -> tuple[type[MyText], tuple[str]]:
return MyText, (str(self),)


class TestUnicodeSubclass(object):
class TestUnicodeSubclass:
"This technique demonstrates how to handle a text-type subclass"

def test_UnicodeSubclass(self):
def test_UnicodeSubclass(self) -> None:
roundtrip(MyText('foo'))
28 changes: 16 additions & 12 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import datetime
import collections
import datetime
from typing import Dict, Generic, TypeVar

import bson.tz_util

import jaraco.modb

_T = TypeVar("_T")


def test_to_bson():
def test_to_bson() -> None:
sample = dict(
a='a string',
b='another string'.encode('ascii'),
c='some binary bytes'.encode('ascii') + b'\x00\xff',
)
res = jaraco.modb.encode(sample)
assert res is not None
assert res['a'] == sample['a']
assert res['b'] == sample['b']
assert jaraco.modb.decode(res) == sample


class ObjectUnderTest(object):
def __init__(self, val):
class ObjectUnderTest(Generic[_T]):
def __init__(self, val: _T) -> None:
self.val = val


def test_object():
def test_object() -> None:
ob = ObjectUnderTest(1)
serialized = jaraco.modb.encode(ob)
ob_res = jaraco.modb.decode(serialized)
Expand All @@ -32,7 +36,7 @@ def test_object():
assert ob.val == ob_res.val


def test_nested_object():
def test_nested_object() -> None:
ob_nested = ObjectUnderTest('child')
ob_parent = ObjectUnderTest(ob_nested)
serialized = jaraco.modb.encode(ob_parent)
Expand All @@ -42,19 +46,19 @@ def test_nested_object():
assert restored.val.val == 'child'


class MyDict(dict):
class MyDict(Dict[str, _T]):
pass


def test_encode_dict_subclass():
def test_encode_dict_subclass() -> None:
d = MyDict(a=3, b=4)
encoded = jaraco.modb.encode(d)
assert 'MyDict' in str(encoded)
decoded = jaraco.modb.decode(encoded)
assert isinstance(decoded, MyDict)


def test_ordered_dict():
def test_ordered_dict() -> None:
items = ('a', 1), ('c', 3), ('b', 4)
ob = collections.OrderedDict(items)
serialized = jaraco.modb.encode(ob)
Expand All @@ -64,23 +68,23 @@ def test_ordered_dict():
assert list(restored.values()) == [1, 3, 4]


def test_datetime_naive():
def test_datetime_naive() -> None:
now = datetime.datetime.now()
serialized = jaraco.modb.encode(now)
assert isinstance(serialized, datetime.datetime)
restored = jaraco.modb.decode(serialized)
assert restored == now


def test_datetime_utc():
def test_datetime_utc() -> None:
now = datetime.datetime.now(bson.tz_util.utc)
serialized = jaraco.modb.encode(now)
assert isinstance(serialized, datetime.datetime)
restored = jaraco.modb.decode(serialized)
assert restored == now


def test_datetime_local():
def test_datetime_local() -> None:
est = bson.tz_util.FixedOffset(-60 * 5, 'EST')
now = datetime.datetime.now(est)
serialized = jaraco.modb.encode(now)
Expand Down

0 comments on commit f17baf1

Please sign in to comment.