diff --git a/CHANGES.rst b/CHANGES.rst
index 89c3e2d..a11d2a1 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -3,13 +3,17 @@
=========
-3.0.1 (unreleased)
+3.1.0 (unreleased)
==================
- Document the ``to_json_representation`` variants and add one
that guarantees sorted keys. Make the "fast" variant not dependent
on second-chance externalization.
-
+- Renamed the "datetime" module to "datetime_ext" to avoid conflicts
+ with the standard library. Backwards compatibility shims are in place.
+- Remove some long-deprecated parameters that were typically
+ undocumented.
+- Introduce some basic type annotations.
3.0.0 (2026-05-07)
==================
diff --git a/MANIFEST.in b/MANIFEST.in
index d516e2b..3e36184 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -11,6 +11,7 @@ include tox.ini
include *.txt
include .isort.cfg
include pyproject.toml
+include .readthedocs.yml
include .pylintrc
include make-manylinux
exclude .nti_cover_package
diff --git a/docs/api/datetime.rst b/docs/api/datetime.rst
index 0147edb..fcd5a9d 100644
--- a/docs/api/datetime.rst
+++ b/docs/api/datetime.rst
@@ -2,4 +2,4 @@
Datetime
==========
-.. automodule:: nti.externalization.datetime
+.. automodule:: nti.externalization.datetime_ext
diff --git a/pyproject.toml b/pyproject.toml
index da0b6db..ef0df0c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,8 +17,54 @@ requires = [
# failing in Python 2 (https://travis-ci.org/github/gevent/gevent/jobs/683782800);
# This was fixed in 3.0a5 (https://github.com/cython/cython/issues/3578)
# 3.0a6 fixes an issue cythonizing source on 32-bit platforms
- "Cython >= 3.2.1",
+ "Cython >= 3.2.4",
]
[tool.check-manifest]
ignore = ["*.c"]
+
+
+[tool.mypy]
+# Must be present for mypy to read this file.
+follow_imports = "normal"
+check_untyped_defs = true
+allow_redefinition = true
+disable_error_code = [
+ "method-assign"
+]
+# Our tests are in terrible shape
+# and will need some work to be clean
+exclude = [
+ 'test_.*\.py',
+]
+
+[[tool.mypy.overrides]]
+# third-party untyped code
+module = [
+ "ZODB.*",
+ "zope.*",
+ "persistent.*",
+ "cpuinfo",
+ "nti.*",
+ "botocore.*",
+ "fsspec.*",
+ "transaction",
+ "grpc",
+ "grpc_health.*",
+ "google.type.*",
+ "zc.*",
+ "z3c.*",
+ "netaddr.*",
+ "dnslib",
+ "cytoolz.*",
+ "toolz.*",
+ "boto3.*",
+ "pg8000",
+ "urllib3.*",
+ "indexed_gzip",
+ "pyperf",
+ "isodate",
+ "vmprof"
+
+]
+ignore_missing_imports = true
diff --git a/setup.py b/setup.py
index e9a548e..2005a8b 100755
--- a/setup.py
+++ b/setup.py
@@ -147,7 +147,7 @@ def _c(m):
setup(
name='nti.externalization',
- version='3.0.1.dev0',
+ version='3.1.0.dev0',
author='Jason Madden',
author_email='jason@seecoresoftware.com',
description="NTI Externalization",
diff --git a/src/nti/externalization/__init__.py b/src/nti/externalization/__init__.py
index 3571f4f..7af6b71 100644
--- a/src/nti/externalization/__init__.py
+++ b/src/nti/externalization/__init__.py
@@ -22,3 +22,8 @@
from nti.externalization.representation import to_json_representation
from nti.externalization.internalization import new_from_external_object
from nti.externalization.internalization import update_from_external_object
+
+# BWC hacks
+import sys
+import nti.externalization.datetime_ext as datetime
+sys.modules['nti.externalization.datetime'] = datetime
diff --git a/src/nti/externalization/_base_interfaces.py b/src/nti/externalization/_base_interfaces.py
index 913e8fe..15448ea 100644
--- a/src/nti/externalization/_base_interfaces.py
+++ b/src/nti/externalization/_base_interfaces.py
@@ -9,10 +9,6 @@
This module is **PRIVATE** to this package.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import decimal
@@ -64,7 +60,7 @@ def update_from_other(self, other):
return dict_update(self, other)
-def make_external_dict():
+def make_external_dict() -> LocatedExternalDict:
# This layer of indirection is for cython; it can't cimport
# types when the extension name doesn't match the
# pxd name. But it can cimport functions that are cpdef to return
@@ -187,7 +183,7 @@ def get_standard_external_fields():
))
-def isSyntheticKey(k):
+def isSyntheticKey(k:str) -> bool:
"""
Deprecated. Prefer to test against StandardExternalFields.EXTERNAL_KEYS
"""
@@ -241,7 +237,7 @@ def __init__(self):
_standard_internal_fields = StandardInternalFields()
-def get_standard_internal_fields():
+def get_standard_internal_fields() -> StandardInternalFields:
return _standard_internal_fields
# Note that we DO NOT include ``numbers.Number``
@@ -308,7 +304,7 @@ def __repr__(self): # pragma: no cover
#: The default externalization policy.
DEFAULT_EXTERNALIZATION_POLICY = ExternalizationPolicy()
-def get_default_externalization_policy():
+def get_default_externalization_policy() -> ExternalizationPolicy:
return DEFAULT_EXTERNALIZATION_POLICY
from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position
diff --git a/src/nti/externalization/_compat.py b/src/nti/externalization/_compat.py
index 6606310..e300dc9 100644
--- a/src/nti/externalization/_compat.py
+++ b/src/nti/externalization/_compat.py
@@ -7,25 +7,24 @@
import os
import sys
import logging
+from typing import overload
text_type = str
-PY2 = sys.version_info[0] == 2
-PY3 = sys.version_info[0] >= 3
-PYPY = hasattr(sys, 'pypy_version_info')
WIN = sys.platform.startswith("win")
LINUX = sys.platform.startswith('linux')
OSX = sys.platform == 'darwin'
-PURE_PYTHON = PYPY or os.getenv('PURE_PYTHON') or os.getenv("NTI_EXT_PURE_PYTHON")
+PURE_PYTHON = os.getenv('PURE_PYTHON') or os.getenv("NTI_EXT_PURE_PYTHON")
try:
from zope.dublincore.interfaces import IDCTimes # pylint: disable=unused-import
except ModuleNotFoundError:
from zope.interface import Interface
- class IDCTimes(Interface): # pylint: disable=inherit-non-class
+ #pylint: disable-next=inherit-non-class
+ class IDCTimes(Interface): # type:ignore[no-redef]
"""Mock"""
try:
@@ -34,7 +33,7 @@ class IDCTimes(Interface): # pylint: disable=inherit-non-class
TRACE = 5
logging.addLevelName(TRACE, "TRACE")
-def to_unicode(s, encoding='utf-8', err='strict'):
+def to_unicode(s, encoding:str='utf-8', err:str='strict') -> str|None:
"""
Decode a byte sequence and unicode result
"""
@@ -44,8 +43,15 @@ def to_unicode(s, encoding='utf-8', err='strict'):
text_ = to_unicode
+@overload
+def bytes_(s:str, encoding:str='', errors:str='') -> bytes:
+ ...
-def bytes_(s, encoding='utf-8', errors='strict'):
+@overload
+def bytes_(s:None, encoding:str='', errors:str='') -> None:
+ ...
+
+def bytes_(s, encoding:str='utf-8', errors:str='strict') -> bytes|None:
"""
If ``s`` is an instance of ``text_type``, return
``s.encode(encoding, errors)``, otherwise return ``s``
diff --git a/src/nti/externalization/_interface_cache.py b/src/nti/externalization/_interface_cache.py
index a4b6cef..73e63df 100644
--- a/src/nti/externalization/_interface_cache.py
+++ b/src/nti/externalization/_interface_cache.py
@@ -4,16 +4,11 @@
A cache based on the interfaces provided by an object.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
from weakref import WeakSet
from zope.interface import providedBy
-cache_instances = WeakSet()
+cache_instances: WeakSet["InterfaceCache"] = WeakSet()
class InterfaceCache(object):
@@ -41,7 +36,7 @@ def __init__(self):
self.modified_event_attributes = {}
-def cache_for_key_in_providedBy(key, provided_by): # type: (object, object) -> InterfaceCache
+def cache_for_key_in_providedBy(key, provided_by) -> InterfaceCache:
# The Declaration objects returned from ``providedBy(obj)`` maintain a _v_attrs that
# gets blown away on changes to themselves or their
# dependents, including adding interfaces dynamically to an instance
@@ -60,7 +55,7 @@ def cache_for_key_in_providedBy(key, provided_by): # type: (object, object) -> I
return cache
-def cache_for(externalizer, ext_self): # type: (object, object) -> InterfaceCache
+def cache_for(externalizer, ext_self) -> InterfaceCache:
return cache_for_key_in_providedBy(type(externalizer), providedBy(ext_self))
@@ -82,4 +77,5 @@ def _cache_cleanUp(instances):
# pylint:disable=wrong-import-position
from nti.externalization._compat import import_c_accel
+
import_c_accel(globals(), 'nti.externalization.__interface_cache')
diff --git a/src/nti/externalization/_threadlocal.py b/src/nti/externalization/_threadlocal.py
index 2e7434f..6a23cc0 100644
--- a/src/nti/externalization/_threadlocal.py
+++ b/src/nti/externalization/_threadlocal.py
@@ -4,34 +4,35 @@
Thread local utilities.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
import threading
+from collections.abc import Callable
+from typing import Generic
+from typing import TypeVar
+
+T = TypeVar("T")
# This cannot be optimized (much) with cython, threading.local could be monkey-patched by gevent,
# so this cannot be a cdef class
-class ThreadLocalManager(threading.local):
+class ThreadLocalManager(threading.local, Generic[T]):
- def __init__(self, default):
+ def __init__(self, default:Callable[[], T]):
# This is called once in each thread, the first time the object
# is used in the thread. The super class does nothing. We use lots
# of threads/greenlets, so save the time.
# pylint:disable=super-init-not-called
- self.stack = []
+ self.stack: list[T] = []
self.default = default
- def push(self, info):
+ def push(self, info:T) -> None:
self.stack.append(info)
set = push # b/c
- def pop(self):
+ def pop(self) -> T|None:
return self.stack.pop() if self.stack else None
- def get(self):
+ def get(self) -> T:
stack = self.stack
if not stack:
return self.default() # Note we're not storing it!
diff --git a/src/nti/externalization/autopackage.py b/src/nti/externalization/autopackage.py
index 68aff56..1467eca 100644
--- a/src/nti/externalization/autopackage.py
+++ b/src/nti/externalization/autopackage.py
@@ -6,17 +6,17 @@
"""
import logging
+from collections.abc import Iterable
from zope import interface
-
from zope.dottedname import resolve as dottedname
from zope.mimetype.interfaces import IContentTypeAware
from nti.schema.interfaces import find_most_derived_interface
+
from ._compat import TRACE
from .datastructures import ModuleScopedInterfaceObjectIO
-
logger = logging.getLogger(__name__)
# If we extend ExtensionClass.Base, __class_init__ is called automatically
@@ -24,7 +24,6 @@
# is probably not what we want
# import ExtensionClass
-
class _ClassNameRegistry(object):
__name__ = ''
@@ -74,7 +73,7 @@ def _ap_compute_external_class_name_from_interface_and_instance(cls, unused_ifac
return cls._ap_compute_external_class_name_from_concrete_class(impl.__class__)
@classmethod
- def _ap_compute_external_class_name_from_concrete_class(cls, a_type):
+ def _ap_compute_external_class_name_from_concrete_class(cls, a_type) -> str:
"""
Return the string value of the external class name.
@@ -87,7 +86,7 @@ def _ap_compute_external_class_name_from_concrete_class(cls, a_type):
return getattr(a_type, '__external_class_name__', a_type.__name__)
@classmethod
- def _ap_compute_external_mimetype(cls, package_name, unused_a_type, ext_class_name):
+ def _ap_compute_external_mimetype(cls, package_name, unused_a_type, ext_class_name) -> str:
"""
Return the string value of the external mime type for the given
type in the given package having the given external name (probably
@@ -105,7 +104,7 @@ def _ap_compute_external_mimetype(cls, package_name, unused_a_type, ext_class_na
@classmethod
# TODO: We can probably do something with this
- def _ap_enumerate_externalizable_root_interfaces(cls, interfaces):
+ def _ap_enumerate_externalizable_root_interfaces(cls, interfaces) -> Iterable:
"""
Return an iterable of the root interfaces in this package that should be
externalized.
@@ -115,7 +114,7 @@ def _ap_enumerate_externalizable_root_interfaces(cls, interfaces):
raise NotImplementedError()
@classmethod
- def _ap_enumerate_module_names(cls):
+ def _ap_enumerate_module_names(cls) -> Iterable[str]:
"""
Return an iterable of module names in this package that should be searched to find
factories.
@@ -125,7 +124,7 @@ def _ap_enumerate_module_names(cls):
raise NotImplementedError()
@classmethod
- def _ap_find_potential_factories_in_module(cls, module):
+ def _ap_find_potential_factories_in_module(cls, module) -> Iterable[type]:
"""
Given a module that we're supposed to examine, iterate over
the types that could be factories.
@@ -249,7 +248,7 @@ def _ap_handle_one_potential_factory_class(cls, namespace, package_name, impleme
implementation_class.containerId = None
@classmethod
- def _ap_find_package_name(cls):
+ def _ap_find_package_name(cls) -> str:
"""
Return the package name to search for modules.
diff --git a/src/nti/externalization/configure.zcml b/src/nti/externalization/configure.zcml
index ba1d962..7481958 100644
--- a/src/nti/externalization/configure.zcml
+++ b/src/nti/externalization/configure.zcml
@@ -48,16 +48,16 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
diff --git a/src/nti/externalization/datastructures.py b/src/nti/externalization/datastructures.py
index 9efcca1..e3eb719 100644
--- a/src/nti/externalization/datastructures.py
+++ b/src/nti/externalization/datastructures.py
@@ -4,52 +4,47 @@
Datastructures to help externalization.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
# There are a *lot* of fixme (XXX and the like) in this file.
# Turn those off in general so we can see through the noise.
# pylint:disable=fixme
# pylint:disable=keyword-arg-before-vararg
-
# stdlib imports
import numbers
import warnings
+from collections.abc import Collection
+from collections.abc import Mapping
+from collections.abc import MutableMapping
from zope import interface
from zope import schema
from zope.component import getUtility
-from zope.schema.interfaces import SchemaNotProvided
from zope.schema.interfaces import IDict
from zope.schema.interfaces import IObject
+from zope.schema.interfaces import SchemaNotProvided
from nti.schema.interfaces import find_most_derived_interface
-from .interfaces import IInternalObjectExternalizer
-from .interfaces import IInternalObjectIO
-from .interfaces import IInternalObjectIOFinder
-from .interfaces import IAnonymousObjectFactory
-from .interfaces import StandardInternalFields
-
+from ._base_interfaces import NotGiven
+from ._base_interfaces import get_default_externalization_policy
+from ._base_interfaces import get_standard_external_fields
+from ._base_interfaces import get_standard_internal_fields
+from ._interface_cache import cache_for
# Things imported from cython with matching cimport
-from .externalization.dictionary import to_minimal_standard_external_dictionary
from .externalization.dictionary import internal_to_standard_external_dictionary
+from .externalization.dictionary import to_minimal_standard_external_dictionary
# Must rename this so it doesn't conflict with method defs;
# that breaks cython
from .externalization.externalizer import to_external_object as _toExternalObject
-
+from .factory import AnonymousObjectFactory
+from .interfaces import IAnonymousObjectFactory
+from .interfaces import IInternalObjectExternalizer
+from .interfaces import IInternalObjectIO
+from .interfaces import IInternalObjectIOFinder
+from .interfaces import StandardInternalFields
from .internalization import validate_named_field_value
from .internalization.factories import find_factory_for
from .representation import make_repr
-from .factory import AnonymousObjectFactory
-
-from ._base_interfaces import get_standard_external_fields
-from ._base_interfaces import get_standard_internal_fields
-from ._base_interfaces import get_default_externalization_policy
-from ._base_interfaces import NotGiven
-
-from ._interface_cache import cache_for
StandardExternalFields = get_standard_external_fields()
StandardInternalFields = get_standard_internal_fields()
@@ -83,7 +78,9 @@ def _ext_replacement(self):
"""
return self
- def _ext_standard_external_dictionary(self, replacement, mergeFrom=None, **kwargs):
+ def _ext_standard_external_dictionary(self, replacement,
+ mergeFrom: Mapping|None = None,
+ **kwargs) -> MutableMapping:
if self.__external_use_minimal_base__:
return to_minimal_standard_external_dictionary(replacement,
mergeFrom=mergeFrom)
@@ -97,7 +94,8 @@ def _ext_standard_external_dictionary(self, replacement, mergeFrom=None, **kwarg
policy=kwargs.get("policy", DEFAULT_EXTERNALIZATION_POLICY),
)
- def toExternalDictionary(self, mergeFrom=None, *unused_args, **kwargs):
+ def toExternalDictionary(self, mergeFrom:Mapping|None = None,
+ *unused_args, **kwargs) -> MutableMapping:
"""
Produce the standard external dictionary for this object.
@@ -193,7 +191,7 @@ class AbstractDynamicObjectIO(ExternalizableDictionaryMixin):
StandardExternalFields.CLASS,
StandardInternalFields.CONTAINER_ID
})
- _ext_primitive_out_ivars_ = frozenset()
+ _ext_primitive_out_ivars_:Collection[str] = frozenset()
_prefer_oid_ = False
def find_factory_for_named_value(self, key, value): # pylint:disable=unused-argument
@@ -313,7 +311,8 @@ def toExternalDictionary(self, mergeFrom=None, *unused_args, **kwargs):
result[StandardExternalFields.ID] = result[StandardExternalFields.OID]
return result
- def toExternalObject(self, mergeFrom=None, *args, **kwargs):
+ def toExternalObject(self, mergeFrom: MutableMapping|None = None,
+ *args, **kwargs) -> MutableMapping:
return self.toExternalDictionary(mergeFrom, *args, **kwargs)
def _ext_accept_update_key(self, k, ext_self, ext_keys): # pylint:disable=unused-argument
@@ -651,7 +650,7 @@ def _ext_getattr(self, ext_self, k, default=NotGiven):
def _ext_setattr(self, ext_self, k, value):
validate_named_field_value(ext_self, self._iface, k, value)()
- def _ext_accept_external_id(self, ext_self, parsed):
+ def _ext_accept_external_id(self, ext_self, parsed) -> bool:
"""
If the interface we're working from has a tagged value
of ``__external_accept_id__`` on the ``id`` field, then
@@ -660,7 +659,7 @@ def _ext_accept_external_id(self, ext_self, parsed):
cache = cache_for(self, ext_self)
if cache.ext_accept_external_id is None:
try:
- field = cache.iface['id']
+ field = cache.iface['id'] # type:ignore[index]
cache.ext_accept_external_id = field.getTaggedValue('__external_accept_id__')
except KeyError:
cache.ext_accept_external_id = False
@@ -782,7 +781,8 @@ def _validate_after_update(self, iface, ext_self):
e.args = (errors[0][0],)
raise
- def toExternalObject(self, mergeFrom=None, **kwargs): # pylint:disable=arguments-differ
+ def toExternalObject(self, mergeFrom: MutableMapping|None = None,# pylint:disable=arguments-differ
+ **kwargs) -> MutableMapping:
ext_class_name = None
# Walk up the tree, checking each one to see if ``__external__class_name__`` exists
# and wants to provide a value. The walking up is what ``queryTaggedValue`` would do,
@@ -868,6 +868,7 @@ def _ext_find_schema(self, ext_self, iface_upper_bound):
return most_derived
def _ext_schemas_to_consider(self, ext_self):
+ assert self._ext_search_module is not None
search_module_name = self._ext_search_module.__name__
return [x for x in interface.providedBy(ext_self)
if x.__module__ == search_module_name
diff --git a/src/nti/externalization/datetime.py b/src/nti/externalization/datetime_ext.py
similarity index 98%
rename from src/nti/externalization/datetime.py
rename to src/nti/externalization/datetime_ext.py
index a1f9094..19391a2 100644
--- a/src/nti/externalization/datetime.py
+++ b/src/nti/externalization/datetime_ext.py
@@ -11,13 +11,8 @@
this package has been configured, but they can be called manually as well.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
from datetime import datetime
-import sys
import time
import isodate
@@ -57,7 +52,7 @@ def _parse_with(func, string):
).with_traceback(e.__traceback__) from e
-_input_type = (str if sys.version_info[0] >= 3 else basestring) # pylint:disable=undefined-variable
+_input_type = str
# XXX: This should really be either unicode or str on Python 2. We need to *know*
# what our input type is. All the tests pass on Python 3 with this registered to 'str',
# so we're never passing ``bytes``
diff --git a/src/nti/externalization/dublincore.py b/src/nti/externalization/dublincore.py
index 0b00648..33f7c17 100644
--- a/src/nti/externalization/dublincore.py
+++ b/src/nti/externalization/dublincore.py
@@ -14,10 +14,6 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
from zope import component
from zope import interface
try:
@@ -25,9 +21,9 @@
from zope.dublincore.interfaces import IDCExtended
except ModuleNotFoundError:
# pylint:disable=inherit-non-class
- class IDCDescriptiveProperties(interface.Interface):
+ class IDCDescriptiveProperties(interface.Interface): # type:ignore[no-redef]
"""Mock"""
- class IDCExtended(interface.Interface):
+ class IDCExtended(interface.Interface): # type:ignore[no-redef]
"""Mock"""
from nti.externalization.interfaces import IExternalStandardDictionaryDecorator
diff --git a/src/nti/externalization/extension_points.py b/src/nti/externalization/extension_points.py
index 57c8ebe..b812e50 100644
--- a/src/nti/externalization/extension_points.py
+++ b/src/nti/externalization/extension_points.py
@@ -24,10 +24,6 @@
.. versionadded:: 1.0
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
from zope.hookable import hookable
from ._compat import to_unicode
diff --git a/src/nti/externalization/externalization/__init__.py b/src/nti/externalization/externalization/__init__.py
index 6465383..95da55a 100644
--- a/src/nti/externalization/externalization/__init__.py
+++ b/src/nti/externalization/externalization/__init__.py
@@ -8,10 +8,11 @@
"""
+from collections.abc import MutableMapping
+
# Our request hook function always returns None, and pylint
# flags that as useless (good for it)
# pylint:disable=assignment-from-none
-
import warnings
from collections.abc import Mapping
@@ -19,26 +20,20 @@
from zope import deferredimport
from nti.externalization._base_interfaces import MINIMAL_SYNTHETIC_EXTERNAL_KEYS
-from nti.externalization._base_interfaces import isSyntheticKey
-from nti.externalization._base_interfaces import NotGiven
from nti.externalization._base_interfaces import PRIMITIVES as _primitives
-
+from nti.externalization._base_interfaces import NotGiven
+from nti.externalization._base_interfaces import isSyntheticKey
from nti.externalization.extension_points import get_current_request
-from .replacers import NonExternalizableObjectError
-
+from .decorate import decorate_external_mapping as _decorate_external_mapping
+from .dictionary import to_minimal_standard_external_dictionary
+from .dictionary import to_standard_external_dictionary
+from .externalizer import to_external_object
from .fields import choose_field
-
+from .replacers import NonExternalizableObjectError
from .standard_fields import SYSTEM_USER_NAME
-from .standard_fields import get_last_modified_time
from .standard_fields import get_created_time
-
-from .dictionary import to_standard_external_dictionary
-from .dictionary import to_minimal_standard_external_dictionary
-
-from .externalizer import to_external_object
-
-from .decorate import decorate_external_mapping as _decorate_external_mapping
+from .standard_fields import get_last_modified_time
__all__ = [
'choose_field',
@@ -102,12 +97,6 @@ def toExternalDictionary(*args, **kwargs): # pragma: no cover
return to_standard_external_dictionary(*args, **kwargs)
-def is_nonstr_iter(v): # pragma: no cover
- warnings.warn("'is_nonstr_iter' will be deleted. It is broken on Python 3",
- FutureWarning, stacklevel=2)
- return hasattr(v, '__iter__')
-
-
def removed_unserializable(ext):
# pylint:disable=too-many-branches,too-complex
# XXX: Why is this here? We don't use it anymore.
@@ -122,10 +111,12 @@ def _clean(m):
for k, v in list(m.items()):
if _is_sequence(v):
if not isinstance(v, list):
+ assert isinstance(m, MutableMapping)
m[k] = list(v)
# pylint:disable-next=confusing-consecutive-elif
elif not isinstance(v, Mapping):
if not isinstance(v, _primitives):
+ assert isinstance(m, MutableMapping)
m[k] = None
values = m.values()
elif isinstance(m, list):
diff --git a/src/nti/externalization/externalization/_externalizer.pxd b/src/nti/externalization/externalization/_externalizer.pxd
index 3e208a8..edbbe1c 100644
--- a/src/nti/externalization/externalization/_externalizer.pxd
+++ b/src/nti/externalization/externalization/_externalizer.pxd
@@ -50,7 +50,7 @@ cdef tuple MAPPING_TYPES
cdef class _ExternalizationState(object):
cdef dict memo
- cdef basestring name
+ cdef str name
cdef catch_components
cdef catch_component_action
cdef request
@@ -78,7 +78,6 @@ cdef class _RecursiveCallState(dict):
cpdef to_external_object(
obj,
name=*,
- registry=*,
catch_components=*,
catch_component_action=*,
request=*,
diff --git a/src/nti/externalization/externalization/_standard_fields.pxd b/src/nti/externalization/externalization/_standard_fields.pxd
index 58e9e40..c615fbe 100644
--- a/src/nti/externalization/externalization/_standard_fields.pxd
+++ b/src/nti/externalization/externalization/_standard_fields.pxd
@@ -27,8 +27,8 @@ cdef tuple _CREATOR_FIELDS
cdef tuple _CONTAINER_FIELDS
cdef _EXT_CLASS_IGNORED_MODULES
-cdef basestring _SYSTEM_USER_NAME
-cdef basestring _SYSTEM_USER_ID
+cdef str _SYSTEM_USER_NAME
+cdef str _SYSTEM_USER_ID
cdef IPrincipal_providedBy
# XXX: If we use ``cdef``, then when we pass these functions to
diff --git a/src/nti/externalization/externalization/dictionary.py b/src/nti/externalization/externalization/dictionary.py
index 552529c..49ab104 100644
--- a/src/nti/externalization/externalization/dictionary.py
+++ b/src/nti/externalization/externalization/dictionary.py
@@ -7,46 +7,34 @@
# Our request hook function always returns None, and pylint
# flags that as useless (good for it)
# pylint:disable=assignment-from-none
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
-import warnings
+from collections.abc import Mapping
-
-from nti.externalization._base_interfaces import make_external_dict
+from nti.externalization._base_interfaces import LocatedExternalDict
from nti.externalization._base_interfaces import NotGiven
-
-
-from nti.externalization.extension_points import set_external_identifiers
-from nti.externalization.interfaces import IExternalStandardDictionaryDecorator
-
-
-from nti.externalization._base_interfaces import get_standard_external_fields
from nti.externalization._base_interfaces import get_default_externalization_policy
-
-
-from nti.externalization.externalization.standard_fields import get_last_modified_time
+from nti.externalization._base_interfaces import get_standard_external_fields
+from nti.externalization._base_interfaces import make_external_dict
+from nti.externalization.extension_points import set_external_identifiers
+from nti.externalization.externalization.decorate import decorate_external_object
+from nti.externalization.externalization.standard_fields import get_class
+from nti.externalization.externalization.standard_fields import get_container_id
from nti.externalization.externalization.standard_fields import get_created_time
from nti.externalization.externalization.standard_fields import get_creator
-from nti.externalization.externalization.standard_fields import get_container_id
-from nti.externalization.externalization.standard_fields import get_class
-
-from nti.externalization.externalization.decorate import decorate_external_object
+from nti.externalization.externalization.standard_fields import get_last_modified_time
+from nti.externalization.interfaces import IExternalStandardDictionaryDecorator
StandardExternalFields = get_standard_external_fields()
DEFAULT_EXTERNALIZATION_POLICY = get_default_externalization_policy()
def internal_to_standard_external_dictionary(
self,
- mergeFrom=None,
+ mergeFrom: Mapping|None = None,
decorate=True,
request=NotGiven,
decorate_callback=NotGiven,
policy=DEFAULT_EXTERNALIZATION_POLICY,
-):
+) -> LocatedExternalDict:
# pylint:disable=too-many-positional-arguments
# The real implementation of this function. Code in this
# package should use this; code outside of this package *MUST NOT*
@@ -73,20 +61,18 @@ def internal_to_standard_external_dictionary(
return result
+
+
def to_standard_external_dictionary(
self,
- mergeFrom=None,
- registry=NotGiven, # Ignored
+ mergeFrom: Mapping|None = None,
decorate=True,
request=NotGiven,
decorate_callback=NotGiven,
policy=DEFAULT_EXTERNALIZATION_POLICY,
- # These are ignored, present for BWC
- name=NotGiven,
- useCache=NotGiven,
- **kwargs
-):
- """to_standard_external_dictionary(self, mergeFrom=None, decorate=True, request=NotGiven)
+) -> LocatedExternalDict:
+ """
+ to_standard_external_dictionary(self, mergeFrom=None, decorate=True, request=NotGiven)
Returns a dictionary representing the standard externalization of
the object *self*. This function takes care of many of the standard external fields:
@@ -115,34 +101,25 @@ def to_standard_external_dictionary(
type and mutating the dictionary returned from super's
``toExternalObject`` in your own implementation.
- :keyword dict mergeFrom: For convenience, if *mergeFrom* is not
+ :keyword dict mergeFrom: For convenience, if *mergeFrom* is not
`None`, then values it contains will be added to the dictionary
created by this method. The keys and values in *mergeFrom*
should already be external.
- :type mergeFrom: dict
- :keyword ExternalizationPolicy policy: The :class:`~.ExternalizationPolicy` to
+ :type mergeFrom: dict
+ :keyword ExternalizationPolicy policy: The :class:`~.ExternalizationPolicy` to
use. Must not be None.
- :returns: A `.LocatedExternalDict`. For further externalization,
+ :returns: A `.LocatedExternalDict`. For further externalization,
this object should be mutated in place.
- .. versionchanged:: 1.0a1
+ .. versionchanged:: 1.0a1
Arbitrary keyword arguments not used by this function are deprecated
and produce a warning.
- .. versionchanged:: 2.1
+ .. versionchanged:: 2.1
Add the *policy* keyword.
+ .. versionchanged:: NEXT
+ Remove deprecated parameters.
"""
# pylint:disable=too-many-positional-arguments
- if (
- kwargs
- or name is not NotGiven
- or useCache is not NotGiven
- or registry is not NotGiven
- ): # pragma: no cover
- for _ in range(3):
- warnings.warn(
- "Passing unused arguments to to_standard_external_dictionary will be an error",
- FutureWarning)
-
return internal_to_standard_external_dictionary(
self,
mergeFrom,
@@ -153,7 +130,8 @@ def to_standard_external_dictionary(
)
-def to_minimal_standard_external_dictionary(self, mergeFrom=None):
+def to_minimal_standard_external_dictionary(self,
+ mergeFrom:Mapping|None = None) -> LocatedExternalDict:
"""
Does no decoration. Useful for non-'object' types. *self* should have a *mime_type* field.
"""
@@ -170,5 +148,5 @@ def to_minimal_standard_external_dictionary(self, mergeFrom=None):
return result
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import import_c_accel
import_c_accel(globals(), 'nti.externalization.externalization._dictionary')
diff --git a/src/nti/externalization/externalization/externalizer.py b/src/nti/externalization/externalization/externalizer.py
index 7fac493..9a6c4a4 100644
--- a/src/nti/externalization/externalization/externalizer.py
+++ b/src/nti/externalization/externalization/externalizer.py
@@ -5,51 +5,46 @@
"""
-# Our request hook function always returns None, and pylint
-# flags that as useless (good for it)
-# pylint:disable=assignment-from-none
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# stdlib imports
+import logging
import warnings
-from collections.abc import Set
-from collections.abc import Mapping
from collections import defaultdict
+from collections.abc import Callable
+from collections.abc import Mapping
+from collections.abc import MutableMapping
+from collections.abc import Set
+from typing import Any
from weakref import WeakKeyDictionary
-
try:
from persistent.list import PersistentList
_PL = (PersistentList,)
except ModuleNotFoundError:
_PL = ()
-from zope.component import queryAdapter
from zope.component import getUtility
+from zope.component import queryAdapter
from zope.interface.common.sequence import IFiniteSequence
-from nti.externalization._base_interfaces import NotGiven
from nti.externalization._base_interfaces import PRIMITIVES
+from nti.externalization._base_interfaces import NotGiven
from nti.externalization._base_interfaces import get_default_externalization_policy
from nti.externalization._threadlocal import ThreadLocalManager
from nti.externalization.extension_points import get_current_request
-
-from nti.externalization.interfaces import IInternalObjectExternalizer
+from nti.externalization.externalization.decorate import decorate_external_object
+from nti.externalization.externalization.dictionary import internal_to_standard_external_dictionary
+from nti.externalization.externalization.replacers import DefaultNonExternalizableReplacer
+from nti.externalization.interfaces import IExternalizationPolicy
from nti.externalization.interfaces import IExternalObjectDecorator
+from nti.externalization.interfaces import IInternalObjectExternalizer
from nti.externalization.interfaces import ILocatedExternalSequence
from nti.externalization.interfaces import INonExternalizableReplacementFactory
-from nti.externalization.interfaces import IExternalizationPolicy
-
-from nti.externalization.externalization.replacers import DefaultNonExternalizableReplacer
-
-from nti.externalization.externalization.dictionary import internal_to_standard_external_dictionary
-from nti.externalization.externalization.decorate import decorate_external_object
+# Our request hook function always returns None, and pylint
+# flags that as useless (good for it)
+# pylint:disable=assignment-from-none
+# stdlib imports
-logger = __import__('logging').getLogger(__name__)
+logger = logging.getLogger(__name__)
DEFAULT_EXTERNALIZATION_POLICY = get_default_externalization_policy()
@@ -60,7 +55,9 @@
# the name that was established at the top level.
# Stores tuples (name, memos)
-_manager = ThreadLocalManager(default=lambda: (NotGiven, None, DEFAULT_EXTERNALIZATION_POLICY))
+_manager: ThreadLocalManager[tuple[Any, Any, Any]] = ThreadLocalManager(
+ default=lambda: (NotGiven, None, DEFAULT_EXTERNALIZATION_POLICY)
+)
_manager_get = _manager.get
_manager_pop = _manager.pop
_manager_push = _manager.push
@@ -102,8 +99,11 @@ class _ExternalizationState(object):
'_kwargs',
)
- def __init__(self, memos,
- name, catch_components, catch_component_action,
+ def __init__(self,
+ memos,
+ name,
+ catch_components: tuple[type[BaseException], ...] | type[BaseException],
+ catch_component_action: Callable[[Any, BaseException], Any]|None,
request,
default_non_externalizable_replacer,
decorate=True,
@@ -130,7 +130,7 @@ def __init__(self, memos,
self.policy = policy
- self._kwargs = None
+ self._kwargs: dict|None = None
def as_kwargs(self):
if self._kwargs is None:
@@ -181,7 +181,7 @@ def _externalize_sequence(obj, state):
return result
-_usable_externalObject_cache = WeakKeyDictionary()
+_usable_externalObject_cache:MutableMapping[type, bool] = WeakKeyDictionary()
_usable_externalObject_cache_get = _usable_externalObject_cache.get
try:
@@ -238,7 +238,7 @@ def _externalize_object(obj, state):
adapter = IInternalObjectExternalizer(obj, None)
if adapter is not None:
- toExternalObject = adapter.toExternalObject
+ toExternalObject = adapter.toExternalObject # type:ignore[misc]
if toExternalObject is not None:
result = toExternalObject(**state.as_kwargs())
@@ -294,7 +294,9 @@ def _to_external_object_state(obj, state, top_level=False):
# TODO: Should this live here, or at a higher level where the ultimate
# external target/use-case is known?
replacer = state.default_non_externalizable_replacer
- result = INonExternalizableReplacementFactory(obj, replacer)(obj)
+ result = INonExternalizableReplacementFactory( # type:ignore[misc]
+ obj, replacer
+ )(obj) # type:ignore[call-arg]
decorate_external_object(
@@ -325,9 +327,8 @@ def _to_external_object_state(obj, state, top_level=False):
def to_external_object(
obj,
name=NotGiven,
- registry=NotGiven,
- catch_components=(),
- catch_component_action=None,
+ catch_components: tuple[type[BaseException],...]|type[BaseException] = (),
+ catch_component_action: Callable[[Any, BaseException], Any]|None = None,
request=NotGiven,
decorate=True,
useCache=True,
@@ -344,7 +345,7 @@ def to_external_object(
:const:`SEQUENCE_TYPES` and :const:`MAPPING_TYPES` for details on
what we can handle by default.
- :param string name: The name of the adapter to
+ :param str name: The name of the adapter to
:class:`~nti.externalization.interfaces.IInternalObjectExternalizer`
to look for. Defaults to the empty string (the default
adapter). If you provide a name, and an adapter is not found,
@@ -380,6 +381,9 @@ def to_external_object(
is used.
:param str policy_name: If no *policy* is given, then this is used to
lookup a utility. If this is used, the utility must exist.
+
+ .. versionchanged:: NEXT
+ Remove the deprecated *registry* argument.
"""
# pylint:disable=too-many-positional-arguments
# Catch the primitives up here, quickly. This catches
@@ -394,11 +398,6 @@ def to_external_object(
name = ''
if request is NotGiven:
request = get_current_request()
- if registry is not NotGiven: # pragma: no cover
- warnings.warn(
- "The registry argument is deprecated and ignored. Call in a correct site.",
- FutureWarning
- )
if policy is NotGiven:
@@ -425,5 +424,7 @@ def to_external_object(
_manager_pop()
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import \
+ import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+
import_c_accel(globals(), 'nti.externalization.externalization._externalizer')
diff --git a/src/nti/externalization/externalization/fields.py b/src/nti/externalization/externalization/fields.py
index 20f23f0..394797d 100644
--- a/src/nti/externalization/externalization/fields.py
+++ b/src/nti/externalization/externalization/fields.py
@@ -4,17 +4,8 @@
Finding fields of an object.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-
from nti.externalization._base_interfaces import get_standard_external_fields
-logger = __import__('logging').getLogger(__name__)
-
StandardExternalFields = get_standard_external_fields()
def choose_field(result, self, ext_name,
diff --git a/src/nti/externalization/externalization/replacers.py b/src/nti/externalization/externalization/replacers.py
index 5fff2f2..5c1a35a 100644
--- a/src/nti/externalization/externalization/replacers.py
+++ b/src/nti/externalization/externalization/replacers.py
@@ -4,17 +4,16 @@
Object replacers.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-from zope import interface
+import logging
+
from zope import deprecation
+from zope import interface
from nti.externalization.interfaces import INonExternalizableReplacement
from nti.externalization.interfaces import INonExternalizableReplacementFactory
-logger = __import__('logging').getLogger(__name__)
+logger = logging.getLogger(__name__)
@interface.implementer(INonExternalizableReplacement)
class _NonExternalizableObject(dict):
diff --git a/src/nti/externalization/externalization/standard_fields.py b/src/nti/externalization/externalization/standard_fields.py
index 7ed042c..647af79 100644
--- a/src/nti/externalization/externalization/standard_fields.py
+++ b/src/nti/externalization/externalization/standard_fields.py
@@ -4,9 +4,6 @@
Functions to find standard fields.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
# pylint:disable=inconsistent-return-statements
@@ -47,7 +44,7 @@ def datetime_to_unix_time(dt):
def datetime_to_string(dt):
global _datetime_to_string # pylint:disable=global-statement
if _datetime_to_string is None:
- from nti.externalization.datetime import datetime_to_string as dts
+ from nti.externalization.datetime_ext import datetime_to_string as dts
_datetime_to_string = dts
if dt is not None:
return _datetime_to_string(dt).toExternalObject()
diff --git a/src/nti/externalization/externalization/tests/test_externalizer.py b/src/nti/externalization/externalization/tests/test_externalizer.py
index 169ef14..cb77d5b 100644
--- a/src/nti/externalization/externalization/tests/test_externalizer.py
+++ b/src/nti/externalization/externalization/tests/test_externalizer.py
@@ -1,9 +1,5 @@
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
@@ -11,12 +7,13 @@
from zope.proxy import ProxyBase
+from nti.externalization.externalization import to_external_object
+
from hamcrest import assert_that
from hamcrest import has_length
from hamcrest import is_
from hamcrest import same_instance
-from nti.externalization.externalization import to_external_object
from ..externalizer import _obj_has_usable_externalObject
@@ -70,6 +67,7 @@ def __conform__(self, iface): # pylint:disable=bad-dunder-name
def test_uses_directly_provided(self):
from zope import interface
+
from nti.externalization.interfaces import IInternalObjectExternalizer
class Obj(object):
diff --git a/src/nti/externalization/factory.py b/src/nti/externalization/factory.py
index 5f3cad1..8cacb08 100644
--- a/src/nti/externalization/factory.py
+++ b/src/nti/externalization/factory.py
@@ -5,16 +5,16 @@
.. versionadded:: 1.0
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+
+from collections.abc import Callable
+from typing import Any
from zope import interface
from zope.component.factory import Factory
+from nti.externalization.interfaces import IAnonymousObjectFactory
from nti.externalization.interfaces import IClassObjectFactory
from nti.externalization.interfaces import IMimeObjectFactory
-from nti.externalization.interfaces import IAnonymousObjectFactory
_builtin_callable = callable
@@ -60,7 +60,7 @@ class properties :attr:`default_factory` and (optionally)
#: The default callable argument, if none is given to the
#: constructor.
- default_factory = None
+ default_factory: Callable[[Any], Any]|None = None
#: The default title, if none is given to the constructor.
default_title = ''
#: The default description, if none is given to the constructor.
diff --git a/src/nti/externalization/integer_strings.py b/src/nti/externalization/integer_strings.py
index 7b58042..00852e1 100644
--- a/src/nti/externalization/integer_strings.py
+++ b/src/nti/externalization/integer_strings.py
@@ -23,9 +23,6 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
__all__ = [
'to_external_string',
@@ -35,11 +32,7 @@
# stdlib imports
import string
-try:
- maketrans = str.maketrans
-except AttributeError: # Python 2
- from string import maketrans # pylint:disable=no-name-in-module
-
+maketrans = str.maketrans
translate = str.translate
# In the first version of the protocol, the version marker, which would
@@ -65,7 +58,7 @@
_ZERO_MARKER = '@' # Zero is special
-def from_external_string(key):
+def from_external_string(key) -> int:
"""
Turn the string in *key* into an integer.
@@ -104,7 +97,7 @@ def from_external_string(key):
return int_sum
-def to_external_string(integer):
+def to_external_string(integer) -> str:
"""
Turn an integer into a native string representation.
diff --git a/src/nti/externalization/interfaces.py b/src/nti/externalization/interfaces.py
index 04307e3..46c6dbc 100644
--- a/src/nti/externalization/interfaces.py
+++ b/src/nti/externalization/interfaces.py
@@ -5,34 +5,31 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+from typing import Any
+import zope.interface.common.builtins as ibuiltins
from zope import interface
-
from zope.component.interfaces import IFactory
from zope.deprecation import deprecated
from zope.interface.common import collections as icollections
-from zope.interface.common import sequence as legacy_isequence
from zope.interface.common import mapping as legacy_imapping
-import zope.interface.common.builtins as ibuiltins
+from zope.interface.common import sequence as legacy_isequence
from zope.interface.interfaces import IObjectEvent
from zope.interface.interfaces import ObjectEvent
from zope.lifecycleevent import IObjectModifiedEvent
from zope.lifecycleevent import ObjectModifiedEvent
from zope.location import ILocation
+from ._base_interfaces import MINIMAL_SYNTHETIC_EXTERNAL_KEYS
+from ._base_interfaces import ExternalizationPolicy
+from ._base_interfaces import LocatedExternalDict
+from ._base_interfaces import get_default_externalization_policy
+from ._base_interfaces import get_standard_external_fields
+from ._base_interfaces import get_standard_internal_fields
# pylint:disable=inherit-non-class,no-method-argument,no-self-argument
# pylint:disable=too-many-ancestors
-from ._base_interfaces import LocatedExternalDict
-from ._base_interfaces import get_standard_external_fields
-from ._base_interfaces import get_standard_internal_fields
-from ._base_interfaces import MINIMAL_SYNTHETIC_EXTERNAL_KEYS
-from ._base_interfaces import ExternalizationPolicy
-from ._base_interfaces import get_default_externalization_policy
StandardExternalFields = get_standard_external_fields()
StandardInternalFields = get_standard_internal_fields()
@@ -457,7 +454,7 @@ class ObjectModifiedFromExternalEvent(ObjectModifiedEvent):
Default implementation of `IObjectModifiedFromExternalEvent`.
"""
- kwargs = None
+ kwargs:dict[str,Any]|None = None
external_value = None
def __init__(self, obj, *descriptions, **kwargs):
diff --git a/src/nti/externalization/internalization/__init__.py b/src/nti/externalization/internalization/__init__.py
index 1ea7469..0d873ad 100644
--- a/src/nti/externalization/internalization/__init__.py
+++ b/src/nti/externalization/internalization/__init__.py
@@ -5,10 +5,6 @@
model objects.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import warnings
from zope.interface.interfaces import ComponentLookupError
diff --git a/src/nti/externalization/internalization/_externals.pxd b/src/nti/externalization/internalization/_externals.pxd
index c7f88b0..b96868d 100644
--- a/src/nti/externalization/internalization/_externals.pxd
+++ b/src/nti/externalization/internalization/_externals.pxd
@@ -3,9 +3,9 @@ import cython
# imports
-cdef MutableSequenc
-cdef component
cdef IExternalReferenceResolver
+cdef MutableSequence
+cdef component
# XXX: This is only public for testing
cpdef resolve_externals(object_io, updating_object, externalObject,
diff --git a/src/nti/externalization/internalization/_factories.pxd b/src/nti/externalization/internalization/_factories.pxd
index 3944c21..1004425 100644
--- a/src/nti/externalization/internalization/_factories.pxd
+++ b/src/nti/externalization/internalization/_factories.pxd
@@ -33,8 +33,8 @@ cdef class _DefaultExternalizedObjectFactoryFinder(object):
cdef _search_for_class_factory(externalized_object, class_name)
cdef _search_for_mime_factory(externalized_object, mime_type)
-cpdef find_factory_for_class_name(class_name)
+cpdef find_factory_for_class_name(str class_name)
cdef _find_factory_for_mime_or_class(externalized_object)
-cpdef find_factory_for(externalized_object, registry=*)
+cpdef find_factory_for(externalized_object)
diff --git a/src/nti/externalization/internalization/_fields.pxd b/src/nti/externalization/internalization/_fields.pxd
index 50d7283..969b273 100644
--- a/src/nti/externalization/internalization/_fields.pxd
+++ b/src/nti/externalization/internalization/_fields.pxd
@@ -58,12 +58,10 @@ cdef _handle_SchemaNotProvided(field_name, field, value)
cdef _handle_WrongType(field_name, field, value)
cdef _handle_WrongContainedType(field_name, field, value)
-cdef str _as_native_str(s)
-
cdef tuple _CONVERTERS
@cython.locals(
meth_name_kind=tuple,
)
-cpdef validate_field_value(self, field_name, field, value)
-cpdef validate_named_field_value(self, iface, field_name, value)
+cpdef validate_field_value(self, str field_name, field, value)
+cpdef validate_named_field_value(self, iface, str field_name, value)
diff --git a/src/nti/externalization/internalization/_legacy_factories.pxd b/src/nti/externalization/internalization/_legacy_factories.pxd
index 222147d..b3675b5 100644
--- a/src/nti/externalization/internalization/_legacy_factories.pxd
+++ b/src/nti/externalization/internalization/_legacy_factories.pxd
@@ -22,7 +22,7 @@ cpdef list find_factories_in_module(module, case_sensitive=*)
# private
cdef set _ext_factory_warnings
-cpdef search_for_external_factory(class_name)
+cpdef search_for_external_factory(str class_name)
cdef register_factories_from_search_set()
cdef register_factories_from_module(module)
diff --git a/src/nti/externalization/internalization/_updater.pxd b/src/nti/externalization/internalization/_updater.pxd
index 3fabacc..24baba4 100644
--- a/src/nti/externalization/internalization/_updater.pxd
+++ b/src/nti/externalization/internalization/_updater.pxd
@@ -38,7 +38,6 @@ cdef dict _EMPTY_DICT
@cython.freelist(1000)
cdef class _RecallArgs(object):
cdef context
- cdef pre_hook
cdef root
cdef bint require_updater
cdef bint notify
@@ -61,20 +60,23 @@ cdef _update_sequence(externalObject, _RecallArgs args,
cpdef _find_INamedExternalizedObjectFactoryFinder(containedObject)
cdef _update_from_external_object(containedObject, externalObject, _RecallArgs args)
-cpdef update_from_external_object(containedObject,
- externalObject,
- registry=*,
- context=*,
- bint require_updater=*,
- bint notify=*,
- pre_hook=*)
+# The use of @overload prevents this from being
+# cpdef, unfortunately. Cython tries to generate the
+# function multiple times.
+# cpdef update_from_external_object(containedObject,
+# externalObject,
+# registry=*,
+# context=*,
+# bint require_updater=*,
+# bint notify=*,
+# )
-cdef dict _argspec_cacheg
+cdef dict _argspec_cache
cdef str _UPDATE_ARGS_TWO
cdef str _UPDATE_ARGS_ONE
cdef str _UPDATE_ARGS_CONTEXT_KW
cdef inline _get_update_signature(updater)
-cdef dict _upsable_updateFromExternalObject_cache
+cdef dict _usable_updateFromExternalObject_cache
cdef _obj_has_usable_updateFromExternalObject(obj)
diff --git a/src/nti/externalization/internalization/events.py b/src/nti/externalization/internalization/events.py
index 2ffa245..17a7046 100644
--- a/src/nti/externalization/internalization/events.py
+++ b/src/nti/externalization/internalization/events.py
@@ -5,21 +5,18 @@
"""
+from collections.abc import Collection
+from collections.abc import Sequence
+from typing import Any
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
+from zope.event import notify as _zope_event_notify
from zope.interface import classImplements
from zope.interface import providedBy
-from zope.event import notify as _zope_event_notify
from zope.lifecycleevent import IAttributes
-from nti.externalization.interfaces import ObjectModifiedFromExternalEvent
from nti.externalization._interface_cache import cache_for_key_in_providedBy
+from nti.externalization.interfaces import ObjectModifiedFromExternalEvent
-logger = __import__('logging').getLogger(__name__)
__all__ = [
'notifyModified',
@@ -42,7 +39,8 @@ def __init__(self, iface):
classImplements(_Attributes, IAttributes)
-def _make_modified_attributes(containedObject, external_keys):
+def _make_modified_attributes(containedObject,
+ external_keys:Sequence[str]) -> Collection[_Attributes]:
# Returns a sequence of fresh _Attributes objects,
# one for each distinct interface (including None) that declared
# any key found in *external_keys*.
@@ -61,7 +59,7 @@ def _make_modified_attributes(containedObject, external_keys):
# {iface -> _Attributes(iface)}. Note that iface will be None if there
# is no interface that defined the key.
- result = {}
+ result: dict[Any, _Attributes]= {}
provides_get = provides.get
@@ -158,5 +156,7 @@ def notifyModified(containedObject, externalObject, updater=None, external_keys=
kwargs)
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import \
+ import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+
import_c_accel(globals(), 'nti.externalization.internalization._events')
diff --git a/src/nti/externalization/internalization/externals.py b/src/nti/externalization/internalization/externals.py
index dbf8d81..6bdeaaf 100644
--- a/src/nti/externalization/internalization/externals.py
+++ b/src/nti/externalization/internalization/externals.py
@@ -5,28 +5,13 @@
objects.
"""
-
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-# stdlib imports
-try:
- from collections.abc import MutableSequence
-except ImportError: # Python 2
- # pylint:disable=deprecated-class
- from collections import MutableSequence
+from collections.abc import MutableSequence
from zope import component
-
from nti.externalization.interfaces import IExternalReferenceResolver
-
__all__ = [
'resolve_externals',
]
@@ -81,5 +66,5 @@ def resolve_externals(object_io, updating_object, externalObject,
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import import_c_accel
import_c_accel(globals(), 'nti.externalization.internalization._externals')
diff --git a/src/nti/externalization/internalization/factories.py b/src/nti/externalization/internalization/factories.py
index 8573b66..c55fc03 100644
--- a/src/nti/externalization/internalization/factories.py
+++ b/src/nti/externalization/internalization/factories.py
@@ -11,32 +11,25 @@
# There are a *lot* of fixme (XXX and the like) in this file.
# Turn those off in general so we can see through the noise.
# pylint:disable=fixme
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import warnings
+import logging
+from collections.abc import Callable
from zope import component
from zope import interface
-from nti.externalization._base_interfaces import NotGiven
from nti.externalization.interfaces import IClassObjectFactory
from nti.externalization.interfaces import IExternalizedObjectFactoryFinder
from nti.externalization.interfaces import IFactory
from nti.externalization.interfaces import IMimeObjectFactory
-from .legacy_factories import search_for_external_factory
-
from .._base_interfaces import get_standard_external_fields
-
+from .legacy_factories import search_for_external_factory
StandardExternalFields = get_standard_external_fields()
component_queryAdapter = component.queryAdapter
component_queryUtility = component.queryUtility
-logger = __import__('logging').getLogger(__name__)
+logger = logging.getLogger(__name__)
__all__ = [
'default_externalized_object_factory_finder',
@@ -131,7 +124,7 @@ def default_externalized_object_factory_finder_factory(unused_externalized_objec
return default_externalized_object_factory_finder
-def find_factory_for_class_name(class_name):
+def find_factory_for_class_name(class_name:str) -> Callable|None:
factory = component_queryUtility(IClassObjectFactory, class_name)
if factory is None:
factory = search_for_external_factory(class_name)
@@ -141,7 +134,7 @@ def find_factory_for_class_name(class_name):
return factory
-def find_factory_for(externalized_object, registry=NotGiven):
+def find_factory_for(externalized_object) -> Callable|None:
"""
find_factory_for(externalized_object) -> factory
@@ -163,17 +156,16 @@ def find_factory_for(externalized_object, registry=NotGiven):
.. versionchanged:: 1.0a10
The ``registry`` argument is deprecated and ignored.
+
+ .. versionchanged:: NEXT
+ Remove the registry argument.
"""
- if registry is not NotGiven: # pragma: no cover
- warnings.warn(
- "The registry argument is deprecated and ignored",
- FutureWarning
- )
factory_finder = IExternalizedObjectFactoryFinder(externalized_object, None)
if factory_finder is not None:
- return factory_finder.find_factory(externalized_object) # pylint:disable=too-many-function-args
+ # pylint:disable-next=too-many-function-args
+ return factory_finder.find_factory(externalized_object) # type:ignore[call-arg,misc]
# We do it this way instead of using
# ``default_externalized_object_factory_finder`` as the default in
@@ -181,5 +173,7 @@ def find_factory_for(externalized_object, registry=NotGiven):
return _find_factory_for_mime_or_class(externalized_object)
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import \
+ import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+
import_c_accel(globals(), 'nti.externalization.internalization._factories')
diff --git a/src/nti/externalization/internalization/fields.py b/src/nti/externalization/internalization/fields.py
index 5229088..7b83b7b 100644
--- a/src/nti/externalization/internalization/fields.py
+++ b/src/nti/externalization/internalization/fields.py
@@ -6,31 +6,24 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+from collections.abc import Callable
# pylint:disable=protected-access
-
# stdlib imports
from sys import exc_info as get_exc_info
-
+from zope.event import notify
from zope.interface import implementedBy
-
+from zope.schema.fieldproperty import NO_VALUE
+from zope.schema.fieldproperty import FieldProperty
+from zope.schema.fieldproperty import FieldUpdatedEvent
from zope.schema.interfaces import IField
-from zope.schema.interfaces import SchemaNotProvided
from zope.schema.interfaces import SchemaNotCorrectlyImplemented
+from zope.schema.interfaces import SchemaNotProvided
from zope.schema.interfaces import ValidationError
from zope.schema.interfaces import WrongContainedType
from zope.schema.interfaces import WrongType
-from zope.schema.fieldproperty import FieldProperty
-from zope.schema.fieldproperty import NO_VALUE
-from zope.schema.fieldproperty import FieldUpdatedEvent
-
-from zope.event import notify
-
IField_providedBy = IField.providedBy
__all__ = [
@@ -116,13 +109,13 @@ def _FieldProperty__set__valid(self, inst, value):
else:
_FieldProperty_orig_set(self, inst, value)
-_FieldProperty__set__valid.orig_func = _FieldProperty_orig_set
+_FieldProperty__set__valid.orig_func = _FieldProperty_orig_set # type:ignore[attr-defined]
# Detect the case that we're in Cython compiled code, where
# we've already replaced the __set__ function with our own.
if FieldProperty.__set__.__name__ == _FieldProperty__set__valid.__name__: # pragma: no cover
_FieldProperty_orig_set = FieldProperty.__set__.orig_func # pylint:disable=no-member
- _FieldProperty__set__valid.org_func = _FieldProperty_orig_set
+ _FieldProperty__set__valid.orig_func = _FieldProperty_orig_set # type:ignore[attr-defined]
FieldProperty.__set__ = _FieldProperty__set__valid
@@ -134,7 +127,7 @@ class CannotConvertSequenceError(TypeError):
but we don't know how.
"""
-def _adapt_sequence(field, value):
+def _adapt_sequence(field, value) -> list:
# IObject provides `schema`, which is an interface, so we can adapt
# using it. Some other things do not, for example nti.schema.field.Variant
# They might provide a `fromObject` function to do the conversion
@@ -174,7 +167,7 @@ def _handle_SchemaNotProvided(field_name, field, value): # pylint:disable=unused
# The object doesn't implement the required interface.
# Can we adapt the provided object to the desired interface?
# First, capture the details so we can reraise if needed
- exc_info = get_exc_info()
+ exc_type, exc_val, _exc_tb = get_exc_info()
try:
value = field.schema(value)
@@ -183,24 +176,25 @@ def _handle_SchemaNotProvided(field_name, field, value): # pylint:disable=unused
# Nope. TypeError (or AttrError - Variant) means we couldn't adapt,
# and a validation error means we could adapt, but it still wasn't
# right. Raise the original SchemaValidationError.
- raise exc_info[1] if exc_info[1] is not None else exc_info[0]() from None
+ raise exc_val if exc_val is not None else exc_type() from None # type:ignore[misc]
return value
def _handle_WrongType(field_name, field, value): # pylint:disable=unused-argument
# Like SchemaNotProvided, but for a primitive type,
# most commonly a date
# Can we adapt?
- exc_info = get_exc_info()
+ _exc_type, exc_value, _exc_tb = get_exc_info()
+ assert isinstance(exc_value, WrongType)
- if not exc_info[1].expected_type: # pragma: no cover
- raise exc_info[1]
+ if not exc_value.expected_type: # pragma: no cover
+ raise exc_value
- exp_type = exc_info[1].expected_type
+ exp_type = exc_value.expected_type
implemented_by_type = list(implementedBy(exp_type))
# If the type unambiguously implements an interface (one interface)
# that's our target. IDate does this
if len(implemented_by_type) != 1: # pragma: no cover
- raise exc_info[1]
+ raise exc_value
schema = implemented_by_type[0]
@@ -209,7 +203,7 @@ def _handle_WrongType(field_name, field, value): # pylint:disable=unused-argumen
result = schema(value)
except (LookupError, TypeError):
# No registered adapter, darn
- raise exc_info[1] if exc_info[1] is not None else exc_info[0]() from None
+ raise exc_value from None
except ValidationError as e:
# Found an adapter, but it does its own validation,
# and that validation failed (eg, IDate below)
@@ -226,10 +220,11 @@ def _handle_WrongContainedType(field_name, field, value): # pylint:disable=unuse
# types.
# Try to adapt each value to what the sequence wants, just as above,
# if the error is one that may be solved via simple adaptation
- exc_info = get_exc_info()
+ _exc_type, exc_val, _exc_tb = get_exc_info()
+ assert isinstance(exc_val, WrongContainedType)
- if not exc_info[1].errors or not _all_SchemaNotProvided(exc_info[1].errors):
- raise exc_info[1]
+ if not exc_val.errors or not _all_SchemaNotProvided(exc_val.errors):
+ raise exc_val
# IObject provides `schema`, which is an interface, so we can adapt
# using it. Some other things do not, for example nti.schema.field.Variant
@@ -244,7 +239,7 @@ def _handle_WrongContainedType(field_name, field, value): # pylint:disable=unuse
# to raise the original error. If we could adapt,
# but the converter does its own validation (e.g., fromObject)
# then we want to let that validation error rise
- raise exc_info[1] from None
+ raise exc_val from None
# Now try to validate the converted value
try:
@@ -253,7 +248,7 @@ def _handle_WrongContainedType(field_name, field, value): # pylint:disable=unuse
# Nope. TypeError means we couldn't adapt, and a
# validation error means we could adapt, but it still wasn't
# right. Raise the original SchemaValidationError.
- raise exc_info[1] from None
+ raise exc_val from None
return value
@@ -263,7 +258,7 @@ def _handle_WrongContainedType(field_name, field, value): # pylint:disable=unuse
('fromObject', object)
)
-def validate_field_value(self, field_name, field, value):
+def validate_field_value(self, field_name:str, field, value) -> Callable[[], None]:
"""
Given a :class:`zope.schema.interfaces.IField` object from a schema
implemented by `self`, validates that the proposed value can be
@@ -312,7 +307,7 @@ def validate_field_value(self, field_name, field, value):
if value is not None:
# First time through we get to set it, but we must bypass
# the field
- _do_set = SetattrSet(self, _as_native_str(field_name), value)
+ _do_set = SetattrSet(self, field_name, value)
else:
_do_set = noop
else:
@@ -321,7 +316,7 @@ def validate_field_value(self, field_name, field, value):
return _do_set
-def validate_named_field_value(self, iface, field_name, value):
+def validate_named_field_value(self, iface, field_name:str, value):
"""
Given a :class:`zope.interface.Interface` and the name of one of its attributes,
validate that the given ``value`` is appropriate to set. See :func:`validate_field_value`
@@ -334,7 +329,6 @@ def validate_named_field_value(self, iface, field_name, value):
:return: A callable of no arguments to call to actually set the value.
"""
- field_name = _as_native_str(field_name)
field = iface[field_name]
if IField_providedBy(field): # pylint:disable=no-value-for-parameter
return validate_field_value(self, field_name, field, value)
@@ -342,11 +336,5 @@ def validate_named_field_value(self, iface, field_name, value):
return SetattrSet(self, field_name, value)
-def _as_native_str(s):
- if isinstance(s, str):
- return s
- return s.encode('ascii') # Python 2
-
-
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import import_c_accel
import_c_accel(globals(), 'nti.externalization.internalization._fields')
diff --git a/src/nti/externalization/internalization/legacy_factories.py b/src/nti/externalization/internalization/legacy_factories.py
index 7d7e568..56bf6ae 100644
--- a/src/nti/externalization/internalization/legacy_factories.py
+++ b/src/nti/externalization/internalization/legacy_factories.py
@@ -5,31 +5,24 @@
.. deprecated:: 1.0
"""
-## Implementation of legacy search modules.
-
-# We go through the global component registry, using a local
-# interface. We treat the registry as a cache and we will only
-# look at any given module object one time. We can detect duplicates
-# in this fashion. (For cython compilation, this lives in interfaces.)
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# stdlib imports
+import logging
import types
import warnings
from zope import component
-
from zope.dottedname.resolve import resolve
-from nti.externalization.interfaces import _ILegacySearchModuleFactory
from nti.externalization._base_interfaces import NotGiven
+from nti.externalization.interfaces import _ILegacySearchModuleFactory
+## Implementation of legacy search modules.
+# We go through the global component registry, using a local
+# interface. We treat the registry as a cache and we will only
+# look at any given module object one time. We can detect duplicates
+# in this fashion. (For cython compilation, this lives in interfaces.)
-logger = __import__('logging').getLogger(__name__)
+
+logger = logging.getLogger(__name__)
__all__ = [
'register_legacy_search_module',
@@ -38,10 +31,10 @@
#: .. deprecated:: 1.0
#: This is legacy functionality, please do not access directly.
#: The public interface is through :func:`register_legacy_search_module`
-LEGACY_FACTORY_SEARCH_MODULES = set()
+LEGACY_FACTORY_SEARCH_MODULES = set[str|types.ModuleType]()
try:
- from zope.testing.cleanup import addCleanUp # pylint: disable=ungrouped-imports
+ from zope.testing.cleanup import addCleanUp # pylint: disable=ungrouped-imports
except ImportError: # pragma: no cover
pass
else:
@@ -69,9 +62,9 @@ def register_legacy_search_module(module_name):
if module_name:
LEGACY_FACTORY_SEARCH_MODULES.add(module_name)
-_ext_factory_warnings = set()
+_ext_factory_warnings = set[str]()
-def search_for_external_factory(typeName):
+def search_for_external_factory(typeName:str):
"""
Deprecated, legacy functionality. Given the name of a type,
optionally ending in 's' for plural, attempt to locate that type.
@@ -201,4 +194,5 @@ def find_factories_in_module(module,
# pylint:disable=wrong-import-position,wrong-import-order
from nti.externalization._compat import import_c_accel
+
import_c_accel(globals(), 'nti.externalization.internalization._legacy_factories')
diff --git a/src/nti/externalization/internalization/tests/test_externals_wo_class_mimetype.py b/src/nti/externalization/internalization/tests/test_externals_wo_class_mimetype.py
index 16490e1..610e185 100644
--- a/src/nti/externalization/internalization/tests/test_externals_wo_class_mimetype.py
+++ b/src/nti/externalization/internalization/tests/test_externals_wo_class_mimetype.py
@@ -4,9 +4,6 @@
the conventions of this package, e.g., missing Class and MimeType values.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
@@ -14,26 +11,24 @@
import sys
import unittest
-from hamcrest import is_
-from hamcrest import assert_that
-from hamcrest import has_property as has_attr
-from hamcrest import has_length
-from hamcrest import contains_string
-
-from zope import interface
from zope import component
-
-from zope.schema import Object
+from zope import interface
+from zope.schema import Dict
from zope.schema import Int
from zope.schema import List
-from zope.schema import Dict
-
+from zope.schema import Object
from zope.testing.cleanup import CleanUp
from nti.externalization import interfaces
+from nti.externalization.datastructures import InterfaceObjectIO
from nti.externalization.internalization import update_from_external_object
from nti.externalization.internalization import updater
-from nti.externalization.datastructures import InterfaceObjectIO
+
+from hamcrest import assert_that
+from hamcrest import contains_string
+from hamcrest import has_length
+from hamcrest import has_property as has_attr
+from hamcrest import is_
class TestExternals(CleanUp,
diff --git a/src/nti/externalization/internalization/tests/test_fields.py b/src/nti/externalization/internalization/tests/test_fields.py
index c61a34d..c6cc122 100644
--- a/src/nti/externalization/internalization/tests/test_fields.py
+++ b/src/nti/externalization/internalization/tests/test_fields.py
@@ -1,31 +1,25 @@
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import unittest
from zope import interface
from zope.component import eventtesting
-
-
+from zope.schema import Object
+from zope.schema.fieldproperty import createFieldProperties
from zope.schema.interfaces import IBeforeObjectAssignedEvent
from zope.schema.interfaces import IFieldUpdatedEvent
from zope.schema.interfaces import SchemaNotProvided
-from zope.schema import Object
-from zope.schema.fieldproperty import createFieldProperties
-
from zope.testing.cleanup import CleanUp
+from nti.externalization.internalization.fields import validate_field_value
+from nti.externalization.internalization.fields import validate_named_field_value
+
from hamcrest import assert_that
from hamcrest import has_length
from hamcrest import has_property as has_attr
from hamcrest import is_
from hamcrest import same_instance
-from nti.externalization.internalization.fields import validate_named_field_value
-from nti.externalization.internalization.fields import validate_field_value
-
# pylint:disable=inherit-non-class,blacklisted-name
class IThing(interface.Interface):
@@ -127,8 +121,8 @@ class Foo(object):
assert_that(foo, has_attr('field', 'text'))
def test_from_bytes(self):
- from zope.schema.interfaces import IFromBytes
from zope.schema import Field
+ from zope.schema.interfaces import IFromBytes
@interface.implementer(IFromBytes)
class OnlyBytes(Field):
_type = bytes
@@ -148,8 +142,8 @@ class Foo(object):
def test_raises_SchemaNotCorrectlyImplemented(self):
- from zope.schema.interfaces import SchemaNotCorrectlyImplemented
from zope.schema import TextLine
+ from zope.schema.interfaces import SchemaNotCorrectlyImplemented
class IFoo(interface.Interface):
field = TextLine(title='text', required=True)
diff --git a/src/nti/externalization/internalization/tests/test_updater.py b/src/nti/externalization/internalization/tests/test_updater.py
index ae84070..8f856c0 100644
--- a/src/nti/externalization/internalization/tests/test_updater.py
+++ b/src/nti/externalization/internalization/tests/test_updater.py
@@ -3,30 +3,25 @@
Tests for updater.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
import unittest
-from zope import interface
from zope import component
-
+from zope import interface
from zope.testing.cleanup import CleanUp
+from nti.externalization import interfaces
+from nti.externalization.internalization import updater
+
from hamcrest import assert_that
-from hamcrest import has_property
from hamcrest import has_length
+from hamcrest import has_property
from hamcrest import is_
from hamcrest import same_instance
-from nti.externalization import interfaces
-
-from nti.externalization.internalization import updater
class CreateCount(object):
created = 0
diff --git a/src/nti/externalization/internalization/updater.py b/src/nti/externalization/internalization/updater.py
index 244c221..21d053d 100644
--- a/src/nti/externalization/internalization/updater.py
+++ b/src/nti/externalization/internalization/updater.py
@@ -5,40 +5,37 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-# stdlib imports
-from collections.abc import MutableSequence
-from collections.abc import MutableMapping
import inspect
import warnings
+from collections.abc import MutableMapping
+from collections.abc import MutableSequence
+from typing import TypeVar
+from typing import overload
from zope import interface
+
try:
from persistent.interfaces import IPersistent
except ModuleNotFoundError:
- class IPersistent(interface.Interface): # pylint: disable=inherit-non-class
+ # pylint: disable-next=inherit-non-class
+ class IPersistent(interface.Interface): # type:ignore[no-redef]
"""Mock"""
from zope.event import notify as notify_event
from nti.externalization._base_interfaces import PRIMITIVES
-from nti.externalization._base_interfaces import NotGiven
-from nti.externalization.interfaces import IInternalObjectUpdater
from nti.externalization.interfaces import IInternalObjectIO
+from nti.externalization.interfaces import IInternalObjectUpdater
from nti.externalization.interfaces import INamedExternalizedObjectFactoryFinder
from nti.externalization.interfaces import ObjectWillUpdateFromExternalEvent
-from .factories import find_factory_for
from .events import _notifyModified
from .externals import resolve_externals
+from .factories import find_factory_for
+T = TypeVar('T')
-
-_EMPTY_DICT = {}
+_EMPTY_DICT: dict = {}
IPersistent_providedBy = IPersistent.providedBy
@@ -47,7 +44,6 @@ class _RecallArgs(object):
'context',
'require_updater',
'notify',
- 'pre_hook',
'root',
)
@@ -59,7 +55,6 @@ def __init__(self):
self.context = None
self.require_updater = False
self.notify = True
- self.pre_hook = None
self.root = None
##
@@ -74,7 +69,7 @@ def __init__(self):
# cumbersome and needs to go; we are in the deprecation period now.
# See https://github.com/NextThought/nti.externalization/issues/30
-_argspec_cache = {}
+_argspec_cache: dict[type, str] = {}
# update(ext, context) or update(ext, context=None) or update(ext, dataserver)
# exactly two arguments. It doesn't matter what the name is, we'll call it
@@ -84,7 +79,7 @@ def __init__(self):
_UPDATE_ARGS_ONE = "update args external only"
-def _get_update_signature(updater):
+def _get_update_signature(updater) -> str:
kind = type(updater)
spec = _argspec_cache.get(kind)
@@ -132,9 +127,9 @@ def _get_update_signature(updater):
return spec
-_usable_updateFromExternalObject_cache = {}
+_usable_updateFromExternalObject_cache: dict[type, bool] = {}
-def _obj_has_usable_updateFromExternalObject(obj):
+def _obj_has_usable_updateFromExternalObject(obj) -> bool:
kind = type(obj)
usable_from = _usable_updateFromExternalObject_cache.get(kind)
@@ -157,7 +152,7 @@ def _obj_has_usable_updateFromExternalObject(obj):
try:
- from zope.testing import cleanup # pylint:disable=ungrouped-imports
+ from zope.testing import cleanup # pylint:disable=ungrouped-imports
except ImportError: # pragma: no cover
pass
else:
@@ -175,12 +170,31 @@ def find_factory_for_named_value(self, name, value): # pylint:disable=unused-arg
_default_factory_finder = DefaultInternalObjectFactoryFinder()
-def update_from_external_object(containedObject, externalObject,
- registry=NotGiven, context=None,
+@overload
+def update_from_external_object(containedObject: MutableSequence,
+ externalObject: MutableSequence,
+ context=None,
require_updater=False,
- notify=True,
- pre_hook=None):
- # pylint:disable=line-too-long, too-many-positional-arguments
+ notify=True) -> MutableSequence:
+ # pylint:disable=too-many-positional-arguments
+ ...
+
+@overload
+def update_from_external_object(containedObject: T,
+ externalObject: MutableMapping,
+ context=None,
+ require_updater=False,
+ notify=True) -> T:
+ # pylint:disable=too-many-positional-arguments
+ ...
+
+def update_from_external_object(containedObject: T|MutableSequence,
+ externalObject: MutableSequence|MutableMapping,
+ context=None,
+ require_updater=False,
+ notify=True) -> T|MutableSequence:
+ # pylint:disable=line-too-long
+ # pylint:disable=too-many-positional-arguments
"""
update_from_external_object(containedObject, externalObject, context=None, require_updater=False, notify=True)
@@ -208,11 +222,6 @@ def update_from_external_object(containedObject, externalObject,
attribute; if this is the case and we can also find an
interface declaring the attribute, then the ``IAttributes``
will have the right value for ``interface`` as well).
- :keyword callable pre_hook: If given, called with the before
- update_from_external_object is called for every nested object.
- Signature ``f(k,x)`` where ``k`` is either the key name, or
- None in the case of a sequence and ``x`` is the external
- object. Deprecated.
:return: *containedObject* after updates from *externalObject*
Notifies `~.IObjectModifiedFromExternalEvent` for each object that is modified,
@@ -223,25 +232,17 @@ def update_from_external_object(containedObject, externalObject,
.. versionchanged:: 1.0.0a2
Remove the ``object_hook`` parameter.
.. versionchanged:: 1.1.3
- Correctly file `~.IObjectWillUpdateFromExternalEvent` before updating
+ Correctly fire `~.IObjectWillUpdateFromExternalEvent` before updating
each object.
+ .. versionchanged:: NEXT
+ Remove the long-deprecated 'pre_hook' parameter. Remove the long-deprecated
+ 'registry' parameter.
"""
- if pre_hook is not None: # pragma: no cover
- for i in range(3):
- warnings.warn('pre_hook is deprecated', FutureWarning, stacklevel=i)
-
- if registry is not NotGiven: # pragma: no cover
- warnings.warn(
- "registry is deprecated and ignored. Call in a correct site.",
- FutureWarning
- )
-
kwargs = _RecallArgs()
kwargs.context = context
kwargs.require_updater = require_updater
kwargs.notify = notify
- kwargs.pre_hook = pre_hook
kwargs.root = containedObject
return _update_from_external_object(containedObject, externalObject, kwargs)
@@ -255,13 +256,13 @@ def _invoke_factory(factory, value):
return factory()
def _update_sequence(
- externalObject, args,
+ externalObject: MutableSequence,
+ args: _RecallArgs,
destination_name=None,
- find_factory_for_named_value=_default_factory_finder.find_factory_for_named_value):
+ find_factory_for_named_value=_default_factory_finder.find_factory_for_named_value
+) -> MutableSequence:
for index, value in enumerate(externalObject):
- if args.pre_hook is not None: # pragma: no cover
- args.pre_hook(None, value)
factory = find_factory_for_named_value(destination_name, value)
if factory is not None:
new_obj = _invoke_factory(factory, value)
@@ -319,7 +320,9 @@ def _find_INamedExternalizedObjectFactoryFinder(containedObject):
return updater
-def _update_from_external_object(containedObject, externalObject, args):
+def _update_from_external_object(containedObject: T,
+ externalObject: MutableSequence|MutableMapping,
+ args: _RecallArgs) -> T|MutableSequence:
# Parse any contained objects
# TODO: We're (deliberately?) not actually updating any contained
@@ -331,7 +334,7 @@ def _update_from_external_object(containedObject, externalObject, args):
if IPersistent_providedBy(containedObject): # pylint:disable=no-value-for-parameter
# pylint:disable=protected-access
- containedObject._v_updated_from_external_source = externalObject
+ containedObject._v_updated_from_external_source = externalObject # type:ignore[attr-defined]
# Sequences do not represent python types, they represent collections of
@@ -353,9 +356,6 @@ def _update_from_external_object(containedObject, externalObject, args):
if isinstance(v, PRIMITIVES):
continue
- if args.pre_hook is not None: # pragma: no cover
- args.pre_hook(k, v)
-
if isinstance(v, MutableSequence):
# Update the sequence in-place
_update_sequence(v, args, k, find_factory_for_named_value)
@@ -390,5 +390,5 @@ def _update_from_external_object(containedObject, externalObject, args):
-from nti.externalization._compat import import_c_accel # pylint:disable=wrong-import-position,wrong-import-order
+from nti.externalization._compat import import_c_accel
import_c_accel(globals(), 'nti.externalization.internalization._updater')
diff --git a/src/nti/externalization/numbers.py b/src/nti/externalization/numbers.py
index e58126f..8e0f9bd 100644
--- a/src/nti/externalization/numbers.py
+++ b/src/nti/externalization/numbers.py
@@ -3,10 +3,6 @@
Support for externalizing arbitrary numbers.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import fractions
import decimal
diff --git a/src/nti/externalization/oids.py b/src/nti/externalization/oids.py
index 688cbcc..1cfed23 100644
--- a/src/nti/externalization/oids.py
+++ b/src/nti/externalization/oids.py
@@ -4,13 +4,10 @@
Functions for finding and parsing OIDs.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
import binascii
import collections
+from collections.abc import Sequence
try:
from ZODB.interfaces import IConnection
@@ -23,11 +20,11 @@ def IConnection(_):
from zope.intid.interfaces import IIntIds
except ModuleNotFoundError:
from zope.interface import Interface
- class IIntIds(Interface): # pylint: disable=inherit-non-class
+ # pylint: disable-next=inherit-non-class
+ class IIntIds(Interface): # type:ignore[no-redef]
"""Mock"""
from nti.externalization._compat import bytes_
-
from nti.externalization.integer_strings import from_external_string
from nti.externalization.integer_strings import to_external_string
from nti.externalization.proxy import removeAllProxies
@@ -121,8 +118,9 @@ def to_external_oid(self, default=None, add_to_connection=False,
pass
if jar:
- db_name = jar.db().database_name
+ db_name:str = jar.db().database_name
oid = oid + b':' + binascii.hexlify(bytes_(db_name))
+
intutility = component.queryUtility(IIntIds)
if intutility is not None:
intid = intutility.queryId(self)
@@ -175,7 +173,7 @@ def from_external_oid(ext_oid):
return ParsedOID(ext_oid, '', None)
ext_oid = ext_oid.encode("ascii") if not isinstance(ext_oid, bytes) else ext_oid
- parts = ext_oid.split(b':') if b':' in ext_oid else (ext_oid,)
+ parts:Sequence[bytes] = ext_oid.split(b':') if b':' in ext_oid else (ext_oid,)
oid_string = parts[0]
name_s = parts[1] if len(parts) > 1 else b""
intid_s = parts[2] if len(parts) > 2 else None
diff --git a/src/nti/externalization/persistence.py b/src/nti/externalization/persistence.py
index a74ea76..ce44def 100644
--- a/src/nti/externalization/persistence.py
+++ b/src/nti/externalization/persistence.py
@@ -12,10 +12,6 @@
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
from collections.abc import Sequence
izip = zip
@@ -33,12 +29,12 @@
assert ex.name == 'persistent'
UPTODATE = None
CHANGED = 'Fake Changed'
- class Persistent:
+ class Persistent: # type:ignore[no-redef]
"""Mock"""
PersistentList = list
PersistentMapping = dict
from weakref import ref
- class PWeakRef(ref):
+ class PWeakRef(ref): # type:ignore[no-redef]
__slots__ = ()
from zope import interface
@@ -231,7 +227,7 @@ def __mul__(self, n):
return self.__class__(plain)
- __hash__ = None
+ __hash__ = None # type:ignore[assignment]
def __wrap(self, obj):
return obj if isinstance(obj, PWeakRef) else PWeakRef(obj)
diff --git a/src/nti/externalization/proxy.py b/src/nti/externalization/proxy.py
index bdb61ae..a5a1b28 100644
--- a/src/nti/externalization/proxy.py
+++ b/src/nti/externalization/proxy.py
@@ -11,9 +11,8 @@
It is extensible with `registerProxyUnwrapper`.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+from collections.abc import Callable
+from typing import Any
from zope.dottedname import resolve as dottedname
@@ -22,7 +21,7 @@
'registerProxyUnwrapper',
]
-_unwrappers = []
+_unwrappers: list[Callable[[Any], Any]] = []
def _init_unwrappers():
del _unwrappers[:]
diff --git a/src/nti/externalization/py.typed b/src/nti/externalization/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/src/nti/externalization/representation.py b/src/nti/externalization/representation.py
index de77958..3121da3 100644
--- a/src/nti/externalization/representation.py
+++ b/src/nti/externalization/representation.py
@@ -9,17 +9,17 @@
`YAML <.EXT_REPR_YAML>`.
"""
import decimal
-import warnings
+from typing import cast
try:
from persistent import Persistent
except ModuleNotFoundError:
- class Persistent:
+ class Persistent: # type:ignore[no-redef]
"""Mock"""
- class POSError(Exception):
+ class POSError(Exception): # type:ignore[no-redef]
"""Mock"""
else:
- from ZODB.POSException import POSError
+ from ZODB.POSException import POSError # type:ignore[no-redef]
import orjson
import yaml
from zope import component
@@ -51,7 +51,7 @@ def _to_external_representation(obj, io, name=_NotGiven,
return io.dump(ext, **repr_kwargs)
def to_external_representation(obj, ext_format=EXT_REPR_JSON,
- name=_NotGiven, registry=_NotGiven,
+ name=_NotGiven,
**repr_kwargs) -> str|bytes:
"""
to_external_representation(obj, ext_format='json', name=NotGiven, **repr_kwargs) -> str|bytes
@@ -72,12 +72,10 @@ def to_external_representation(obj, ext_format=EXT_REPR_JSON,
.. versionchanged:: 3.0.0
Added *repr_kwargs*
+ .. versionchanged:: NEXT
+ Removed the deprecated 'registry' param
"""
- if registry is not _NotGiven: # pragma: no cover
- warnings.warn(
- "The registry argument is ignored. Call in a correct site.",
- FutureWarning
- )
+
# It would seem nice to be able to do this in one step during
# the externalization process itself, but we would wind up traversing
# parts of the datastructure more than necessary. Here we traverse
@@ -95,7 +93,7 @@ def to_json_representation(obj) -> str:
A convenience function that calls
:func:`to_external_representation` with `.EXT_REPR_JSON`.
"""
- return to_external_representation(obj, EXT_REPR_JSON)
+ return cast(str, to_external_representation(obj, EXT_REPR_JSON))
def to_json_representation_fast(obj) -> bytes:
"""
@@ -111,8 +109,8 @@ def to_json_representation_fast(obj) -> bytes:
Now properly externalizes the object instead of relying on
the second-chance externalization mechanism.
"""
- return _to_external_representation(obj, JsonRepresenter,
- sort_keys=False, as_str=False)
+ return cast(bytes, _to_external_representation(obj, JsonRepresenter,
+ sort_keys=False, as_str=False))
def to_json_representation_sorted(obj) -> str:
"""
@@ -125,8 +123,8 @@ def to_json_representation_sorted(obj) -> str:
.. versionadded:: NEXT
"""
- return _to_external_representation(obj, JsonRepresenter,
- sort_keys=True)
+ return cast(str, _to_external_representation(obj, JsonRepresenter,
+ sort_keys=True))
# JSON
@@ -180,7 +178,7 @@ def dump(obj, fp=None, sort_keys=False, as_str=True, **_unused) -> str|bytes:
option=orjson.OPT_SORT_KEYS if sort_keys else 0,
default=_second_pass_to_external_object)
if as_str:
- result = result.decode('utf-8')
+ result = result.decode('utf-8') # type:ignore[assignment]
if fp:
return fp.write(result)
return result
@@ -212,11 +210,7 @@ class _ExtDumper(yaml.SafeDumper):
# requires an exact type match.
_ExtDumper.add_multi_representer(list, _ExtDumper.represent_list)
_ExtDumper.add_multi_representer(dict, _ExtDumper.represent_dict)
-if str is bytes: # Python 2
- # pylint:disable=undefined-variable,no-member
- _ExtDumper.add_multi_representer(unicode, _ExtDumper.represent_unicode)
-else: # Python 3
- _ExtDumper.add_multi_representer(str, _ExtDumper.represent_str)
+_ExtDumper.add_multi_representer(str, _ExtDumper.represent_str)
def _yaml_represent_decimal(dumper, data):
s = str(data)
@@ -241,7 +235,7 @@ def _yaml_represent_decimal(dumper, data):
def _yaml_represent_unknown(dumper, data):
ext_obj = _second_pass_to_external_object(data)
return dumper.represent_data(ext_obj)
-_ExtDumper.add_multi_representer(None, _yaml_represent_unknown)
+_ExtDumper.add_multi_representer(None, _yaml_represent_unknown) # type:ignore[arg-type]
diff --git a/src/nti/externalization/singleton.py b/src/nti/externalization/singleton.py
index db559bb..f59739a 100644
--- a/src/nti/externalization/singleton.py
+++ b/src/nti/externalization/singleton.py
@@ -21,10 +21,6 @@
a constant object.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# This was originally based on code from sympy.core.singleton
__all__ = [
@@ -82,6 +78,8 @@ class is instantiated.
False
"""
+ _new_instance: staticmethod
+
def __new__(mcs, name, bases, cls_dict): # pylint:disable=bad-mcs-classmethod-argument
cls_dict['__slots__'] = () # no ivars
cls_dict['__init__'] = lambda *args: None
@@ -98,7 +96,7 @@ def __new__(mcs, name, bases, cls_dict): # pylint:disable=bad-mcs-classmethod-ar
ctor = cls.__new__
cls._new_instance = staticmethod(ctor)
- the_instance = ctor(cls)
+ the_instance = ctor(cls) # type: ignore[call-arg,arg-type]
cls.__new__ = staticmethod(lambda *args: the_instance)
@@ -106,15 +104,14 @@ def __new__(mcs, name, bases, cls_dict): # pylint:disable=bad-mcs-classmethod-ar
SingletonDecorator = SingletonMetaclass # BWC
-Singleton = SingletonMetaclass(
- 'Singleton', (object,),
- {
- '__doc__':
- "A base class for singletons. "
- "Can be more convenient than a metaclass for Python2/Python3 compatibility."
- }
-)
+class Singleton(metaclass=SingletonMetaclass):
+ """
+ A base class for singletons.
+
+ Can be more convenient than using the metaclass.
+ """
+
from nti.externalization._compat import import_c_accel
import_c_accel(globals(), 'nti.externalization._singleton')
diff --git a/src/nti/externalization/testing.py b/src/nti/externalization/testing.py
index 65aaaad..5232796 100644
--- a/src/nti/externalization/testing.py
+++ b/src/nti/externalization/testing.py
@@ -3,10 +3,6 @@
Support for testing code.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
# stdlib imports
import pickle
diff --git a/src/nti/externalization/tests/__init__.py b/src/nti/externalization/tests/__init__.py
index 5959b38..bf38ba7 100644
--- a/src/nti/externalization/tests/__init__.py
+++ b/src/nti/externalization/tests/__init__.py
@@ -1,23 +1,19 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
import zope.testing.cleanup
import nti.testing.base
-from nti.testing.layers import ConfiguringLayerMixin
-from nti.testing.layers import ZopeComponentLayer
-
# BWC exports
from nti.externalization.testing import Externalizes
-from nti.externalization.testing import externalizes
from nti.externalization.testing import assert_does_not_pickle
+from nti.externalization.testing import externalizes
+from nti.testing.layers import ConfiguringLayerMixin
+from nti.testing.layers import ZopeComponentLayer
+
Externalizes = Externalizes
externalizes = externalizes
assert_does_not_pickle = assert_does_not_pickle
diff --git a/src/nti/externalization/tests/benchmarks/__init__.py b/src/nti/externalization/tests/benchmarks/__init__.py
index 9796905..80a7371 100644
--- a/src/nti/externalization/tests/benchmarks/__init__.py
+++ b/src/nti/externalization/tests/benchmarks/__init__.py
@@ -9,6 +9,3 @@
`_.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
diff --git a/src/nti/externalization/tests/benchmarks/__main__.py b/src/nti/externalization/tests/benchmarks/__main__.py
index 43d0a83..e83d090 100644
--- a/src/nti/externalization/tests/benchmarks/__main__.py
+++ b/src/nti/externalization/tests/benchmarks/__main__.py
@@ -3,17 +3,15 @@
Main file to run when the package is specified. Primary CLI.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import glob
import os
import os.path
-import pyperf as perf
from zope.dottedname import resolve as dottedname
+import pyperf as perf
+
here = os.path.dirname(__file__)
def find_benchmarks():
diff --git a/src/nti/externalization/tests/benchmarks/bm_simple_iface.py b/src/nti/externalization/tests/benchmarks/bm_simple_iface.py
index d393156..501916c 100644
--- a/src/nti/externalization/tests/benchmarks/bm_simple_iface.py
+++ b/src/nti/externalization/tests/benchmarks/bm_simple_iface.py
@@ -4,27 +4,22 @@
a single text field.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import sys
-import pyperf
-from pyperf import perf_counter
-
from zope.configuration import xmlconfig
-from nti.externalization.representation import JsonRepresenter
+import nti.externalization.tests.benchmarks
from nti.externalization.externalization import toExternalObject
from nti.externalization.interfaces import StandardExternalFields
from nti.externalization.internalization import default_externalized_object_factory_finder
from nti.externalization.internalization import update_from_external_object
-
-import nti.externalization.tests.benchmarks
+from nti.externalization.representation import JsonRepresenter
from nti.externalization.tests.benchmarks.objects import DerivedWithOneTextField
+import pyperf
+from pyperf import perf_counter
+
INNER_LOOPS = 100
def to_external_object_time_func(loops, obj):
@@ -59,8 +54,8 @@ def update_from_external_object_time_func(loops, ext):
def profile(loops=1000, obj=None):
- from cProfile import Profile
import pstats
+ from cProfile import Profile
if obj is None:
obj = DerivedWithOneTextField()
@@ -85,7 +80,7 @@ def profile(loops=1000, obj=None):
stats.print_stats(20)
def vmprofile(loops=1000, obj=None):
- import vmprof # pylint:disable=import-error
+ import vmprof # pylint:disable=import-error
if obj is None:
obj = DerivedWithOneTextField()
diff --git a/src/nti/externalization/tests/benchmarks/bm_simple_iface_list.py b/src/nti/externalization/tests/benchmarks/bm_simple_iface_list.py
index b217fdb..6e67c8b 100644
--- a/src/nti/externalization/tests/benchmarks/bm_simple_iface_list.py
+++ b/src/nti/externalization/tests/benchmarks/bm_simple_iface_list.py
@@ -3,35 +3,24 @@
Extends bm_simple_iface to add a list.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import sys
-import pyperf as perf
-
-
from zope.configuration import xmlconfig
-from nti.externalization._compat import PYPY
+import nti.externalization.tests.benchmarks
from nti.externalization.externalization import toExternalObject
from nti.externalization.interfaces import StandardExternalFields
-
-import nti.externalization.tests.benchmarks
-
+from nti.externalization.tests.benchmarks.bm_simple_iface import INNER_LOOPS
+from nti.externalization.tests.benchmarks.bm_simple_iface import profile
+from nti.externalization.tests.benchmarks.bm_simple_iface import to_external_object_time_func
+from nti.externalization.tests.benchmarks.bm_simple_iface import \
+ update_from_external_object_time_func
+from nti.externalization.tests.benchmarks.bm_simple_iface import vmprofile
from nti.externalization.tests.benchmarks.objects import DerivedWithOneTextField
from nti.externalization.tests.benchmarks.objects import HasListOfDerived
-from nti.externalization.tests.benchmarks.bm_simple_iface import (
- INNER_LOOPS,
- to_external_object_time_func,
- update_from_external_object_time_func,
- profile,
- vmprofile,
-)
-
-logger = __import__('logging').getLogger(__name__)
+import pyperf as perf
def main(runner=None):
@@ -47,7 +36,7 @@ def main(runner=None):
return
if '--vmprofile' in sys.argv:
- vmprofile(100 if not PYPY else 1, obj)
+ vmprofile(100, obj)
return
mt = getattr(obj, 'mimeType')
diff --git a/src/nti/externalization/tests/benchmarks/bm_simple_registered_class.py b/src/nti/externalization/tests/benchmarks/bm_simple_registered_class.py
index 2959f5e..8c78fea 100644
--- a/src/nti/externalization/tests/benchmarks/bm_simple_registered_class.py
+++ b/src/nti/externalization/tests/benchmarks/bm_simple_registered_class.py
@@ -3,22 +3,20 @@
Benchmark for a simple registered Class factory object.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import warnings
-import pyperf as perf
from zope.configuration import xmlconfig
+import nti.externalization.tests.benchmarks
from nti.externalization.externalization import toExternalObject
from nti.externalization.interfaces import StandardExternalFields
from nti.externalization.internalization import default_externalized_object_factory_finder
from nti.externalization.internalization import update_from_external_object
-import nti.externalization.tests.benchmarks
from nti.externalization.tests.benchmarks.objects import SimplestPossibleObject
+import pyperf as perf
+
# pylint:disable=arguments-renamed,unused-argument
# pylint:disable=arguments-differ
diff --git a/src/nti/externalization/tests/benchmarks/bm_singleton.py b/src/nti/externalization/tests/benchmarks/bm_singleton.py
index 3100d29..a116def 100644
--- a/src/nti/externalization/tests/benchmarks/bm_singleton.py
+++ b/src/nti/externalization/tests/benchmarks/bm_singleton.py
@@ -3,13 +3,11 @@
Benchmark for creating singleton objects.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
+
+from nti.externalization.singleton import Singleton
import pyperf as perf
-from nti.externalization.singleton import Singleton
# These are defined to have __slots__ = ()
class SingletonSubclass(Singleton):
diff --git a/src/nti/externalization/tests/benchmarks/bm_user_profile.py b/src/nti/externalization/tests/benchmarks/bm_user_profile.py
index e26e06d..7493fa6 100644
--- a/src/nti/externalization/tests/benchmarks/bm_user_profile.py
+++ b/src/nti/externalization/tests/benchmarks/bm_user_profile.py
@@ -3,9 +3,6 @@
Benchmarks a realistic user profile object.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import sys
@@ -28,8 +25,6 @@
profile
)
-logger = __import__('logging').getLogger(__name__)
-
def main(runner=None):
diff --git a/src/nti/externalization/tests/benchmarks/bootstrapinterfaces.py b/src/nti/externalization/tests/benchmarks/bootstrapinterfaces.py
index 5265f94..ff2e336 100644
--- a/src/nti/externalization/tests/benchmarks/bootstrapinterfaces.py
+++ b/src/nti/externalization/tests/benchmarks/bootstrapinterfaces.py
@@ -3,15 +3,10 @@
Interfaces for objects we will benchmark with.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
import re
from zope.interface import Interface
-
-
from zope.schema.interfaces import InvalidValue
# pylint:disable=inherit-non-class
diff --git a/src/nti/externalization/tests/benchmarks/interfaces.py b/src/nti/externalization/tests/benchmarks/interfaces.py
index cb90057..01d48c6 100644
--- a/src/nti/externalization/tests/benchmarks/interfaces.py
+++ b/src/nti/externalization/tests/benchmarks/interfaces.py
@@ -3,26 +3,21 @@
Interfaces for objects we will benchmark with.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
from zope.interface import Interface
from zope.interface import taggedValue
-
from zope.schema import List
from zope.schema import Object
-from nti.schema.field import TextLine
-
from nti.externalization.tests.benchmarks.bootstrapinterfaces import IRootInterface
-from nti.externalization.tests.benchmarks.profileinterfaces import IFriendlyNamed
+from nti.externalization.tests.benchmarks.profileinterfaces import IAddress
from nti.externalization.tests.benchmarks.profileinterfaces import IAvatarURL
from nti.externalization.tests.benchmarks.profileinterfaces import IBackgroundURL
+from nti.externalization.tests.benchmarks.profileinterfaces import IFriendlyNamed
from nti.externalization.tests.benchmarks.profileinterfaces import IProfileAvatarURL
-from nti.externalization.tests.benchmarks.profileinterfaces import IAddress
from nti.externalization.tests.benchmarks.profileinterfaces import IUserContactProfile
from nti.externalization.tests.benchmarks.profileinterfaces import IUserProfile
+from nti.schema.field import TextLine
__all__ = [
'IRootInterface',
diff --git a/src/nti/externalization/tests/benchmarks/objects.py b/src/nti/externalization/tests/benchmarks/objects.py
index 948b1ea..8fea439 100644
--- a/src/nti/externalization/tests/benchmarks/objects.py
+++ b/src/nti/externalization/tests/benchmarks/objects.py
@@ -3,20 +3,15 @@
Implementations of interfaces.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
from zope import interface
-
from zope.schema.fieldproperty import createFieldProperties
from nti.externalization.datastructures import ExternalizableInstanceDict
from nti.externalization.representation import WithRepr
-
+from nti.schema.eqhash import EqHash
from nti.schema.fieldproperty import createDirectFieldProperties
from nti.schema.schema import SchemaConfigured
-from nti.schema.eqhash import EqHash
from . import interfaces
@@ -36,6 +31,7 @@ def __init__(self, text=''):
@interface.implementer(interfaces.IHasListOfDerived)
class HasListOfDerived(object):
+ the_objects: list
createDirectFieldProperties(interfaces.IHasListOfDerived)
diff --git a/src/nti/externalization/tests/benchmarks/profileinterfaces.py b/src/nti/externalization/tests/benchmarks/profileinterfaces.py
index 521fa51..49783c7 100644
--- a/src/nti/externalization/tests/benchmarks/profileinterfaces.py
+++ b/src/nti/externalization/tests/benchmarks/profileinterfaces.py
@@ -2,24 +2,20 @@
"""
A rich user profile.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
from zope.interface import Interface
from zope.interface import taggedValue
-
-from zope.schema import Object
from zope.schema import URI
+from zope.schema import Object
+from nti.externalization.tests.benchmarks.bootstrapinterfaces import IRootInterface
+from nti.externalization.tests.benchmarks.bootstrapinterfaces import checkEmailAddress
+from nti.externalization.tests.benchmarks.bootstrapinterfaces import checkRealname
+from nti.schema.field import DecodingValidTextLine
from nti.schema.field import Dict
from nti.schema.field import TextLine
from nti.schema.field import ValidTextLine
-from nti.schema.field import DecodingValidTextLine
-from nti.externalization.tests.benchmarks.bootstrapinterfaces import IRootInterface
-from nti.externalization.tests.benchmarks.bootstrapinterfaces import checkEmailAddress
-from nti.externalization.tests.benchmarks.bootstrapinterfaces import checkRealname
# pylint:disable=inherit-non-class
class IFriendlyNamed(Interface):
diff --git a/src/nti/externalization/tests/test__compat.py b/src/nti/externalization/tests/test__compat.py
index cf8e915..145cb92 100644
--- a/src/nti/externalization/tests/test__compat.py
+++ b/src/nti/externalization/tests/test__compat.py
@@ -3,11 +3,6 @@
Tests for _compat.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
diff --git a/src/nti/externalization/tests/test_autopackage.py b/src/nti/externalization/tests/test_autopackage.py
index 066ca4d..c4db68e 100644
--- a/src/nti/externalization/tests/test_autopackage.py
+++ b/src/nti/externalization/tests/test_autopackage.py
@@ -3,11 +3,7 @@
Tests for autopackage.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
from zope import interface
@@ -15,15 +11,15 @@
from nti.testing.matchers import implements
-from ..autopackage import AutoPackageSearchingScopedInterfaceObjectIO as AutoPackage
-
from hamcrest import assert_that
+from hamcrest import contains_string
from hamcrest import has_key
from hamcrest import has_property
from hamcrest import is_
from hamcrest import is_not as does_not
from hamcrest import none
-from hamcrest import contains_string
+
+from ..autopackage import AutoPackageSearchingScopedInterfaceObjectIO as AutoPackage
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
diff --git a/src/nti/externalization/tests/test_datastructures.py b/src/nti/externalization/tests/test_datastructures.py
index 96c1ef4..a5ea890 100644
--- a/src/nti/externalization/tests/test_datastructures.py
+++ b/src/nti/externalization/tests/test_datastructures.py
@@ -1,11 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import sys
import unittest
@@ -13,17 +9,16 @@
from zope.testing.cleanup import CleanUp
from nti.externalization.tests import ExternalizationLayerTest
-
from nti.testing.matchers import is_false
from nti.testing.matchers import is_true
from nti.testing.matchers import verifiably_provides
from hamcrest import assert_that
+from hamcrest import contains_string
from hamcrest import has_property
from hamcrest import is_
from hamcrest import is_not as does_not
from hamcrest import none
-from hamcrest import contains_string
is_not = does_not
@@ -54,11 +49,12 @@ def test_ext_replacement_getattr_default(self):
is_(none()))
def test_standard_dates_policy(self):
- from ..interfaces import ExternalizationPolicy
- from ..datetime import datetime_to_string
from datetime import datetime as DateTime
from datetime import timezone
+ from ..datetime_ext import datetime_to_string
+ from ..interfaces import ExternalizationPolicy
+
iso_policy = ExternalizationPolicy(use_iso8601_for_unix_timestamp=True)
class X(object):
@@ -769,15 +765,15 @@ def register(self, obj):
class TestStandardInternalObjectExternalizer(unittest.TestCase):
def test_provides(self):
- from nti.externalization.interfaces import IInternalObjectExternalizer
from nti.externalization.datastructures import StandardInternalObjectExternalizer
+ from nti.externalization.interfaces import IInternalObjectExternalizer
o = StandardInternalObjectExternalizer(object())
assert_that(o, verifiably_provides(IInternalObjectExternalizer))
def test_subclass(self):
- from nti.externalization.interfaces import IInternalObjectExternalizer
- from nti.externalization.datastructures import StandardInternalObjectExternalizer
from nti.externalization._compat import PURE_PYTHON
+ from nti.externalization.datastructures import StandardInternalObjectExternalizer
+ from nti.externalization.interfaces import IInternalObjectExternalizer
class X(StandardInternalObjectExternalizer):
def __init__(self, context):
diff --git a/src/nti/externalization/tests/test_datetime.py b/src/nti/externalization/tests/test_datetime.py
index bf082fa..349b580 100644
--- a/src/nti/externalization/tests/test_datetime.py
+++ b/src/nti/externalization/tests/test_datetime.py
@@ -1,27 +1,23 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
-from contextlib import contextmanager
-from datetime import date
-from datetime import timedelta
import os
import time
import unittest
+from contextlib import contextmanager
+from datetime import date
+from datetime import timedelta
+from zope.configuration import xmlconfig
from zope.interface.common.idatetime import IDate
from zope.interface.common.idatetime import IDateTime
from zope.schema.interfaces import InvalidValue
-from zope.configuration import xmlconfig
from zope.testing import cleanup
import nti.externalization
-from nti.externalization.datetime import datetime_to_string
-from nti.externalization.datetime import datetime_from_string
+from nti.externalization.datetime_ext import datetime_from_string
+from nti.externalization.datetime_ext import datetime_to_string
from nti.externalization.tests import ExternalizationLayerTest
from nti.externalization.tests import externalizes
@@ -124,8 +120,9 @@ def test_datetime_from_timestamp(self):
class TestTzinfo(unittest.TestCase):
def test_invalid_local_name_in_dst_uses_system_settings(self):
+ from nti.externalization.datetime_ext import _local_tzinfo
+
import pytz
- from nti.externalization.datetime import _local_tzinfo
with environ_tz():
os.environ['TZ'] = 'CST+06CDT+05,0,365'
time.tzset()
diff --git a/src/nti/externalization/tests/test_docs.py b/src/nti/externalization/tests/test_docs.py
index 46b7912..c51edfe 100644
--- a/src/nti/externalization/tests/test_docs.py
+++ b/src/nti/externalization/tests/test_docs.py
@@ -3,18 +3,14 @@
Tests for the sphinx documentation using `Manuel
`_.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
import doctest
import os.path
import re
import unittest
-from zope.testing import renormalizing
from zope.testing import cleanup
+from zope.testing import renormalizing
import manuel.capture
import manuel.codeblock
diff --git a/src/nti/externalization/tests/test_dublincore.py b/src/nti/externalization/tests/test_dublincore.py
index 99f6fb6..d504a2b 100644
--- a/src/nti/externalization/tests/test_dublincore.py
+++ b/src/nti/externalization/tests/test_dublincore.py
@@ -3,19 +3,15 @@
Tests for dublincore.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
-from . import ExternalizationLayerTest
-
from hamcrest import assert_that
from hamcrest import is_
from hamcrest import same_instance
+from . import ExternalizationLayerTest
+
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
# pylint: disable=attribute-defined-outside-init
@@ -104,13 +100,13 @@ class Original(object):
class TestConfigured(ExternalizationLayerTest):
def test_decorate(self):
- from ..dublincore import IDCDescriptiveProperties
- from ..dublincore import IDCExtended
-
from zope import interface
from nti.externalization.externalization import decorate_external_mapping
+ from ..dublincore import IDCDescriptiveProperties
+ from ..dublincore import IDCExtended
+
@interface.implementer(IDCExtended, IDCDescriptiveProperties)
class O(object):
creators = ('abc',)
diff --git a/src/nti/externalization/tests/test_externalization.py b/src/nti/externalization/tests/test_externalization.py
index 6c731a0..d6dad49 100644
--- a/src/nti/externalization/tests/test_externalization.py
+++ b/src/nti/externalization/tests/test_externalization.py
@@ -1,55 +1,64 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import datetime
import json
-from numbers import Number
import unittest
-
+from numbers import Number
try:
- from ZODB.broken import Broken
from persistent import CHANGED
from persistent import UPTODATE
from zope.dublincore import interfaces as dub_interfaces
+
+ from ZODB.broken import Broken
except ModuleNotFoundError:
Broken = None
dub_interfaces = None
from ..persistence import CHANGED
from ..persistence import UPTODATE
+from collections import UserDict
+
from zope import component
from zope import interface
-
from zope.testing.cleanup import CleanUp
from nti.externalization.externalization import stripSyntheticKeysFromExternalDictionary
-from nti.testing.matchers import verifiably_provides
-from nti.testing.matchers import is_true
from nti.testing.matchers import is_false
+from nti.testing.matchers import is_true
+from nti.testing.matchers import verifiably_provides
+
+from hamcrest import assert_that
+from hamcrest import calling
+from hamcrest import contains_exactly
+from hamcrest import has_entry
+from hamcrest import has_items
+from hamcrest import has_key
+from hamcrest import has_property as has_attr
+from hamcrest import is_
+from hamcrest import is_not
+from hamcrest import none
+from hamcrest import raises
+from hamcrest import same_instance
-from . import ExternalizationLayerTest
from ..datastructures import ExternalizableDictionaryMixin
from ..datastructures import ExternalizableInstanceDict
+from ..extension_points import set_external_identifiers
from ..externalization import NonExternalizableObjectError
-from ..externalization.replacers import DevmodeNonExternalizableObjectReplacementFactory
from ..externalization import catch_replace_action
from ..externalization import choose_field
from ..externalization import isSyntheticKey
from ..externalization import removed_unserializable
-from ..extension_points import set_external_identifiers
from ..externalization import to_standard_external_dictionary
from ..externalization import toExternalObject
+from ..externalization.replacers import DevmodeNonExternalizableObjectReplacementFactory
from ..externalization.standard_fields import get_creator
from ..interfaces import EXT_REPR_JSON
from ..interfaces import EXT_REPR_YAML
-from ..interfaces import IInternalObjectExternalizer as IExternalObject
from ..interfaces import IExternalObjectDecorator
+from ..interfaces import IInternalObjectExternalizer as IExternalObject
from ..interfaces import LocatedExternalDict
from ..interfaces import LocatedExternalList
from ..interfaces import StandardExternalFields
@@ -60,22 +69,7 @@
from ..persistence import getPersistentState
from ..representation import to_external_representation
from ..testing import assert_does_not_pickle
-
-from hamcrest import assert_that
-from hamcrest import calling
-from hamcrest import contains_exactly
-from hamcrest import has_entry
-from hamcrest import has_items
-from hamcrest import has_key
-from hamcrest import is_
-from hamcrest import is_not
-from hamcrest import none
-from hamcrest import raises
-from hamcrest import same_instance
-from hamcrest import has_property as has_attr
-
-from collections import UserDict
-
+from . import ExternalizationLayerTest
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
@@ -276,10 +270,11 @@ class WithSystemUser(object):
assert_that(result, is_({StandardExternalFields.CREATOR: WithSystemUser.user}))
def test_get_creator_system_user(self):
- from nti.externalization.externalization import SYSTEM_USER_NAME
from zope.security.interfaces import IPrincipal
from zope.security.management import system_user
+ from nti.externalization.externalization import SYSTEM_USER_NAME
+
@interface.implementer(IPrincipal)
class MySystemUser(object):
id = system_user.id
@@ -300,8 +295,8 @@ class TestDecorators(CleanUp,
unittest.TestCase):
def test_decorate_external_mapping(self):
- from nti.externalization.interfaces import IExternalStandardDictionaryDecorator
from nti.externalization.externalization import decorate_external_mapping
+ from nti.externalization.interfaces import IExternalStandardDictionaryDecorator
class IRequest(interface.Interface):
pass
@@ -417,9 +412,10 @@ def __init__(self):
self.lastModified = 8675309
def to_str(ts): # pylint:disable=no-self-argument
- from ..datetime import datetime_to_string
from datetime import datetime as DateTime
from datetime import timezone
+
+ from ..datetime_ext import datetime_to_string
return datetime_to_string(DateTime.fromtimestamp(ts, timezone.utc)).toExternalObject()
created_string = to_str(X().createdTime)
modified_string = to_str(X().lastModified)
@@ -639,8 +635,8 @@ class X(object):
def test_to_stand_dict_uses_dubcore_iso8601(self):
if dub_interfaces is None:
self.skipTest('zope.dublincore not installed')
+ from ..datetime_ext import datetime_to_string
from ..interfaces import ExternalizationPolicy
- from ..datetime import datetime_to_string
policy = ExternalizationPolicy(use_iso8601_for_unix_timestamp=True)
@interface.implementer(dub_interfaces.IDCTimes)
@@ -660,9 +656,10 @@ class X(object):
def test_to_stand_dict_prefers_direct_fields_iso8601(self):
if dub_interfaces is None:
self.skipTest('zope.dublincore not installed')
- from ..interfaces import ExternalizationPolicy
- from ..datetime import datetime_to_string
from datetime import timezone
+
+ from ..datetime_ext import datetime_to_string
+ from ..interfaces import ExternalizationPolicy
policy = ExternalizationPolicy(use_iso8601_for_unix_timestamp=True)
@interface.implementer(dub_interfaces.IDCTimes)
@@ -901,9 +898,10 @@ def test_decorator(self):
class TestDeprecatedImports(unittest.TestCase):
def test_SEF(self):
+ import warnings
+
from nti.externalization import externalization
from nti.externalization import interfaces
- import warnings
with warnings.catch_warnings(record=True):
sef = getattr(externalization, 'StandardExternalFields')
@@ -911,9 +909,10 @@ def test_SEF(self):
assert_that(sef, is_(same_instance(interfaces.StandardExternalFields)))
def test_SIF(self):
+ import warnings
+
from nti.externalization import externalization
from nti.externalization import interfaces
- import warnings
with warnings.catch_warnings(record=True):
sif = getattr(externalization, 'StandardInternalFields')
diff --git a/src/nti/externalization/tests/test_factory.py b/src/nti/externalization/tests/test_factory.py
index e003c32..5db9340 100644
--- a/src/nti/externalization/tests/test_factory.py
+++ b/src/nti/externalization/tests/test_factory.py
@@ -3,22 +3,17 @@
Tests for factory.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
# stdlib imports
import doctest
import unittest
+from nti.testing.matchers import validly_provides
from hamcrest import assert_that
+from hamcrest import has_property
from hamcrest import is_
from hamcrest import is_not
-from hamcrest import has_property
-from nti.testing.matchers import validly_provides
-
-logger = __import__('logging').getLogger(__name__)
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
diff --git a/src/nti/externalization/tests/test_integer_strings.py b/src/nti/externalization/tests/test_integer_strings.py
index 9a5d46b..505d79d 100644
--- a/src/nti/externalization/tests/test_integer_strings.py
+++ b/src/nti/externalization/tests/test_integer_strings.py
@@ -1,11 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import sys
import unittest
diff --git a/src/nti/externalization/tests/test_interfaces.py b/src/nti/externalization/tests/test_interfaces.py
index 8085d64..0ae5da5 100644
--- a/src/nti/externalization/tests/test_interfaces.py
+++ b/src/nti/externalization/tests/test_interfaces.py
@@ -3,19 +3,17 @@
Tests for interfaces.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
import unittest
+from nti.externalization.interfaces import LocatedExternalDict
+
from hamcrest import assert_that
from hamcrest import has_property
-from nti.externalization.interfaces import LocatedExternalDict
class TestLocatedExternalDict(unittest.TestCase):
diff --git a/src/nti/externalization/tests/test_internalization.py b/src/nti/externalization/tests/test_internalization.py
index 6cb8046..12ab0eb 100644
--- a/src/nti/externalization/tests/test_internalization.py
+++ b/src/nti/externalization/tests/test_internalization.py
@@ -1,11 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
import warnings
from unittest.mock import patch as Patch
@@ -13,16 +9,11 @@
from zope import component
from zope import interface
from zope.interface.common.idatetime import IDate
-from zope.testing.cleanup import CleanUp
from zope.schema.interfaces import InvalidValue
+from zope.testing.cleanup import CleanUp
from nti.externalization.tests import ExternalizationLayerTest
-
-from .. import internalization as INT
-from ..interfaces import IClassObjectFactory
-from ..interfaces import IMimeObjectFactory
-
from hamcrest import assert_that
from hamcrest import contains_exactly
from hamcrest import contains_string
@@ -37,6 +28,10 @@
from hamcrest import none
from hamcrest import same_instance
+from .. import internalization as INT
+from ..interfaces import IClassObjectFactory
+from ..interfaces import IMimeObjectFactory
+
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
# pylint: disable=inherit-non-class
@@ -55,8 +50,8 @@ class TestEvents(CleanUp,
unittest.TestCase):
def _doIt(self, *args, **kwargs):
- from nti.externalization.internalization import notifyModified
from nti.externalization.interfaces import ObjectModifiedFromExternalEvent
+ from nti.externalization.internalization import notifyModified
with warnings.catch_warnings(record=True):
event = notifyModified(*args, **kwargs)
@@ -614,8 +609,8 @@ def __conform__(self, iface): # pylint:disable=bad-dunder-name
def test_wrong_type_adapts(self):
from zope.schema import Field
- from zope.schema.interfaces import WrongType
from zope.schema.interfaces import ValidationError
+ from zope.schema.interfaces import WrongType
class Iface(interface.Interface):
pass
@@ -656,8 +651,8 @@ def __conform__(self, iface): # pylint:disable=bad-dunder-name
assert_that(exc.exception, has_property('field', field))
def test_wrong_contained_type_object_field_adapts(self):
- from zope.schema import Object
from zope.schema import List
+ from zope.schema import Object
class IThing(interface.Interface):
@@ -677,9 +672,9 @@ def __conform__(self, iface): # pylint:disable=bad-dunder-name
assert_that(bag, has_property('field', contains_exactly(is_(O))))
def test_wrong_contained_type_object_field_adapts_fails(self):
- from zope.schema.interfaces import WrongContainedType
- from zope.schema import Object
from zope.schema import List
+ from zope.schema import Object
+ from zope.schema.interfaces import WrongContainedType
class IThing(interface.Interface):
@@ -712,8 +707,8 @@ def bind(self, _):
def test_wrong_contained_type_field(self):
- from zope.schema import Object
from zope.schema import List
+ from zope.schema import Object
from zope.schema.interfaces import WrongContainedType
@@ -740,8 +735,8 @@ def __conform__(self, iface): # pylint:disable=bad-dunder-name
assert_that(ex.errors[0], has_property('value', is_(Conforms)))
def test_wrong_contained_type_value_type_fromObject(self):
- from zope.schema import Object
from zope.schema import List
+ from zope.schema import Object
class IThing(interface.Interface):
pass
diff --git a/src/nti/externalization/tests/test_oids.py b/src/nti/externalization/tests/test_oids.py
index 6cb93b5..5a4ee90 100644
--- a/src/nti/externalization/tests/test_oids.py
+++ b/src/nti/externalization/tests/test_oids.py
@@ -4,21 +4,17 @@
Tests for oids.py.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
from zope.testing.cleanup import CleanUp
-from ..oids import fromExternalOID
-from ..oids import toExternalOID
-
from hamcrest import assert_that
from hamcrest import is_
+from ..oids import fromExternalOID
+from ..oids import toExternalOID
+
class TestToExternalOID(CleanUp,
unittest.TestCase):
@@ -53,8 +49,8 @@ class Persistent(object):
assert_that(result, is_('default'))
def test_intid(self):
- from zope.interface import implementer
from zope import component
+ from zope.interface import implementer
try:
from zope.intid.interfaces import IIntIds
except ModuleNotFoundError:
diff --git a/src/nti/externalization/tests/test_persistence.py b/src/nti/externalization/tests/test_persistence.py
index dff8252..370c06a 100644
--- a/src/nti/externalization/tests/test_persistence.py
+++ b/src/nti/externalization/tests/test_persistence.py
@@ -1,19 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
import warnings
try:
+ from persistent import CHANGED
+ from persistent import UPTODATE
from persistent import Persistent
from persistent.wref import WeakRef as PWeakRef
- from persistent import UPTODATE
- from persistent import CHANGED
except ModuleNotFoundError:
class Persistent:
"""Mock"""
@@ -22,20 +18,20 @@ class Persistent:
from ..persistence import UPTODATE
from ..persistence import CHANGED
-from ..persistence import PersistentExternalizableList
-from ..persistence import PersistentExternalizableDictionary
-from ..persistence import PersistentExternalizableWeakList
-from ..persistence import getPersistentState
-from ..persistence import setPersistentStateChanged
-from ..persistence import NoPickle
-from . import ExternalizationLayerTest
-
from hamcrest import assert_that
from hamcrest import calling
+from hamcrest import has_length
from hamcrest import is_
from hamcrest import is_not
from hamcrest import raises
-from hamcrest import has_length
+
+from ..persistence import NoPickle
+from ..persistence import PersistentExternalizableDictionary
+from ..persistence import PersistentExternalizableList
+from ..persistence import PersistentExternalizableWeakList
+from ..persistence import getPersistentState
+from ..persistence import setPersistentStateChanged
+from . import ExternalizationLayerTest
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
diff --git a/src/nti/externalization/tests/test_proxy.py b/src/nti/externalization/tests/test_proxy.py
index bc1a5b2..8d72085 100644
--- a/src/nti/externalization/tests/test_proxy.py
+++ b/src/nti/externalization/tests/test_proxy.py
@@ -1,11 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
try:
diff --git a/src/nti/externalization/tests/test_singleton.py b/src/nti/externalization/tests/test_singleton.py
index fd9e957..adf14ec 100644
--- a/src/nti/externalization/tests/test_singleton.py
+++ b/src/nti/externalization/tests/test_singleton.py
@@ -1,11 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
from nti.externalization.singleton import SingletonDecorator
from nti.externalization.tests import ExternalizationLayerTest
@@ -57,8 +52,8 @@ class Z(Y):
def test_suite():
- import unittest
import doctest
+ import unittest
suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
return unittest.TestSuite([
diff --git a/src/nti/externalization/tests/test_testing.py b/src/nti/externalization/tests/test_testing.py
index 77a9bab..322b97c 100644
--- a/src/nti/externalization/tests/test_testing.py
+++ b/src/nti/externalization/tests/test_testing.py
@@ -3,11 +3,7 @@
Tests for testing.py
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
from nti.externalization.testing import externalizes
diff --git a/src/nti/externalization/tests/test_zcml.py b/src/nti/externalization/tests/test_zcml.py
index cebc4b4..df3f4e9 100644
--- a/src/nti/externalization/tests/test_zcml.py
+++ b/src/nti/externalization/tests/test_zcml.py
@@ -3,11 +3,7 @@
Tests for zcml.py.
"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-# stdlib imports
import unittest
from zope import component
@@ -21,13 +17,13 @@
from nti.testing.matchers import is_empty
from hamcrest import assert_that
-from hamcrest import same_instance
from hamcrest import equal_to
-from hamcrest import is_
-from hamcrest import is_not
from hamcrest import has_length
from hamcrest import has_property
+from hamcrest import is_
+from hamcrest import is_not
from hamcrest import none
+from hamcrest import same_instance
# disable: accessing protected members, too many methods
# pylint: disable=W0212,R0904
@@ -196,7 +192,9 @@ def test_scan_package_inherited(self):
# Issue #97: When interface tags are inherited,
# we don't double register.
import sys
+
from zope.interface.interfaces import IInterface
+
from ..interfaces import IInternalObjectIOFinder
class IPublic(interface.Interface):
diff --git a/src/nti/externalization/zcml.py b/src/nti/externalization/zcml.py
index b3defd1..be872a5 100644
--- a/src/nti/externalization/zcml.py
+++ b/src/nti/externalization/zcml.py
@@ -191,16 +191,16 @@ def autoPackageExternalization(_context, root_interfaces, modules,
package_name = ext_module_name.rsplit('.', 1)[0]
root_interfaces = frozenset(root_interfaces)
- @classmethod
+ @classmethod # type:ignore[misc]
def _ap_enumerate_externalizable_root_interfaces(_cls, unused_ifaces):
return root_interfaces
module_names = frozenset([m.__name__.split('.')[-1] for m in modules])
- @classmethod
+ @classmethod # type:ignore[misc]
def _ap_enumerate_module_names(_cls):
return module_names
- @classmethod
+ @classmethod # type:ignore[misc]
def _ap_find_package_name(_cls):
return package_name
@@ -216,9 +216,10 @@ def _ap_find_package_name(_cls):
if iobase:
bases = (iobase,) + bases
- cls_iio = type('AutoPackageSearchingScopedInterfaceObjectIO',
- bases,
- cls_dict)
+ cls_iio: type[AutoPackageSearchingScopedInterfaceObjectIO] = type(
+ 'AutoPackageSearchingScopedInterfaceObjectIO',
+ bases,
+ cls_dict)
# If we don't set the __module__, it defaults to this module,
# which would be very confusing.
cls_iio.__module__ = _context.package.__name__ if _context.package else '__dynamic__'