0.4.0
Pre-releaseReleased on May 25, 2018.
Language
-
Union tags became possible to have
default
keyword. It's useful for migrating a record type to a union type. [#13, #227] -
Enum members and union tags became disallowed to shadow an other type name in a module. It's because in some target languages we compile both types and members/tags into objects that share the same namespace. In Python, both types and union tags are compiled into classes.
For example, the following definitions had been allowed, but now became disallowed:
unboxed foo (text); // ^~~ enum bar = foo | baz; // ^~~
record foo (text a); // ^~~ union bar = foo (text b) | baz (text c); // ^~~
This rule is applied even between a member/tag and its belonging enum/union type as well. The following definitions are disallowed:
enum foo = foo | bar; ^~~ ^~~
union bar = foo (text a) | bar (text b); ^~~ ^~~
If you already have used the same name for a type and a tag, you can avoid breaking backward compatibility of serialization by specifying a different behind name. For example, if you've had a definition like:
enum foo = foo | bar; // ^~~ ^~~
It can be changed like the following:
enum foo = foo-renamed/foo | bar; // ^~~~~~~~~~~ ^~~
-
Enum members and union tags became disallowed to shadow other enum members and union tags even if they belong to an other type. It's because in some target language we compile them into objects that share the same namespace, regardless of their belonging type.
For example, the following definitions had been allowed, but now became disallowed:
enum foo = bar | baz; // ^~~ enum qux = quux | bar; // ^~~
union foo = bar (text a) | baz (text b); // ^~~ enum qux = quux | bar; // ^~~
union foo = bar (text a) | baz (text b); // ^~~ union qux = quux (text c) | baz (text d); // ^~~
If you already have used the same name for members/tags of different enum/union types, you can avoid breaking backward compatibility of serialization by specifying a different behind name. For example, if you've had a definition like:
enum foo = bar | baz; // ^~~ union qux = bar (text a) | quux (text b); // ^~~
It can be changed like the following:
enum foo = bar-renamed/bar | baz; // ^~~~~~~~~~~ ^~~ union qux = bar (text a) | quux (text b);
-
Fixed a compiler bug that an error message on name duplicates had referred to a wrong line/column number. [#255]
-
Added aliased import. It's handy to avoid a name shadowing. [#217, #258]
import iso (country as iso-country); import types (country);
-
Added support for integer type annotation argument. [#178, #267]
service foo-service ( @bar(baz=1) int32 qux (int32 quux), );
-
Deprecated
uri
andurl
type is added. [#126, #277 by Jonghun Park]
Docs target
-
A new required configuration
targets.docs.title
was added. It's rendered in generated HTML documents'<title>
element. [#253] -
Docs now have a sidebar which contains table of contents. [#257]
-
Fixed a bug that a module-level docs hadn't been rendered. Now it's shown in the right below the module name. [#259]
Python target
-
Generated Python packages became to have two entry points (a feature provided by setuptools):
nirum.modules
: It maps Nirum modules to Python modules. Nirum module paths are normalized to avoid underscores and upper letters and use hyphens and lower letters instead, e.g.,foo-bar.baz
. The table works well withrenames
settings as well.nirum.classes
: It maps Nirum types (including services) to Python classes. Nirum type names are qualified and their leading module paths are also normalized (the same rule tonirum.modules
applies here).
-
Generated deserializers became independent from nirum-python runtime library. [#160, #272]
-
Error messages made during deserialization became more standardized. Every error now consists of two fields: one represents a path to the value having an error, and other one is a human-readable message.
For example, suppose there's types like:
record user (dob date); record user-group ([user] users);
and the following payload for
user-group
type is given:[ {"_type": "user", "dob": "2000-06-30"}, {"_type": "user", "dob": "2000-13-32"} ]
An error is reported with a path like
[1].dob
. -
Added an optional
on_error
callback parameter to generated__nirum_deserialize__()
methods.It has to be a callable which has two parameters (and no return value). An
on_error
callback is called every time any validation/parsing error happens during deserialization, and it can be called multiple times at a single call of__nirum_deserialize__()
.The callback function's first parameter takes a string referring a path to the value having an error (e.g.,
'.users[0].dob'
). The second parameter takes an error message string (e.g.,'Expected a string of RFC 3339 date, but the date is invalid.'
).When it's omitted or
None
, aValueError
is raised with a multiline message that consists of all error messages made during deserialization, as it has been.
-
-
Fixed a bug that record/union deserializers refuses payloads without
"_type"
field. It is only for humans and can be omitted according to the specification. -
All integral types (
int32
,int64
, andbigint
) became represented asnumbers.Integral
instead ofint
.There's no change to Python 3.
-
The
uri
type became represented asbasestring
instead ofunicode
in Python 2, since URI (unlike IRI) is limited to a subset of ASCII character set.There's no change to Python 3.
-
Generated type constructors became to validate field value's range or format besides class checks: range checks for
int32
/int64
, time zone (tzinfo
) awareness check fordatetime
, and basic format check foruri
. -
Generated service methods became to have its own serialization and deserialization functions. Each method object now has these attributes:
-
__nirum_serialize_arguments__
takes the same keywords to the method parameters and serialize them into a mapping object (which can be directly translated to a JSON object). It can raise aTypeError
orValueError
if any invalid values are passed. -
__nirum_deserialize_arguments__
takes a mapping object returned byjson.load()
/json.loads()
(and an optionalon_error
callable) and deserialize it into a mapping object of pairs from parameter's facial name string to its corresponding Python object. -
__nirum_argument_serializers__
is a mapping object that keys are a string of method's parameter facial name and values are its serializer.A serializer function takes an argument value and returns its corresponding value which can be passed to
json.dump()
/json.dumps()
. It can raise aTypeError
orValueError
if an argument is invalid. -
__nirum_argument_deserializers__
is a mapping object that keys are a string of method's parameter behind name and values are its deserializer.A deserializer function takes an argument value preprocessed by
json.load()
/json.loads()
with an optionalon_error
callback, and returns its corresponding Python object. -
__nirum_serialize_result__
takes a method's return value and serialize it into a corresponding value which can be passed tojson.dump()
/json.dumps()
.If the given value does not match to method's return type it raises
TypeError
, orValueError
if the value is invalid.This attribute is
None
if the method has no return type. -
__nirum_deserialize_result__
takes a result value preprocessed byjson.load()
/json.loads()
with an optionalon_error
callback, and deserialize it into its corresponding Python object.This attribute is
None
if the method has no return type. -
__nirum_serialize_error__
takes a method's error object and serialize it into a corresponding value which can be passed tojson.dump()
/json.dumps()
.If the given error object does not match to method's return type it raises
TypeError
, orValueError
if the error object is invalid.This attribute is
None
if the method has no error type. -
__nirum_deserialize_error__
takes an error value preprocessed byjson.load()
/json.loads()
with an optionalon_error
callback, and deserialize it into its corresponding Python object.This attribute is
None
if the method has no error type.
-
-
Removed
__nirum_get_inner_type__()
class methods from generated unboxed type classes. -
Removed
__nirum_record_behind_name__
static fields and__nirum_field_types__()
class methods from generated record type classes. -
Removed
__nirum_tag_names__
,__nirum_union_behind_name__
, and__nirum_field_names__
static fields from generated union type classes. -
Removed
__nirum_tag_types__
static fields from generated union tag classes. -
Removed
__nirum_schema_version__
static field from generated service classes. -
Fixed a bug that generated service methods hadn't checked its arguments before its transport sends a payload. [#220]
-
Fixed a bug that field/parameter names that use a module name of the Python standard library cause runtime
TypeError
s (due to name shadowing). Under the hood, all generatedimport
s are now aliased with a name prefixed an underscore.