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
e8caa024
Verified
Commit
e8caa024
authored
1 year ago
by
Daniel Hornung
Browse files
Options
Downloads
Patches
Plain Diff
ENH: jsex: Allowing to update schemata with any other dicts.
parent
c4fdfba2
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.
,
!86
ENH: jsex: Allowing to update schemata with any other dicts.
Pipeline
#43655
passed
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
+100
-6
100 additions, 6 deletions
src/caosadvancedtools/json_schema_exporter.py
unittests/test_json_schema_exporter.py
+67
-1
67 additions, 1 deletion
unittests/test_json_schema_exporter.py
with
167 additions
and
7 deletions
src/caosadvancedtools/json_schema_exporter.py
+
100
−
6
View file @
e8caa024
...
...
@@ -39,6 +39,8 @@ class JsonSchemaExporter:
name_property_for_new_records
:
bool
=
False
,
description_property_for_new_records
:
bool
=
False
,
additional_options_for_text_props
:
dict
=
None
,
additional_json_schema
:
Dict
[
str
,
dict
]
=
None
,
additional_ui_schema
:
Dict
[
str
,
dict
]
=
None
,
units_in_description
:
bool
=
True
,
do_not_create
:
List
[
str
]
=
None
,
do_not_retrieve
:
List
[
str
]
=
None
,
...
...
@@ -61,6 +63,10 @@ class JsonSchemaExporter:
additional_options_for_text_props : dict, optional
Dictionary containing additional
"
pattern
"
or
"
format
"
options for
string-typed properties. Optional, default is empty.
additional_json_schema : dict[str, dict], optional
Additional schema content for elements of the given names.
additional_ui_schema : dict[str, dict], optional
Additional ui schema content for elements of the given names.
units_in_description : bool, optional
Whether to add the unit of a LinkAhead property (if it has any) to the
description of the corresponding schema entry. If set to false, an
...
...
@@ -83,6 +89,10 @@ class JsonSchemaExporter:
"""
if
not
additional_options_for_text_props
:
additional_options_for_text_props
=
{}
if
not
additional_json_schema
:
additional_json_schema
=
{}
if
not
additional_ui_schema
:
additional_ui_schema
=
{}
if
not
do_not_create
:
do_not_create
=
[]
if
not
do_not_retrieve
:
...
...
@@ -94,6 +104,8 @@ class JsonSchemaExporter:
self
.
_name_property_for_new_records
=
name_property_for_new_records
self
.
_description_property_for_new_records
=
description_property_for_new_records
self
.
_additional_options_for_text_props
=
additional_options_for_text_props
self
.
_additional_json_schema
=
additional_json_schema
self
.
_additional_ui_schema
=
additional_ui_schema
self
.
_units_in_description
=
units_in_description
self
.
_do_not_create
=
do_not_create
self
.
_do_not_retrieve
=
do_not_retrieve
...
...
@@ -117,11 +129,18 @@ class JsonSchemaExporter:
def
_make_segment_from_prop
(
self
,
prop
:
db
.
Property
)
->
Tuple
[
OrderedDict
,
dict
]:
"""
Return the JSON Schema and ui schema segments for the given property.
The result may either be a simple json schema segment, such as a `string
<https://json-schema.org/understanding-json-schema/reference/string>`_ element (or another
simple type), a combination such as `anyOf
<https://json-schema.org/understanding-json-schema/reference/combining#anyof>`_ or an `array
<https://json-schema.org/understanding-json-schema/reference/array>`_ element
Parameters
----------
prop : db.Property
The property to be transformed.
"""
json_prop
=
OrderedDict
()
ui_schema
:
dict
=
{}
if
prop
.
datatype
==
db
.
TEXT
or
prop
.
datatype
==
db
.
DATETIME
:
text_format
=
None
...
...
@@ -139,9 +158,9 @@ class JsonSchemaExporter:
# options list.
text_format
=
[
"
date
"
,
"
date-time
"
]
return
self
.
_make_text_property
(
prop
.
description
,
text_format
,
text_pattern
),
ui_schema
json_prop
=
self
.
_make_text_property
(
prop
.
description
,
text_format
,
text_pattern
)
return
self
.
_customize
(
json_prop
,
ui_schema
,
prop
)
json_prop
=
OrderedDict
()
if
prop
.
description
:
json_prop
[
"
description
"
]
=
prop
.
description
if
self
.
_units_in_description
and
prop
.
unit
:
...
...
@@ -216,13 +235,31 @@ class JsonSchemaExporter:
raise
ValueError
(
f
"
Unknown or no property datatype. Property
{
prop
.
name
}
with type
{
prop
.
datatype
}
"
)
return
json_prop
,
ui_schema
return
self
.
_customize
(
json_prop
,
ui_schema
,
prop
)
@staticmethod
def
_make_text_property
(
description
=
""
,
text_format
=
None
,
text_pattern
=
None
):
prop
=
{
def
_make_text_property
(
description
=
""
,
text_format
=
None
,
text_pattern
=
None
)
->
OrderedDict
:
"""
Create a text element.
Can be a `string <https://json-schema.org/understanding-json-schema/reference/string>`_
element or an `anyOf
<https://json-schema.org/understanding-json-schema/reference/combining#anyof>`_ combination
thereof.
Example:
.. code-block:: json
{
"
type
"
:
"
string
"
,
"
description
"
:
"
Some description
"
,
"
pattern
"
:
"
[0-9]{2..4}-[0-9]{2-4}
"
,
"
format
"
:
"
hostname
"
,
}
"""
prop
:
OrderedDict
[
str
,
Union
[
str
,
list
]]
=
OrderedDict
({
"
type
"
:
"
string
"
}
}
)
if
description
:
prop
[
"
description
"
]
=
description
if
text_format
is
not
None
:
...
...
@@ -265,6 +302,22 @@ class JsonSchemaExporter:
def
_make_segment_from_recordtype
(
self
,
rt
:
db
.
RecordType
)
->
Tuple
[
OrderedDict
,
dict
]:
"""
Return Json schema and uischema segments for the given RecordType.
The result is an element of type `object
<https://json-schema.org/understanding-json-schema/reference/object>`_ and typically
contains more properties:
.. code-block:: json
{
"
type
"
:
"
object
"
,
"
title
"
:
"
MyRecordtypeName
"
,
"
properties
"
: {
"
number
"
: {
"
type
"
:
"
number
"
},
"
street_name
"
: {
"
type
"
:
"
string
"
},
"
street_type
"
: {
"
enum
"
: [
"
Street
"
,
"
Avenue
"
,
"
Boulevard
"
] }
}
}
"""
schema
:
OrderedDict
[
str
,
Any
]
=
OrderedDict
({
"
type
"
:
"
object
"
...
...
@@ -299,6 +352,38 @@ class JsonSchemaExporter:
return
schema
,
ui_schema
def
_customize
(
self
,
schema
:
OrderedDict
,
ui_schema
:
dict
,
entity
:
db
.
Entity
=
None
)
->
(
Tuple
[
OrderedDict
,
dict
]):
"""
Generic customization method.
Walk over the available customization stores and apply all applicable ones. No specific order is
guaranteed (as of now).
Parameters
----------
schema, ui_schema : dict
The input schemata.
entity: db.Entity : , optional
An Entity object, may be useful in the future for customizers.
Returns
-------
out : Tuple[dict, dict]
The modified input schemata.
"""
name
=
schema
.
get
(
"
title
"
,
None
)
if
entity
and
entity
.
name
:
name
=
entity
.
name
for
key
,
add_schema
in
self
.
_additional_json_schema
.
items
():
if
key
==
name
:
schema
.
update
(
add_schema
)
for
key
,
add_schema
in
self
.
_additional_ui_schema
.
items
():
if
key
==
name
:
ui_schema
.
update
(
add_schema
)
return
schema
,
ui_schema
def
recordtype_to_json_schema
(
self
,
rt
:
db
.
RecordType
,
rjsf
:
bool
=
False
)
->
Union
[
dict
,
Tuple
[
dict
,
dict
]]:
"""
Create a jsonschema from a given RecordType that can be used, e.g., to
...
...
@@ -327,6 +412,7 @@ class JsonSchemaExporter:
schema
[
"
$schema
"
]
=
"
https://json-schema.org/draft/2020-12/schema
"
if
rt
.
description
:
schema
[
"
description
"
]
=
rt
.
description
schema
,
inner_uischema
=
self
.
_customize
(
schema
,
inner_uischema
,
rt
)
if
rjsf
:
uischema
=
{}
...
...
@@ -340,6 +426,8 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
name_property_for_new_records
:
bool
=
False
,
description_property_for_new_records
:
bool
=
False
,
additional_options_for_text_props
:
Optional
[
dict
]
=
None
,
additional_json_schema
:
Dict
[
str
,
dict
]
=
None
,
additional_ui_schema
:
Dict
[
str
,
dict
]
=
None
,
units_in_description
:
bool
=
True
,
do_not_create
:
List
[
str
]
=
None
,
do_not_retrieve
:
List
[
str
]
=
None
,
...
...
@@ -369,6 +457,10 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
additional_options_for_text_props : dict, optional
Dictionary containing additional
"
pattern
"
or
"
format
"
options for
string-typed properties. Optional, default is empty.
additional_json_schema : dict[str, dict], optional
Additional schema content for elements of the given names.
additional_ui_schema : dict[str, dict], optional
Additional ui schema content for elements of the given names.
units_in_description : bool, optional
Whether to add the unit of a LinkAhead property (if it has any) to the
description of the corresponding schema entry. If set to false, an
...
...
@@ -406,6 +498,8 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
name_property_for_new_records
=
name_property_for_new_records
,
description_property_for_new_records
=
description_property_for_new_records
,
additional_options_for_text_props
=
additional_options_for_text_props
,
additional_json_schema
=
additional_json_schema
,
additional_ui_schema
=
additional_ui_schema
,
units_in_description
=
units_in_description
,
do_not_create
=
do_not_create
,
do_not_retrieve
=
do_not_retrieve
,
...
...
This diff is collapsed.
Click to expand it.
unittests/test_json_schema_exporter.py
+
67
−
1
View file @
e8caa024
...
...
@@ -99,7 +99,7 @@ RT3:
elif
query_string
==
"
SELECT name, id FROM FILE
"
:
return
all_files
else
:
print
(
f
"
Query string:
{
query_string
}
"
)
#
print(f"Query string: {query_string}")
if
unique
is
True
:
return
db
.
Entity
()
return
db
.
Container
()
...
...
@@ -929,3 +929,69 @@ RT3:
assert
array2_ui
[
"
items
"
]
==
uischema_2
assert
(
str
(
array2_ui
[
"
items
"
])
==
"
{
'
RT1
'
: {
'
ui:widget
'
:
'
checkboxes
'
,
'
ui:options
'
: {
'
inline
'
: True}}}
"
)
def
test_schema_customization_with_dicts
():
"""
Testing the ``additional_json_schema`` and ``additional_ui_schema`` parameters.
"""
model_str
=
"""
RT1:
RT21:
obligatory_properties:
RT1:
datatype: LIST<RT1>
text:
datatype: TEXT
description: Some description
RT3:
obligatory_properties:
number:
datatype: INTEGER
"""
model
=
parse_model_from_string
(
model_str
)
custom_schema
=
{
"
RT21
"
:
{
"
minProperties
"
:
2
,
},
"
text
"
:
{
"
format
"
:
"
email
"
,
"
description
"
:
"
Better description.
"
,
},
"
number
"
:
{
"
minimum
"
:
0
,
"
exclusiveMaximum
"
:
100
,
},
}
custom_ui_schema
=
{
"
text
"
:
{
"
ui:help
"
:
"
Hint: keep it short.
"
,
"
ui:widget
"
:
"
password
"
,
},
"
number
"
:
{
"
ui:order
"
:
2
,
}
}
schema_21
,
uischema_21
=
rtjs
(
model
.
get_deep
(
"
RT21
"
),
additional_properties
=
False
,
do_not_create
=
[
"
RT1
"
],
rjsf
=
True
)
assert
len
(
uischema_21
)
==
0
assert
schema_21
[
"
properties
"
][
"
text
"
][
"
description
"
]
==
"
Some description
"
assert
"
format
"
not
in
schema_21
[
"
properties
"
][
"
text
"
]
schema_21
,
uischema_21
=
rtjs
(
model
.
get_deep
(
"
RT21
"
),
additional_properties
=
False
,
additional_json_schema
=
custom_schema
,
additional_ui_schema
=
custom_ui_schema
,
do_not_create
=
[
"
RT1
"
],
rjsf
=
True
)
assert
(
str
(
uischema_21
)
==
"
{
'
text
'
: {
'
ui:help
'
:
'
Hint: keep it short.
'
,
'
ui:widget
'
:
'
password
'
}}
"
)
assert
schema_21
[
"
properties
"
][
"
text
"
][
"
description
"
]
==
"
Better description.
"
assert
schema_21
[
"
properties
"
][
"
text
"
].
get
(
"
format
"
)
==
"
email
"
assert
schema_21
.
get
(
"
minProperties
"
)
==
2
schema_3
,
uischema_3
=
rtjs
(
model
.
get_deep
(
"
RT3
"
),
additional_properties
=
False
,
additional_json_schema
=
custom_schema
,
additional_ui_schema
=
custom_ui_schema
,
rjsf
=
True
)
assert
(
json
.
dumps
(
schema_3
[
"
properties
"
][
"
number
"
])
==
'
{
"
type
"
:
"
integer
"
,
"
minimum
"
: 0,
"
exclusiveMaximum
"
: 100}
'
)
assert
(
str
(
uischema_3
)
==
"
{
'
number
'
: {
'
ui:order
'
: 2}}
"
)
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