Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
C
caosdb-advanced-user-tools
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
caosdb
Software
caosdb-advanced-user-tools
Commits
61b2cd48
Verified
Commit
61b2cd48
authored
1 year ago
by
Daniel Hornung
Browse files
Options
Downloads
Patches
Plain Diff
ENH: jsex: UI schemas implemented for merging and arraying
parent
17e1efd5
No related branches found
Branches containing commit
No related tags found
Tags containing commit
2 merge requests
!89
ENH: JsonSchemaExporter accepts do_not_create parameter.
,
!85
more jsonschema export
Pipeline
#43532
failed
1 year ago
Stage: setup
Stage: cert
Stage: style
Stage: unittest
Stage: integrationtest
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/caosadvancedtools/json_schema_exporter.py
+40
-5
40 additions, 5 deletions
src/caosadvancedtools/json_schema_exporter.py
unittests/test_json_schema_exporter.py
+52
-0
52 additions, 0 deletions
unittests/test_json_schema_exporter.py
with
92 additions
and
5 deletions
src/caosadvancedtools/json_schema_exporter.py
+
40
−
5
View file @
61b2cd48
...
...
@@ -25,7 +25,7 @@ The scope of this json schema is the automatic generation of user interfaces.
"""
from
collections
import
OrderedDict
from
typing
import
Any
,
Dict
,
Iterable
,
List
,
Optional
,
Tuple
,
Union
from
typing
import
Any
,
Dict
,
Iterable
,
List
,
Optional
,
Sequence
,
Tuple
,
Union
import
linkahead
as
db
from
linkahead.common.datatype
import
get_list_datatype
,
is_list_datatype
...
...
@@ -409,7 +409,7 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
return
exporter
.
recordtype_to_json_schema
(
rt
,
rjsf_uischema
=
rjsf_uischema
)
def
make_array
(
schema
:
dict
)
->
dict
:
def
make_array
(
schema
:
dict
,
rjsf_uischema
:
dict
=
None
)
->
Union
[
dict
,
tuple
[
dict
,
dict
]]
:
"""
Create an array of the given schema.
The result will look like this:
...
...
@@ -428,21 +428,33 @@ Parameters
schema : dict
The JSON schema which shall be packed into an array.
rjsf_uischema : dict, optional
A react-jsonschema-forms ui schema that shall be wrapped as well.
Returns
-------
out
: dict
schema
: dict
A JSON schema dict with a top-level array which contains instances of the given schema.
ui_schema : dict, optional
The wrapped ui schema. Only returned if ``rjsf_uischema`` is given as parameter.
"""
result
=
{
"
type
"
:
"
array
"
,
"
items
"
:
schema
,
"
$schema
"
:
"
https://json-schema.org/draft/2020-12/schema
"
,
}
if
rjsf_uischema
is
not
None
:
ui_schema
=
{
"
items
"
:
rjsf_uischema
}
return
result
,
ui_schema
return
result
def
merge_schemas
(
schemas
:
Union
[
Dict
[
str
,
dict
],
Iterable
[
dict
]])
->
dict
:
def
merge_schemas
(
schemas
:
Union
[
Dict
[
str
,
dict
],
Iterable
[
dict
]],
rjsf_uischemas
:
Union
[
Dict
[
str
,
dict
],
Sequence
[
dict
]]
=
None
)
->
(
Union
[
dict
,
Tuple
[
dict
,
dict
]]):
"""
Merge the given schemata into a single schema.
The result will look like this:
...
...
@@ -469,24 +481,45 @@ schemas : dict[str, dict] | Iterable[dict]
be used as property names, otherwise the titles of the submitted schemata. If they have no title,
numbers will be used as a fallback. Note that even with a dict, the original schema
'
s
"
title
"
is
not changed.
rjsf_uischemas : dict[str, dict] | Iterable[dict], optional
If given, also merge the react-jsonschema-forms from this argument and return as the second return
value. If ``schemas`` is a dict, this parameter must also be a dict, if ``schemas`` is only an
iterable, this paramater must support numerical indexing.
Returns
-------
out
: dict
schema
: dict
A JSON schema dict with a top-level object which contains the given schemata as properties.
uischema : dict
If ``rjsf_uischemas`` was given, this contains the merged UI schemata.
"""
sub_schemas
:
dict
[
str
,
dict
]
=
OrderedDict
()
required
=
[]
ui_schema
=
None
if
isinstance
(
schemas
,
dict
):
sub_schemas
=
schemas
required
=
[
str
(
k
)
for
k
in
schemas
.
keys
()]
if
rjsf_uischemas
is
not
None
:
if
not
isinstance
(
rjsf_uischemas
,
dict
):
raise
ValueError
(
"
Parameter `rjsf_uischemas` must be a dict, because `schemas` is
"
f
"
as well, but it is a
{
type
(
rjsf_uischemas
)
}
.
"
)
ui_schema
=
{
k
:
rjsf_uischemas
[
k
]
for
k
in
schemas
.
keys
()}
else
:
for
i
,
schema
in
enumerate
(
schemas
,
start
=
1
):
title
=
schema
.
get
(
"
title
"
,
str
(
i
))
sub_schemas
[
title
]
=
schema
required
.
append
(
title
)
if
rjsf_uischemas
is
not
None
:
if
not
isinstance
(
rjsf_uischemas
,
Sequence
):
raise
ValueError
(
"
Parameter `rjsf_uischemas` must be a sequence, because `schemas`
"
f
"
is as well, but it is a
{
type
(
rjsf_uischemas
)
}
.
"
)
ui_schema
=
{}
for
i
,
title
in
enumerate
(
sub_schemas
.
keys
()):
ui_schema
[
title
]
=
rjsf_uischemas
[
i
]
# ui_schema = {"index": ui_schema}
result
=
{
"
type
"
:
"
object
"
,
...
...
@@ -496,4 +529,6 @@ out : dict
"
$schema
"
:
"
https://json-schema.org/draft/2020-12/schema
"
,
}
if
ui_schema
is
not
None
:
return
result
,
ui_schema
return
result
This diff is collapsed.
Click to expand it.
unittests/test_json_schema_exporter.py
+
52
−
0
View file @
61b2cd48
...
...
@@ -883,3 +883,55 @@ RT4:
assert
(
str
(
uischema
[
"
RT4
"
])
==
"
{
'
RT21
'
: {
'
items
'
: {
'
RT1
'
: {
'
ui:widget
'
:
'
checkboxes
'
,
"
"'
ui:options
'
: {
'
inline
'
: True}}}}}
"
)
@patch
(
"
linkahead.execute_query
"
,
new
=
Mock
(
side_effect
=
_mock_execute_query
))
def
test_uischema
():
model_str
=
"""
RT1:
RT2:
obligatory_properties:
RT1:
datatype: LIST<RT1>
RT3:
obligatory_properties:
RT1:
datatype: LIST<RT1>
"""
model
=
parse_model_from_string
(
model_str
)
uischema_2
=
{}
schema_2
=
rtjs
(
model
.
get_deep
(
"
RT2
"
),
additional_properties
=
False
,
do_not_create
=
[
"
RT1
"
],
multiple_choice
=
[
"
RT1
"
],
rjsf_uischema
=
uischema_2
)
uischema_3
=
{}
schema_3
=
rtjs
(
model
.
get_deep
(
"
RT3
"
),
additional_properties
=
False
,
do_not_create
=
[
"
RT1
"
],
multiple_choice
=
[
"
RT1
"
],
rjsf_uischema
=
uischema_3
)
# Merging #################################################################
# Using dictionaries
schemas_dict
=
{
"
schema_2
"
:
schema_2
,
"
schema_3
"
:
schema_3
}
uischemas_dict
=
{
"
schema_2
"
:
uischema_2
[
"
RT2
"
],
"
schema_3
"
:
uischema_3
[
"
RT3
"
]}
merged_dict
,
merged_dict_ui
=
jsex
.
merge_schemas
(
schemas_dict
,
uischemas_dict
)
assert
merged_dict_ui
[
"
schema_2
"
]
==
merged_dict_ui
[
"
schema_3
"
]
assert
(
str
(
merged_dict_ui
[
"
schema_2
"
])
==
"
{
'
RT1
'
: {
'
ui:widget
'
:
'
checkboxes
'
,
'
ui:options
'
: {
'
inline
'
: True}}}
"
)
# Using lists
schemas_list
=
[
schema_2
,
schema_3
]
uischemas_list
=
[
uischema_2
[
"
RT2
"
],
uischema_3
[
"
RT3
"
]]
merged_list
,
merged_list_ui
=
jsex
.
merge_schemas
(
schemas_list
,
uischemas_list
)
assert
merged_list
[
"
properties
"
][
"
RT2
"
]
==
merged_dict
[
"
properties
"
][
"
schema_2
"
]
assert
merged_list_ui
[
"
RT2
"
]
==
merged_list_ui
[
"
RT3
"
]
assert
merged_list_ui
[
"
RT2
"
]
==
merged_dict_ui
[
"
schema_2
"
]
# Asserting failures
with
raises
(
ValueError
):
jsex
.
merge_schemas
(
schemas_dict
,
uischemas_list
)
with
raises
(
ValueError
):
jsex
.
merge_schemas
(
schemas_list
,
uischemas_dict
)
# Arraying ################################################################
array2
,
array2_ui
=
jsex
.
make_array
(
schema_2
,
uischema_2
[
"
RT2
"
])
assert
array2
[
"
items
"
]
==
schema_2
assert
array2_ui
[
"
items
"
]
==
uischema_2
[
"
RT2
"
]
assert
(
str
(
array2_ui
[
"
items
"
])
==
"
{
'
RT1
'
: {
'
ui:widget
'
:
'
checkboxes
'
,
'
ui:options
'
: {
'
inline
'
: True}}}
"
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment