Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 23c3017

Browse files
authored
Merge pull request #30 from IdentityPython/dldict
Dldict
2 parents d139f1f + 4c3c63b commit 23c3017

28 files changed

+2278
-1988
lines changed

.travis.yml

+1-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ addons:
1212
- rustc
1313
- cargo
1414
install:
15+
- pip install --upgrade pip
1516
- pip install codecov
1617
- pip install isort
1718
- pip install tox
@@ -24,12 +25,3 @@ after_success:
2425
- codecov
2526
notifications:
2627
email: false
27-
deploy:
28-
provider: pypi
29-
on:
30-
tags: true
31-
distributions: bdist_wheel
32-
skip_existing: true
33-
user: __token__
34-
password:
35-
secure: AH3jGGXVjV/oOlg4cOnsN7pURlZ7JMcd3Prr69Q++rxfsrmFpxCPtQLpO0LUNPisfyctoImpY64auNMHh20AHdlnvXQu8k/YFZCVcyK6N2d66wgJbO9AOT21N6IkFGyW11K3lYIHzURv9RsTEhzSkOhKmPUack5UhSJ+yAUTZXpt6iZqXBvmxMNzNiCLQdUmTMj4HxxkUVPabpef8PLqyDXvAxJxOCss+QcJVZuWFs85Niw0scTkU4SWz2lhOxeqQNg8s+CEgje2KaIoRy2kETywK53G3RFkSp5ytIJPp8RQK039laeal5yjMsWP4KlbDhHrywyNN7yS69FwPuLC41ppde5G054WcuJTm60Y2uckGu6L3oTBMHsAtSfZuEym/qfDngxYADA+xrATJQF5XSrCz13IiBnoz8Y9zI7t9s66PZSBHg99L85jM45M2kJYCDKxNPffJ/JzCnAMTP0yiBMEQ/UfguMDfJMw+6oSPzGcZHuQVzjLO5mUni71X528Psd/iEYCyN+Vi1QbvDZjbNo/oOLtvegOcnu/H1tGWkH4uEXsg2giqkld2hrZi6K3KfcpPtltuP66Z6ohMqcLegqGUNr8mPMP2I58p7if/6xLEu1e7MNZuoV459bnWepoNMMug2NLq/WIPCiGLNCyV4tdbzqcZQLNwjc5ruFLoz8=

src/oidcmsg/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
__author__ = 'Roland Hedberg'
2-
__version__ = '1.2.0'
1+
__author__ = "Roland Hedberg"
2+
__version__ = "1.3.0"
33

44
import os
55

6-
VERIFIED_CLAIM_PREFIX = '__verified'
6+
VERIFIED_CLAIM_PREFIX = "__verified"
77

88

99
def verified_claim_name(claim):
10-
return '{}_{}'.format(VERIFIED_CLAIM_PREFIX, claim)
10+
return "{}_{}".format(VERIFIED_CLAIM_PREFIX, claim)
1111

1212

1313
def proper_path(path):

src/oidcmsg/context.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -11,41 +11,41 @@
1111
def add_issuer(conf, issuer):
1212
res = {}
1313
for key, val in conf.items():
14-
if key == 'abstract_storage_cls':
14+
if key == "abstract_storage_cls":
1515
res[key] = val
1616
else:
1717
_val = copy.copy(val)
18-
_val['issuer'] = quote_plus(issuer)
18+
_val["issuer"] = quote_plus(issuer)
1919
res[key] = _val
2020
return res
2121

2222

2323
class OidcContext(ImpExp):
2424
parameter = {"keyjar": KeyJar, "issuer": None}
2525

26-
def __init__(self, config=None, keyjar=None, entity_id=''):
26+
def __init__(self, config=None, keyjar=None, entity_id=""):
2727
ImpExp.__init__(self)
2828
if config is None:
2929
config = {}
3030

3131
self.issuer = entity_id
3232
self.keyjar = self._keyjar(keyjar, conf=config, entity_id=entity_id)
3333

34-
def _keyjar(self, keyjar=None, conf=None, entity_id=''):
34+
def _keyjar(self, keyjar=None, conf=None, entity_id=""):
3535
if keyjar is None:
36-
if 'keys' in conf:
36+
if "keys" in conf:
3737
args = {k: v for k, v in conf["keys"].items() if k != "uri_path"}
3838
_keyjar = init_key_jar(**args)
3939
else:
4040
_keyjar = KeyJar()
41-
if 'jwks' in conf:
42-
_keyjar.import_jwks(conf['jwks'], '')
41+
if "jwks" in conf:
42+
_keyjar.import_jwks(conf["jwks"], "")
4343

44-
if '' in _keyjar and entity_id:
44+
if "" in _keyjar and entity_id:
4545
# make sure I have the keys under my own name too (if I know it)
46-
_keyjar.import_jwks_as_json(_keyjar.export_jwks_as_json(True, ''), entity_id)
46+
_keyjar.import_jwks_as_json(_keyjar.export_jwks_as_json(True, ""), entity_id)
4747

48-
_httpc_params = conf.get('httpc_params')
48+
_httpc_params = conf.get("httpc_params")
4949
if _httpc_params:
5050
_keyjar.httpc_params = _httpc_params
5151

src/oidcmsg/exception.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__author__ = 'Roland Hedberg'
1+
__author__ = "Roland Hedberg"
22

33

44
class OidcMsgError(Exception):

src/oidcmsg/impexp.py

+84-17
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from typing import Any
12
from typing import List
23
from typing import Optional
34

5+
from cryptojwt.utils import as_bytes
46
from cryptojwt.utils import importer
57
from cryptojwt.utils import qualified_name
68

@@ -9,19 +11,24 @@
911

1012
class ImpExp:
1113
parameter = {}
14+
special_load_dump = {}
15+
init_args = []
1216

1317
def __init__(self):
1418
pass
1519

16-
def _dump(self, cls, item, exclude_attributes: Optional[List[str]] = None) -> dict:
17-
if cls in [None, "", [], {}]:
18-
val = item
20+
def dump_attr(self, cls, item, exclude_attributes: Optional[List[str]] = None) -> dict:
21+
if cls in [None, 0, "", [], {}, bool, b'']:
22+
if cls == b'':
23+
val = as_bytes(item)
24+
else:
25+
val = item
1926
elif isinstance(item, Message):
2027
val = {qualified_name(item.__class__): item.to_dict()}
2128
elif cls == object:
2229
val = qualified_name(item)
2330
elif isinstance(cls, list):
24-
val = [self._dump(cls[0], v, exclude_attributes) for v in item]
31+
val = [self.dump_attr(cls[0], v, exclude_attributes) for v in item]
2532
else:
2633
val = item.dump(exclude_attributes=exclude_attributes)
2734

@@ -31,42 +38,98 @@ def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict:
3138
_exclude_attributes = exclude_attributes or []
3239
info = {}
3340
for attr, cls in self.parameter.items():
34-
if attr in _exclude_attributes:
41+
if attr in _exclude_attributes or attr in self.special_load_dump:
3542
continue
3643

3744
item = getattr(self, attr, None)
3845
if item is None:
3946
continue
4047

41-
info[attr] = self._dump(cls, item, exclude_attributes)
48+
info[attr] = self.dump_attr(cls, item, exclude_attributes)
49+
50+
for attr, d in self.special_load_dump.items():
51+
item = getattr(self, attr, None)
52+
if item:
53+
info[attr] = d["dump"](item, exclude_attributes=exclude_attributes)
4254

4355
return info
4456

45-
def _local_adjustments(self):
57+
def local_load_adjustments(self, **kwargs):
4658
pass
4759

48-
def _load(self, cls, item):
49-
if cls in [None, "", [], {}]:
50-
val = item
60+
def load_attr(
61+
self,
62+
cls: Any,
63+
item: dict,
64+
init_args: Optional[dict] = None,
65+
load_args: Optional[dict] = None,
66+
) -> Any:
67+
if load_args:
68+
_kwargs = {"load_args": load_args}
69+
_load_args = load_args
70+
else:
71+
_kwargs = {}
72+
_load_args = {}
73+
74+
if init_args:
75+
_kwargs["init_args"] = init_args
76+
77+
if cls in [None, 0, "", [], {}, bool, b'']:
78+
if cls == b'':
79+
val = as_bytes(item)
80+
else:
81+
val = item
5182
elif cls == object:
5283
val = importer(item)
5384
elif isinstance(cls, list):
54-
val = [cls[0]().load(v) for v in item]
85+
if isinstance(cls[0], str):
86+
_cls = importer(cls[0])
87+
else:
88+
_cls = cls[0]
89+
90+
if issubclass(_cls, ImpExp) and init_args:
91+
_args = {k: v for k, v in init_args.items() if k in _cls.init_args}
92+
else:
93+
_args = {}
94+
95+
val = [_cls(**_args).load(v, **_kwargs) for v in item]
5596
elif issubclass(cls, Message):
56-
val = cls().from_dict(item)
97+
_cls_name = list(item.keys())[0]
98+
_cls = importer(_cls_name)
99+
val = _cls().from_dict(item[_cls_name])
57100
else:
58-
val = cls().load(item)
101+
if issubclass(cls, ImpExp) and init_args:
102+
_args = {k: v for k, v in init_args.items() if k in cls.init_args}
103+
else:
104+
_args = {}
105+
106+
val = cls(**_args).load(item, **_kwargs)
59107

60108
return val
61109

62-
def load(self, item: dict):
110+
def load(self, item: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None):
111+
112+
if load_args:
113+
_kwargs = {"load_args": load_args}
114+
_load_args = load_args
115+
else:
116+
_kwargs = {}
117+
_load_args = {}
118+
119+
if init_args:
120+
_kwargs["init_args"] = init_args
121+
63122
for attr, cls in self.parameter.items():
64-
if attr not in item:
123+
if attr not in item or attr in self.special_load_dump:
65124
continue
66125

67-
setattr(self, attr, self._load(cls, item[attr]))
126+
setattr(self, attr, self.load_attr(cls, item[attr], **_kwargs))
127+
128+
for attr, func in self.special_load_dump.items():
129+
if attr in item:
130+
setattr(self, attr, func["load"](item[attr], **_kwargs))
68131

69-
self._local_adjustments()
132+
self.local_load_adjustments(**_load_args)
70133
return self
71134

72135
def flush(self):
@@ -78,6 +141,10 @@ def flush(self):
78141
for attr, cls in self.parameter.items():
79142
if cls is None:
80143
setattr(self, attr, None)
144+
elif cls == 0:
145+
setattr(self, attr, 0)
146+
elif cls is bool:
147+
setattr(self, attr, False)
81148
elif cls == "":
82149
setattr(self, attr, "")
83150
elif cls == []:

src/oidcmsg/item.py

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
from typing import List
2+
from typing import Optional
3+
4+
from oidcmsg.impexp import ImpExp
5+
from oidcmsg.message import Message
6+
from oidcmsg.storage import importer
7+
from oidcmsg.storage.utils import qualified_name
8+
9+
10+
class DLDict(ImpExp):
11+
parameter = {"db": {}}
12+
13+
def __init__(self, **kwargs):
14+
ImpExp.__init__(self)
15+
self.db = kwargs
16+
17+
def __setitem__(self, key: str, val):
18+
self.db[key] = val
19+
20+
def __getitem__(self, key: str):
21+
return self.db[key]
22+
23+
def __delitem__(self, key: str):
24+
del self.db[key]
25+
26+
def dump(self, exclude_attributes: Optional[List[str]] = None) -> dict:
27+
res = {}
28+
29+
for k, v in self.db.items():
30+
_class = qualified_name(v.__class__)
31+
res[k] = [_class, v.dump(exclude_attributes=exclude_attributes)]
32+
33+
return res
34+
35+
def load(
36+
self, spec: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None
37+
) -> "DLDict":
38+
if load_args:
39+
_kwargs = {"load_args": load_args}
40+
_load_args = {}
41+
else:
42+
_load_args = {}
43+
_kwargs = {}
44+
45+
if init_args:
46+
_kwargs["init_args"] = init_args
47+
48+
for attr, (_item_cls, _item) in spec.items():
49+
_cls = importer(_item_cls)
50+
51+
if issubclass(_cls, ImpExp) and init_args:
52+
_args = {k: v for k, v in init_args.items() if k in _cls.init_args}
53+
else:
54+
_args = {}
55+
56+
_x = _cls(**_args)
57+
_x.load(_item, **_kwargs)
58+
self.db[attr] = _x
59+
60+
self.local_load_adjustments(**_load_args)
61+
62+
return self
63+
64+
def keys(self):
65+
return self.db.keys()
66+
67+
def items(self):
68+
return self.db.items()
69+
70+
def values(self):
71+
return self.db.values()
72+
73+
def __contains__(self, item):
74+
return item in self.db
75+
76+
def get(self, item, default=None):
77+
return self.db.get(item, default)
78+
79+
def __len__(self):
80+
return len(self.db)
81+
82+
83+
def dump_dldict(item, exclude_attributes: Optional[List[str]] = None) -> dict:
84+
res = {}
85+
86+
for k, v in item.items():
87+
_class = qualified_name(v.__class__)
88+
if isinstance(v, Message):
89+
res[k] = [_class, v.to_dict()]
90+
else:
91+
res[k] = [_class, v.dump(exclude_attributes=exclude_attributes)]
92+
93+
return res
94+
95+
96+
def load_dldict(
97+
spec: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None
98+
) -> dict:
99+
db = {}
100+
101+
for attr, (_item_cls, _item) in spec.items():
102+
_class = importer(_item_cls)
103+
if issubclass(_class, Message):
104+
db[attr] = _class().from_dict(_item)
105+
else:
106+
if issubclass(_class, ImpExp) and init_args:
107+
_args = {k: v for k, v in init_args.items() if k in _class.init_args}
108+
else:
109+
_args = {}
110+
111+
db[attr] = _class(**_args).load(_item)
112+
113+
return db
114+
115+
116+
def dump_class_map(item, exclude_attributes: Optional[List[str]] = None) -> dict:
117+
_dump = {}
118+
for key, val in item.items():
119+
if isinstance(val, str):
120+
_dump[key] = val
121+
else:
122+
_dump[key] = qualified_name(val)
123+
return _dump
124+
125+
126+
def load_class_map(
127+
spec: dict, init_args: Optional[dict] = None, load_args: Optional[dict] = None
128+
) -> dict:
129+
_item = {}
130+
for key, val in spec.items():
131+
_item[key] = importer(val)
132+
return _item

0 commit comments

Comments
 (0)