Having user defined types with names like Optional will make Python unable to use the typing.Optional type since it is from imported.
Not importing typing.Optional but instead using it with the full module prefix would fix this.
The same would happen with Enum, Any, or List.
Shame that this is unmaintained, I would not mind making a PR for this since it's a simple fix.
Creating this issue so that others will realize their issue faster.
Running jtd-codegen --python-out . schema.json creates the following:
# Code generated by jtd-codegen for Python v0.3.1
import re
from dataclasses import dataclass
from datetime import datetime, timedelta, timezone
from typing import Any, Dict, Optional, Union, get_args, get_origin
@dataclass
class Schema:
opt: 'Optional'
t: 'Optional[str]'
@classmethod
def from_json_data(cls, data: Any) -> 'Schema':
return cls(
_from_json_data(Optional, data.get("opt")),
_from_json_data(Optional[str], data.get("t")),
)
def to_json_data(self) -> Any:
data: Dict[str, Any] = {}
data["opt"] = _to_json_data(self.opt)
if self.t is not None:
data["t"] = _to_json_data(self.t)
return data
@dataclass
class Optional:
value: 'Any'
@classmethod
def from_json_data(cls, data: Any) -> 'Optional':
return cls(_from_json_data(Any, data))
def to_json_data(self) -> Any:
return _to_json_data(self.value)
def _from_json_data(cls: Any, data: Any) -> Any:
if data is None or cls in [bool, int, float, str, object] or cls is Any:
return data
if cls is datetime:
return _parse_rfc3339(data)
if get_origin(cls) is Union:
return _from_json_data(get_args(cls)[0], data)
if get_origin(cls) is list:
return [_from_json_data(get_args(cls)[0], d) for d in data]
if get_origin(cls) is dict:
return { k: _from_json_data(get_args(cls)[1], v) for k, v in data.items() }
return cls.from_json_data(data)
def _to_json_data(data: Any) -> Any:
if data is None or type(data) in [bool, int, float, str, object]:
return data
if type(data) is datetime:
return data.isoformat()
if type(data) is list:
return [_to_json_data(d) for d in data]
if type(data) is dict:
return { k: _to_json_data(v) for k, v in data.items() }
return data.to_json_data()
def _parse_rfc3339(s: str) -> datetime:
datetime_re = '^(\d{4})-(\d{2})-(\d{2})[tT](\d{2}):(\d{2}):(\d{2})(\.\d+)?([zZ]|((\+|-)(\d{2}):(\d{2})))$'
match = re.match(datetime_re, s)
if not match:
raise ValueError('Invalid RFC3339 date/time', s)
(year, month, day, hour, minute, second, frac_seconds, offset,
*tz) = match.groups()
frac_seconds_parsed = None
if frac_seconds:
frac_seconds_parsed = int(float(frac_seconds) * 1_000_000)
else:
frac_seconds_parsed = 0
tzinfo = None
if offset == 'Z':
tzinfo = timezone.utc
else:
hours = int(tz[2])
minutes = int(tz[3])
sign = 1 if tz[1] == '+' else -1
if minutes not in range(60):
raise ValueError('minute offset must be in 0..59')
tzinfo = timezone(timedelta(minutes=sign * (60 * hours + minutes)))
second_parsed = int(second)
if second_parsed == 60:
second_parsed = 59
return datetime(int(year), int(month), int(day), int(hour), int(minute),
second_parsed, frac_seconds_parsed, tzinfo)
Running it with
import model
import json
data = json.loads("{}")
t = model.Schema.from_json_data(data)
causes
Traceback (most recent call last):
File "/media/asd/96B4-13F2/jtdc/t.py", line 7, in <module>
t = model.Schema.from_json_data(data)
File "/media/asd/96B4-13F2/jtdc/model.py", line 18, in from_json_data
_from_json_data(Optional[str], data.get("t")),
TypeError: 'type' object is not subscriptable
Having user defined types with names like
Optional
will make Python unable to use thetyping.Optional
type since it is from imported.Not importing
typing.Optional
but instead using it with the full module prefix would fix this.The same would happen with
Enum
,Any
, orList
.Shame that this is unmaintained, I would not mind making a PR for this since it's a simple fix. Creating this issue so that others will realize their issue faster.
With the following schema:
Running
jtd-codegen --python-out . schema.json
creates the following:Running it with
causes