Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
serializer_utils
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Rolf van Kleef
serializer_utils
Commits
00e99d9c
Verified
Commit
00e99d9c
authored
Nov 08, 2018
by
Rolf van Kleef
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed defaulting
parent
5d9c0d96
Pipeline
#1260
canceled with stages
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
131 additions
and
15 deletions
+131
-15
dict_deserializer/deserializer.py
dict_deserializer/deserializer.py
+28
-15
test_DirectoryExample.py
test_DirectoryExample.py
+103
-0
No files found.
dict_deserializer/deserializer.py
View file @
00e99d9c
...
...
@@ -86,22 +86,28 @@ class Deserializable(metaclass=BaseMeta):
return
fields
def
get_deserialization_class
(
t
,
d
,
try_all
=
False
):
def
get_deserialization_classes
(
t
,
d
,
try_all
=
True
)
->
List
[
type
]:
candidates
=
[]
for
sc
in
t
.
__subclasses__
():
if
hasattr
(
sc
,
'_discriminators'
):
for
discriminator
in
sc
.
_discriminators
:
if
not
discriminator
.
check
(
d
):
# Invalid
break
else
:
# All were valid
try
:
return
get_deserialization_class
(
sc
,
t
,
try_all
)
candidates
.
extend
(
get_deserialization_classes
(
sc
,
t
,
try_all
)
)
except
TypeError
as
e
:
if
not
try_all
:
raise
e
return
t
if
not
getattr
(
t
,
'_abstract'
,
True
):
candidates
.
append
(
t
)
return
candidates
def
deserialize
(
rule
:
Rule
,
data
,
try_all
=
False
,
key
=
None
):
def
deserialize
(
rule
:
Rule
,
data
,
try_all
=
True
,
key
=
'$'
):
# In case of primitive types, attempt to assign.
try
:
return
rule
.
validate
(
key
,
data
)
...
...
@@ -111,7 +117,10 @@ def deserialize(rule: Rule, data, try_all=False, key=None):
if
type
(
rule
.
type
)
is
type
(
Union
):
for
arg
in
rule
.
type
.
__args__
:
try
:
return
deserialize
(
Rule
(
arg
),
data
,
try_all
,
key
)
v
=
deserialize
(
Rule
(
arg
),
data
,
try_all
,
key
)
if
v
is
None
:
v
=
rule
.
default
return
v
except
TypeError
:
pass
raise
TypeError
(
'{} did not match any of {} for key {}.'
.
format
(
type
(
data
),
rule
.
type
.
__args__
,
key
))
...
...
@@ -126,23 +135,27 @@ def deserialize(rule: Rule, data, try_all=False, key=None):
t
=
rule
.
type
.
__args__
[
0
]
result
=
[]
for
i
,
v
in
enumerate
(
data
):
result
.
append
(
deserialize
(
Rule
(
t
),
v
,
try_all
,
i
))
result
.
append
(
deserialize
(
Rule
(
t
),
v
,
try_all
,
'{}.{}'
.
format
(
key
,
i
)
))
return
result
if
issubclass
(
rule
.
type
,
Deserializable
):
if
not
isinstance
(
data
,
dict
):
raise
TypeError
(
'Cannot deserialize non-dict into class.'
)
cl
s
=
get_deserialization_clas
s
(
rule
.
type
,
data
,
try_all
)
cl
asses
=
get_deserialization_classe
s
(
rule
.
type
,
data
,
try_all
)
if
hasattr
(
cls
,
'_abstract'
)
and
cls
.
_abstract
:
raise
TypeError
(
'Cannot deserialize into {}: is abstract.'
.
format
(
cls
.
__name__
))
for
cls
in
classes
:
try
:
instance
=
cls
()
for
k
,
r
in
cls
.
get_attrs
().
items
():
v
=
deserialize
(
r
,
data
[
k
]
if
k
in
data
else
r
.
default
,
try_all
,
key
=
'{}.{}'
.
format
(
key
,
k
))
setattr
(
instance
,
k
,
v
)
instance
=
cls
()
for
k
,
r
in
cls
.
get_attrs
().
items
()
:
v
=
deserialize
(
r
,
data
[
k
]
if
k
in
data
else
r
.
default
,
try_all
,
key
=
k
)
setattr
(
instance
,
k
,
v
)
return
instance
except
TypeError
as
e
:
if
not
try_all
:
raise
e
r
eturn
instance
r
aise
TypeError
(
'Unable to find matching non-abstract (sub)type of {} with key {}.'
.
format
(
rule
.
type
,
key
))
raise
TypeError
(
'Unable to find a deserialization candidate for {} in {}.'
.
format
(
data
,
rule
))
\ No newline at end of file
raise
TypeError
(
'Unable to find a deserialization candidate for {} with key {}.'
.
format
(
rule
,
key
))
\ No newline at end of file
test_DirectoryExample.py
0 → 100644
View file @
00e99d9c
import
unittest
from
typing
import
List
,
Optional
from
dict_deserializer.annotations
import
abstract
from
dict_deserializer.deserializer
import
Deserializable
,
deserialize
,
Rule
@
abstract
class
Object
(
Deserializable
):
def
__init__
(
self
,
name
=
None
):
self
.
name
=
name
name
:
str
def
__repr__
(
self
):
return
'Object(name="{}")'
.
format
(
self
.
name
)
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
Object
)
and
other
.
name
==
self
.
name
class
User
(
Object
):
def
__init__
(
self
,
full_name
=
None
,
calling_name
=
None
,
*
args
,
**
kwargs
):
super
(
User
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
full_name
=
full_name
self
.
calling_name
=
calling_name
full_name
:
str
calling_name
:
Optional
[
str
]
=
'Unknown'
def
__repr__
(
self
):
if
self
.
calling_name
is
None
:
return
'User(super={}, full_name="{}")'
\
.
format
(
super
(
User
,
self
).
__repr__
(),
self
.
full_name
)
return
'User(super={}, full_name="{}", calling_name="{}")'
\
.
format
(
super
(
User
,
self
).
__repr__
(),
self
.
full_name
,
self
.
calling_name
)
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
User
)
and
super
(
User
,
self
).
__eq__
(
other
)
and
\
other
.
full_name
==
self
.
full_name
and
\
other
.
calling_name
==
self
.
calling_name
class
Group
(
Object
):
def
__init__
(
self
,
members
=
None
,
*
args
,
**
kwargs
):
super
(
Group
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
members
=
members
members
:
List
[
Object
]
def
__repr__
(
self
):
return
'Group(super={}, members=[{}])'
\
.
format
(
super
(
Group
,
self
).
__repr__
(),
','
.
join
([
m
.
__repr__
()
for
m
in
self
.
members
]))
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
Group
)
and
super
(
Group
,
self
).
__eq__
(
other
)
\
and
other
.
members
==
self
.
members
class
TestLists
(
unittest
.
TestCase
):
def
test_CorrectDeserializationForNestedWithTypeUnionsAndLists
(
self
):
self
.
assertEqual
(
Group
(
name
=
'IAPC'
,
members
=
[
User
(
name
=
'Rolf'
,
full_name
=
'Rolf van Kleef'
,
calling_name
=
'Unknown'
),
Group
(
name
=
'Syscom'
,
members
=
[
User
(
name
=
'Kevin'
,
full_name
=
'Kevin Alberts'
,
calling_name
=
'Kevin'
),
]),
],
),
deserialize
(
Rule
(
Object
),
{
'name'
:
'IAPC'
,
'members'
:
[
{
'name'
:
'Rolf'
,
'full_name'
:
'Rolf van Kleef'
},
{
'name'
:
'Syscom'
,
'members'
:
[
{
'name'
:
'Kevin'
,
'full_name'
:
'Kevin Alberts'
,
'calling_name'
:
'Kevin'
},
]},
],
})
)
def
test_FailDeserializeWithInvalidTypes
(
self
):
with
self
.
assertRaises
(
TypeError
):
deserialize
(
Rule
(
Object
),
{
'name'
:
'Karel'
,
'full_name'
:
0.0
,
})
with
self
.
assertRaises
(
TypeError
):
deserialize
(
Rule
(
Object
),
{
'name'
:
'Rolf'
,
'full_name'
:
'Rolf van Kleef'
,
'calling_name'
:
False
,
})
def
test_DeserializeIntoAbstract
(
self
):
with
self
.
assertRaises
(
TypeError
)
as
ctx
:
deserialize
(
Rule
(
Object
),
{
'name'
:
'Test'
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment