Skip to content

Commit fa0969a

Browse files
authored
Added JSON schema correctness check. (#38)
* Added JSON schema correctness check * Added pre-commit
1 parent 722a14a commit fa0969a

38 files changed

+999
-898
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ jobs:
5151
- run: PGPASSWORD=postgres psql -c 'create database tests;' -U postgres -h localhost -p 5432
5252
- run: poetry run ./bin/test
5353

54+
pre-commit:
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v3
58+
- uses: actions/setup-python@v3
59+
- uses: pre-commit/[email protected]
60+
5461
publish:
5562
if: startsWith(github.event.ref, 'refs/tags')
5663
name: publish

.pre-commit-config.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.4.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
- id: debug-statements
9+
- id: double-quote-string-fixer
10+
11+
- repo: https://github.com/asottile/pyupgrade
12+
rev: v3.3.1
13+
hooks:
14+
- id: pyupgrade
15+
args: [--py38-plus]

bin/wait_for_it.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@ def log(self, loginfo):
1919
def build_log(self, type, app, time=0):
2020
# 1=enable_timeout,2=disable_timeout,3=success_msg,4=unavailable,5=timeout_msg
2121
loginfo = {
22-
1: "%s: waiting %d seconds for %s" % (sys.argv[0], time, app),
23-
2: "%s: waiting for %s without a timeout" % (sys.argv[0], app),
24-
3: "%s: %s is available after %d seconds" % (sys.argv[0], app, time),
25-
4: "%s: %s is unavailable" % (sys.argv[0], app),
26-
5: "%s: timeout occurred after waiting %d seconds for %s" % (sys.argv[0], time, app),
22+
1: '%s: waiting %d seconds for %s' % (sys.argv[0], time, app),
23+
2: f'{sys.argv[0]}: waiting for {app} without a timeout',
24+
3: '%s: %s is available after %d seconds' % (sys.argv[0], app, time),
25+
4: f'{sys.argv[0]}: {app} is unavailable',
26+
5: '%s: timeout occurred after waiting %d seconds for %s' % (sys.argv[0], time, app),
2727
}.get(type)
2828
return loginfo
2929

3030
def wait_for(self, host, port, timeout):
31-
self.app = ("%s:%d") % (host, port)
31+
self.app = ('%s:%d') % (host, port)
3232
sk = socket.socket()
3333
logmsg = self.build_log(2, self.app, timeout)
3434
if timeout != 0:
@@ -44,21 +44,21 @@ def wait_for(self, host, port, timeout):
4444

4545
def get_parser(self):
4646
parser = OptionParser()
47-
parser.add_option("-a", "--address", dest="address", help="Host or IP under test")
48-
parser.add_option("-p", "--port", dest="port", help="TCP port under test")
47+
parser.add_option('-a', '--address', dest='address', help='Host or IP under test')
48+
parser.add_option('-p', '--port', dest='port', help='TCP port under test')
4949
parser.add_option(
50-
"-t", "--timeout", dest="timeout", default="15", help="Timeout in seconds, zero for no timeout"
50+
'-t', '--timeout', dest='timeout', default='15', help='Timeout in seconds, zero for no timeout'
5151
)
52-
parser.add_option("-q", "--quiet", dest="quiet", action="store_false", help="Don't output any status messages")
52+
parser.add_option('-q', '--quiet', dest='quiet', action='store_false', help="Don't output any status messages")
5353
return parser
5454

5555
def verify_options(self):
5656
if self.options.address is None:
57-
raise OptionException("The address must be set!")
57+
raise OptionException('The address must be set!')
5858
elif self.options.port is None:
59-
raise OptionException("The port must be set!")
59+
raise OptionException('The port must be set!')
6060
elif str(self.options.port).isnumeric() is False:
61-
raise OptionException("The value of port must be number!")
61+
raise OptionException('The value of port must be number!')
6262

6363
def start_up(self):
6464
try:
@@ -77,6 +77,6 @@ def start_up(self):
7777
self.log(logmsg)
7878

7979

80-
if __name__ == "__main__":
80+
if __name__ == '__main__':
8181
w = wait_for_app()
8282
w.start_up()

django_reactive/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
default_app_config = "django_reactive.apps.DjangoReactJsonSchemaFormConfig"
1+
default_app_config = 'django_reactive.apps.DjangoReactJsonSchemaFormConfig'

django_reactive/apps.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
# -*- coding: utf-8
21
from django.apps import AppConfig
32

43

54
class DjangoReactJsonSchemaFormConfig(AppConfig):
6-
name = "django_reactive"
5+
name = 'django_reactive'

django_reactive/fields.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from django.core.exceptions import ValidationError
2+
from django.core import checks
23
from jsonschema import validate, ValidationError as JSONSchemaValidationError
34

45
from .widget.fields import ReactJSONSchemaFormField
56
from .widget.widgets import ReactJSONSchemaFormWidget
7+
from .schema_validator import validate_json_schema
68

79
try:
810
# DJANGO 3.1
@@ -13,8 +15,8 @@
1315

1416
class ReactJSONSchemaField(BaseJSONField):
1517
def __init__(self, schema=None, ui_schema=None, on_render=None, extra_css=None, extra_js=None, **kwargs):
16-
kwargs.setdefault("default", dict)
17-
super(ReactJSONSchemaField, self).__init__(**kwargs)
18+
kwargs.setdefault('default', dict)
19+
super().__init__(**kwargs)
1820
self.schema = schema
1921
self.ui_schema = ui_schema
2022
self.on_render = on_render
@@ -23,7 +25,7 @@ def __init__(self, schema=None, ui_schema=None, on_render=None, extra_css=None,
2325

2426
def formfield(self, **kwargs):
2527
defaults = {
26-
"required": not self.blank,
28+
'required': not self.blank,
2729
}
2830
defaults.update(**kwargs)
2931
return ReactJSONSchemaFormField(
@@ -38,8 +40,23 @@ def formfield(self, **kwargs):
3840
)
3941

4042
def validate(self, value, model_instance):
41-
super(ReactJSONSchemaField, self).validate(value, model_instance)
43+
super().validate(value, model_instance)
4244
try:
4345
validate(value, self.schema)
4446
except JSONSchemaValidationError:
45-
raise ValidationError("This field has errors.")
47+
raise ValidationError('This field has errors.')
48+
49+
def check(self, **kwargs):
50+
errors = super().check(**kwargs)
51+
res, schema_errors = validate_json_schema(self.schema)
52+
if not res:
53+
msg = ','.join(schema_errors)
54+
errors = [
55+
checks.Error(
56+
f'JSON schema is not valid: {msg}',
57+
obj=self.model,
58+
id='fields.JSON_SCHEMA_ERROR',
59+
)
60+
]
61+
62+
return errors

django_reactive/forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class ReactJSONSchemaModelForm(ModelForm):
99
"""
1010

1111
def __init__(self, *args, **kwargs):
12-
on_render_object = kwargs.get("instance", None)
12+
on_render_object = kwargs.get('instance', None)
1313
super().__init__(*args, **kwargs)
1414
for field_name, field_value in self.fields.items():
1515
if isinstance(field_value, ReactJSONSchemaFormField):
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from jsonschema import Draft7Validator
2+
from typing import List, Tuple
3+
4+
5+
def validate_json_schema(schema: dict) -> Tuple[bool, List[str]]:
6+
"""
7+
Validate a JSON schema using the Draft 7 validator.
8+
"""
9+
validator = Draft7Validator(
10+
schema=Draft7Validator.META_SCHEMA,
11+
format_checker=Draft7Validator.FORMAT_CHECKER,
12+
)
13+
errors = [f"{'.'.join(e.path)}: {e.message}" for e in validator.iter_errors(schema)]
14+
15+
return not bool(errors), errors

django_reactive/static/css/django_reactive.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,4 +126,3 @@
126126
.form-row .rjsf .list-inline li {
127127
display: inline;
128128
}
129-

django_reactive/static/dist/react-jsonschema-form.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)