Skip to content

Commit e27abdb

Browse files
authored
Update for Python 3.6+ (#7)
Update for Python 3.6+
2 parents 88bab21 + b0aaccd commit e27abdb

6 files changed

Lines changed: 48 additions & 67 deletions

File tree

azure-pipelines.yml

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,6 @@ jobs:
99
- job: 'Test'
1010
strategy:
1111
matrix:
12-
Python27Linux:
13-
imageName: 'ubuntu-16.04'
14-
python.version: '2.7'
15-
Python27Mac:
16-
imageName: 'macos-10.13'
17-
python.version: '2.7'
18-
Python35Linux:
19-
imageName: 'ubuntu-16.04'
20-
python.version: '3.5'
21-
Python35Windows:
22-
imageName: 'vs2017-win2016'
23-
python.version: '3.5'
24-
Python35Mac:
25-
imageName: 'macos-10.13'
26-
python.version: '3.5'
2712
Python36Linux:
2813
imageName: 'ubuntu-16.04'
2914
python.version: '3.6'
@@ -57,6 +42,9 @@ jobs:
5742
python setup.py sdist
5843
displayName: 'Build sdist'
5944
45+
- script: python -m mypy catalogue.py
46+
displayName: 'Run mypy'
47+
6048
- task: DeleteFiles@1
6149
inputs:
6250
contents: 'catalogue.py'

catalogue.py

Lines changed: 38 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,44 @@
1-
# coding: utf8
2-
from __future__ import unicode_literals
3-
4-
from collections import OrderedDict
5-
import sys
1+
from typing import Sequence, Any, Dict, Tuple, Callable, Optional, TypeVar
62

73
try: # Python 3.8
84
import importlib.metadata as importlib_metadata
95
except ImportError:
10-
import importlib_metadata
11-
12-
if sys.version_info[0] == 2:
13-
basestring_ = basestring # noqa: F821
14-
else:
15-
basestring_ = str
6+
import importlib_metadata # type: ignore
167

178
# Only ever call this once for performance reasons
18-
AVAILABLE_ENTRY_POINTS = importlib_metadata.entry_points()
9+
AVAILABLE_ENTRY_POINTS = importlib_metadata.entry_points() # type: ignore
1910

2011
# This is where functions will be registered
21-
REGISTRY = OrderedDict()
12+
REGISTRY: Dict[Tuple[str, ...], Any] = {}
13+
2214

15+
InFunc = TypeVar("InFunc")
2316

24-
def create(*namespace, **kwargs):
17+
18+
def create(*namespace: str, entry_points: bool = False) -> "Registry":
2519
"""Create a new registry.
2620
2721
*namespace (str): The namespace, e.g. "spacy" or "spacy", "architectures".
28-
RETURNS (Tuple[Callable]): The setter (decorator to register functions)
29-
and getter (to retrieve functions).
22+
entry_points (bool): Accept registered functions from entry points.
23+
RETURNS (Registry): The Registry object.
3024
"""
31-
entry_points = kwargs.get("entry_points", False)
3225
if check_exists(*namespace):
3326
raise RegistryError("Namespace already exists: {}".format(namespace))
3427
return Registry(namespace, entry_points=entry_points)
3528

3629

3730
class Registry(object):
38-
def __init__(self, namespace, entry_points=False):
31+
def __init__(self, namespace: Sequence[str], entry_points: bool = False) -> None:
3932
"""Initialize a new registry.
4033
41-
namespace (Tuple[str]): The namespace.
34+
namespace (Sequence[str]): The namespace.
4235
entry_points (bool): Whether to also check for entry points.
43-
RETURNS (Registry): The newly created object.
4436
"""
4537
self.namespace = namespace
4638
self.entry_point_namespace = "_".join(namespace)
4739
self.entry_points = entry_points
4840

49-
def __contains__(self, name):
41+
def __contains__(self, name: str) -> bool:
5042
"""Check whether a name is in the registry.
5143
5244
name (str): The name to check.
@@ -56,16 +48,20 @@ def __contains__(self, name):
5648
has_entry_point = self.entry_points and self.get_entry_point(name)
5749
return has_entry_point or namespace in REGISTRY
5850

59-
def __call__(self, name, **kwargs):
51+
def __call__(
52+
self, name: str, func: Optional[Any] = None
53+
) -> Callable[[InFunc], InFunc]:
6054
"""Register a function for a given namespace. Same as Registry.register.
6155
6256
name (str): The name to register under the namespace.
6357
func (Any): Optional function to register (if not used as decorator).
6458
RETURNS (Callable): The decorator.
6559
"""
66-
return self.register(name, **kwargs)
60+
return self.register(name, func=func)
6761

68-
def register(self, name, **kwargs):
62+
def register(
63+
self, name: str, *, func: Optional[Any] = None
64+
) -> Callable[[InFunc], InFunc]:
6965
"""Register a function for a given namespace.
7066
7167
name (str): The name to register under the namespace.
@@ -77,12 +73,11 @@ def do_registration(func):
7773
_set(list(self.namespace) + [name], func)
7874
return func
7975

80-
func = kwargs.get("func")
8176
if func is not None:
8277
return do_registration(func)
8378
return do_registration
8479

85-
def get(self, name):
80+
def get(self, name: str) -> Any:
8681
"""Get the registered function for a given name.
8782
8883
name (str): The name.
@@ -100,14 +95,14 @@ def get(self, name):
10095
raise RegistryError(err.format(name, current_namespace, available))
10196
return _get(namespace)
10297

103-
def get_all(self):
98+
def get_all(self) -> Dict[str, Any]:
10499
"""Get a all functions for a given namespace.
105100
106101
namespace (Tuple[str]): The namespace to get.
107102
RETURNS (Dict[str, Any]): The functions, keyed by name.
108103
"""
109104
global REGISTRY
110-
result = OrderedDict()
105+
result = {}
111106
if self.entry_points:
112107
result.update(self.get_entry_points())
113108
for keys, value in REGISTRY.items():
@@ -117,7 +112,7 @@ def get_all(self):
117112
result[keys[-1]] = value
118113
return result
119114

120-
def get_entry_points(self):
115+
def get_entry_points(self) -> Dict[str, Any]:
121116
"""Get registered entry points from other packages for this namespace.
122117
123118
RETURNS (Dict[str, Any]): Entry points, keyed by name.
@@ -127,7 +122,7 @@ def get_entry_points(self):
127122
result[entry_point.name] = entry_point.load()
128123
return result
129124

130-
def get_entry_point(self, name, default=None):
125+
def get_entry_point(self, name: str, default: Optional[Any] = None) -> Any:
131126
"""Check if registered entry point is available for a given name in the
132127
namespace and load it. Otherwise, return the default value.
133128
@@ -141,7 +136,7 @@ def get_entry_point(self, name, default=None):
141136
return default
142137

143138

144-
def check_exists(*namespace):
139+
def check_exists(*namespace: str) -> bool:
145140
"""Check if a namespace exists.
146141
147142
*namespace (str): The namespace.
@@ -150,14 +145,14 @@ def check_exists(*namespace):
150145
return namespace in REGISTRY
151146

152147

153-
def _get(namespace):
148+
def _get(namespace: Sequence[str]) -> Any:
154149
"""Get the value for a given namespace.
155150
156-
namespace (Tuple[str]): The namespace.
157-
RETURNS: The value for the namespace.
151+
namespace (Sequence[str]): The namespace.
152+
RETURNS (Any): The value for the namespace.
158153
"""
159154
global REGISTRY
160-
if not all(isinstance(name, basestring_) for name in namespace):
155+
if not all(isinstance(name, str) for name in namespace):
161156
err = "Invalid namespace. Expected tuple of strings, but got: {}"
162157
raise ValueError(err.format(namespace))
163158
namespace = tuple(namespace)
@@ -167,16 +162,16 @@ def _get(namespace):
167162
return REGISTRY[namespace]
168163

169164

170-
def _get_all(namespace):
165+
def _get_all(namespace: Sequence[str]) -> Dict[Tuple[str, ...], Any]:
171166
"""Get all matches for a given namespace, e.g. ("a", "b", "c") and
172167
("a", "b") for namespace ("a", "b").
173168
174-
namespace (Tuple[str]): The namespace.
169+
namespace (Sequence[str]): The namespace.
175170
RETURNS (Dict[Tuple[str], Any]): All entries for the namespace, keyed
176171
by their full namespaces.
177172
"""
178173
global REGISTRY
179-
result = OrderedDict()
174+
result = {}
180175
for keys, value in REGISTRY.items():
181176
if len(namespace) <= len(keys) and all(
182177
namespace[i] == keys[i] for i in range(len(namespace))
@@ -185,21 +180,21 @@ def _get_all(namespace):
185180
return result
186181

187182

188-
def _set(namespace, func):
183+
def _set(namespace: Sequence[str], func: Any) -> None:
189184
"""Set a value for a given namespace.
190185
191-
namespace (Tuple[str]): The namespace.
186+
namespace (Sequence[str]): The namespace.
192187
func (Callable): The value to set.
193188
"""
194189
global REGISTRY
195190
REGISTRY[tuple(namespace)] = func
196191

197192

198-
def _remove(namespace):
193+
def _remove(namespace: Sequence[str]) -> Any:
199194
"""Remove a value for a given namespace.
200195
201-
namespace (Tuple[str]): The namespace.
202-
RETURNS: The removed value.
196+
namespace (Sequence[str]): The namespace.
197+
RETURNS (Any): The removed value.
203198
"""
204199
global REGISTRY
205200
namespace = tuple(namespace)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
importlib_metadata>=0.20; python_version < "3.8"
22
setuptools
33
pytest>=4.6.5
4+
mypy

setup.cfg

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[metadata]
2-
version = 1.0.0
2+
version = 2.0.0.dev0
33
description = Super lightweight function registries for your library
44
url = https://github.com/explosion/catalogue
55
author = Explosion
@@ -16,10 +16,7 @@ classifiers =
1616
Operating System :: POSIX :: Linux
1717
Operating System :: MacOS :: MacOS X
1818
Operating System :: Microsoft :: Windows
19-
Programming Language :: Python :: 2
20-
Programming Language :: Python :: 2.7
2119
Programming Language :: Python :: 3
22-
Programming Language :: Python :: 3.5
2320
Programming Language :: Python :: 3.6
2421
Programming Language :: Python :: 3.7
2522
Programming Language :: Python :: 3.8
@@ -29,7 +26,7 @@ classifiers =
2926
py_modules = catalogue
3027
zip_safe = true
3128
include_package_data = true
32-
python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
29+
python_requires = >=3.6
3330
install_requires =
3431
importlib_metadata>=0.20; python_version < "3.8"
3532

@@ -47,3 +44,7 @@ exclude =
4744
.env,
4845
.git,
4946
__pycache__,
47+
48+
[mypy]
49+
ignore_missing_imports = True
50+
no_implicit_optional = True

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# coding: utf-8
32

43
if __name__ == "__main__":
54
from setuptools import setup

test_catalogue.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# coding: utf8
2-
from __future__ import unicode_literals
3-
41
import pytest
52
import catalogue
63

0 commit comments

Comments
 (0)