Skip to content

Commit 4e7e509

Browse files
committed
basic logic for adding gettext + babel to json schema generator
1 parent 2ffa321 commit 4e7e509

File tree

4 files changed

+131
-20
lines changed

4 files changed

+131
-20
lines changed

datamodel/base.py

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,39 @@ def sample(cls) -> dict:
449449
"required": required
450450
}
451451

452+
def _get_meta_value(self, key: str, fallback: Any = None, locale: Any = None):
453+
value = getattr(self.Meta, key, fallback)
454+
if locale is not None:
455+
value = locale(value)
456+
return value
457+
458+
def _get_metadata(self, field, key: str, locale: Any = None):
459+
value = field.metadata.get(key, None)
460+
if locale is not None:
461+
value = locale(value)
462+
return value
463+
464+
def _get_field_schema(
465+
self,
466+
type_info: str,
467+
field: object,
468+
description: str,
469+
locale: Any = None,
470+
**kwargs
471+
) -> dict:
472+
return {
473+
"type": type_info,
474+
"nullable": field.metadata.get('nullable', False),
475+
"attrs": {
476+
"placeholder": description,
477+
"format": field.metadata.get('format', None),
478+
},
479+
"readOnly": field.metadata.get('readonly', False),
480+
**kwargs
481+
}
482+
452483
@classmethod
453-
def schema(cls, as_dict=False):
484+
def schema(cls, as_dict=False, locale: Any = None):
454485
"""Convert Model to JSON-Schema.
455486
456487
Args:
@@ -460,27 +491,47 @@ def schema(cls, as_dict=False):
460491
Returns:
461492
_type_: JSON-Schema version of Model.
462493
"""
463-
title = getattr(cls.Meta, 'title', cls.__name__)
494+
# description:
495+
description = cls._get_meta_value(
496+
cls,
497+
'description',
498+
fallback=cls.__doc__.strip("\n").strip(),
499+
locale=locale
500+
)
501+
title = cls._get_meta_value(
502+
cls,
503+
'title',
504+
fallback=cls.__name__,
505+
locale=locale
506+
)
464507
try:
465508
title = slugify_camelcase(title)
466509
except Exception:
467510
pass
468511

512+
# Table Name:
513+
table = cls.Meta.name.lower() if cls.Meta.name else title.lower()
469514
endpoint = cls.Meta.endpoint
470515
schema = cls.Meta.schema
471-
table = cls.Meta.name.lower() if cls.Meta.name else title.lower()
472516
columns = cls.get_columns().items()
473-
description = cls.Meta.description or cls.__doc__.strip("\n").strip()
517+
474518
fields = {}
475519
required = []
476520
defs = {}
477521

478522
# settings:
479-
settings = getattr(cls.Meta, 'settings', {})
480-
if settings:
523+
settings = cls._get_meta_value(
524+
cls,
525+
'settings',
526+
fallback={},
527+
locale=None
528+
)
529+
try:
481530
settings = {
482531
"settings": settings
483532
}
533+
except TypeError:
534+
settings = {}
484535

485536
for name, field in columns:
486537
_type = field.type
@@ -494,7 +545,6 @@ def schema(cls, as_dict=False):
494545
minimum = field.metadata.get('min', None)
495546
maximum = field.metadata.get('max', None)
496547
secret = field.metadata.get('secret', None)
497-
498548
# custom endpoint for every field:
499549
custom_endpoint = field.metadata.get('endpoint', None)
500550

@@ -507,22 +557,27 @@ def schema(cls, as_dict=False):
507557
}
508558
# schema_extra:
509559
schema_extra = field.metadata.get('schema_extra', {})
510-
511-
fields[name] = {
512-
"type": type_info,
513-
"nullable": field.metadata.get('nullable', False),
514-
"attrs": {
515-
"placeholder": field.metadata.get('description', None),
516-
"format": field.metadata.get('format', None),
517-
},
518-
"readOnly": field.metadata.get('readonly', False),
560+
meta_description = cls._get_metadata(
561+
cls,
562+
field,
563+
key='description',
564+
locale=locale
565+
)
566+
fields[name] = cls._get_field_schema(
567+
cls,
568+
type_info,
569+
field,
570+
description=meta_description,
571+
locale=locale,
519572
**ui_objects,
520573
**schema_extra,
521574
**ref_info
522-
}
523-
label = field.metadata.get('label', None)
575+
)
576+
label = cls._get_metadata(cls, field, 'label', locale=locale)
524577
if label:
525578
fields[name]["label"] = label
579+
if meta_description:
580+
fields[name]["description"] = meta_description
526581
if custom_endpoint:
527582
fields[name]["endpoint"] = custom_endpoint
528583

@@ -578,7 +633,7 @@ def schema(cls, as_dict=False):
578633
if defs:
579634
base_schema["$defs"] = defs
580635

581-
if as_dict:
636+
if as_dict is True:
582637
return base_schema
583638
else:
584639
return json_encoder(base_schema)

datamodel/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
__title__ = 'python-datamodel'
55
__description__ = ('simple library based on python +3.8 to use Dataclass-syntax'
66
'for interacting with Data')
7-
__version__ = '0.6.27'
7+
__version__ = '0.6.28'
88
__author__ = 'Jesus Lara'
99
__author_email__ = '[email protected]'
1010
__license__ = 'BSD'

examples/json_schema.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import pprint
2+
from datetime import datetime
3+
import locale
4+
from datamodel import BaseModel, Column
5+
from navigator.ext.locale import LocaleSupport
6+
from navigator import Application
7+
8+
pp = pprint.PrettyPrinter(width=41, compact=True)
9+
10+
l18n = LocaleSupport(
11+
localization=['en_US', 'es_ES', 'es', 'it_IT', 'de_DE', 'fr_FR'],
12+
domain='nav'
13+
)
14+
app = Application()
15+
l18n.setup(app)
16+
17+
class Airport(BaseModel):
18+
iata: str = Column(
19+
primary_key=True, required=True, label="IATA"
20+
)
21+
airport: str = Column(
22+
required=True, label="airport"
23+
)
24+
city: str = Column(
25+
required=False, label="city"
26+
)
27+
country: str = Column(
28+
required=False, label="country"
29+
)
30+
created_by: int = Column(
31+
required=False, label="created_by"
32+
)
33+
created_at: datetime = Column(
34+
default=datetime.now, repr=False, label="created_at"
35+
)
36+
37+
class Meta:
38+
name: str = 'airports'
39+
description: str = 'airports'
40+
title: str = 'airports'
41+
schema = 'public'
42+
strict = True
43+
44+
localization = 'it_IT'
45+
locale.setlocale(
46+
locale.LC_ALL, f"{localization}.UTF-8"
47+
) # set the current localization
48+
49+
trans = l18n.translator(locale=locale, lang=f"{localization}.UTF-8")
50+
print('LOCALE > ', l18n.current_locale())
51+
print('T > ', trans)
52+
d = trans('city')
53+
print(d)
54+
schema = Airport.schema(as_dict=True, locale=trans)
55+
print(schema)

tests/test_qsobject.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class QueryObject(ClassDict):
4545

4646
def test_queryobject():
4747
qry = QueryObject(**data)
48+
print('AQUI >> ', qry.fields)
4849
assert qry.fields == ["store_id", "postpaid_sales", "postpaid_trended", "apd", "postpaid_to_goal", "hours_worked", "hps", "hps_to_goal"]
4950
fields = qry.pop('fields')
5051
assert fields == ["store_id", "postpaid_sales", "postpaid_trended", "apd", "postpaid_to_goal", "hours_worked", "hps", "hps_to_goal"]

0 commit comments

Comments
 (0)