Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strict typing, py.typed and link issues #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:
Comment on lines -23 to +30
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 @@ -13,3 +13,7 @@ explicit_package_bases = True
disable_error_code =
# Disable due to many false positives
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
Loading