/
registry.py
121 lines (97 loc) · 4.33 KB
/
registry.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Licensed under a 3-clause BSD style license - see LICENSE.rst
"""Public interface functions for registering and retrieving from registries"""
from . import bandpasses
from . import magsystems
from . import models
__all__ = ['register_loader', 'register']
def _get_registry(data_class):
if issubclass(data_class, bandpasses.Bandpass):
return bandpasses._BANDPASSES
elif issubclass(data_class, magsystems.MagSystem):
return magsystems._MAGSYSTEMS
elif issubclass(data_class, models.Source):
return models._SOURCES
raise ValueError("No registry for type: {}".format(data_class))
def register_loader(data_class, name, func, args=None,
version=None, meta=None, force=False):
"""Register a data reading function.
Parameters
----------
data_class : classobj
The class of the object that the loader returns.
name : str
The data identifier.
func : callable
The function to read in the data. Must accept a name and version
keyword argument.
args : list, optional
Arguments to pass to the function. Default is an empty list.
version : str, optional
Sub-version of name, if desired. Use formats such as ``'1'``,
``'1.0'``, ``'1.0.0'``, etc. Default is `None`.
force : bool, optional
Whether to override any existing function if already present.
meta : dict, optional
Metadata describing this loader. Default is an empty dictionary.
"""
_get_registry(data_class).register_loader(
name, func, args=args, version=version, meta=meta, force=force)
def register(instance, name=None, data_class=None, force=False):
"""Register a class instance.
Parameters
----------
instance : object
The object to be registered.
name : str, optional
Identifier. If `None`, the name is taken from the `name` attribute
of the instance, if it exists and is a string.
data_class : classobj, optional
If given, the instance is registered as an instance of this class
rather the the class of the instance itself. Use this for registering
subclasses when you wish them to be accessible from their superclass.
force : bool, optional
Whether to override any existing instance of the same name. Note: this
may not play well with versioned instances.
"""
if data_class is None:
data_class = instance.__class__
_get_registry(data_class).register(instance, name=name, force=force)
def retrieve(data_class, name, version=None):
"""Retrieve a class instance from a registered identifier.
Parameters
----------
data_class : classobj
The class of the object requested.
name : str
Identifier of the specific instance. `name` is case-independent,
however, note the following: Internally, names are stored in lowercase.
The retrieval is first tried assuming the requested name is also
lowercase, then `name` is converted to lowercase. So it should be
slightly faster to use lowercase names everywhere.
version : str
Sub-identifier. If `None`, default to highest or only version.
Returns
-------
instance : data_class (or subclass thereof)
Notes
-----
**Precedence** The following are tried in this order:
1. If `name` is already an instance of `data_class`
(rather than a string), it is immediately returned.
2. If (`data_class`, `name`) is already in the registry,
that instance is returned.
3. If there is a loader defined for (`data_class`, `name`), it is used
to create an instance, save it to the registry and return it.
4. An Exception is raised listing the available registered names for
the requested data class.
**Versioning** There is support for multiple versions of data for the
same `name`.
1. If `version` is specified, the registry and its loaders are
searched for (`data_class`, `name`, `version`).
2. If `version` is not specified but there are registered loaders for
(`data_class`, `name`, `version`), the latest version is used,
and both (`data_class`, `name`) and (`data_class`, `name`,
`version`) are saved to the registry. "Latest" is defined by
string comparision.
"""
_get_registry(data_class).retrieve(name, version=version)