Beispiel #1
0
    def to_canonical_json(self, names=None):
        names = names or Names()

        to_dump = self.canonical_properties
        to_dump["values"] = self.get_prop("values").to_canonical_json(names)

        return to_dump
Beispiel #2
0
    def to_json(self, names=None):
        names = names or Names()

        to_dump = self.props.copy()
        to_dump["type"] = self.type.to_json(names)

        return to_dump
Beispiel #3
0
    def to_json(self, names=None):
        names = names or Names()

        to_dump = self.props.copy()
        to_dump["values"] = self.get_prop("values").to_json(names)

        return to_dump
Beispiel #4
0
    def to_canonical_json(self, names=None):
        names = names or Names()

        to_dump = self.canonical_properties
        to_dump["type"] = self.type.to_canonical_json(names)

        return to_dump
Beispiel #5
0
    def __init__(
        self,
        type_: str,
        name: str,
        namespace: Optional[str] = None,
        names: Optional[Names] = None,
        other_props: Optional[Mapping[str, object]] = None,
    ) -> None:
        super().__init__(type_, other_props)
        if not name:
            raise avro.errors.SchemaParseException(
                "Named Schemas must have a non-empty name.")
        if not isinstance(name, str):
            raise avro.errors.SchemaParseException(
                "The name property must be a string.")
        if namespace is not None and not isinstance(namespace, str):
            raise avro.errors.SchemaParseException(
                "The namespace property must be a string.")
        namespace = namespace or None  # Empty string -> None
        names = names or Names()
        new_name = names.add_name(name, namespace, self)

        # Store name and namespace as they were read in origin schema
        self.set_prop("name", name)
        if namespace is not None:
            self.set_prop("namespace", new_name.space)

        # Store full name as calculated from name, namespace
        self._fullname = new_name.fullname
Beispiel #6
0
    def to_json(self, names=None):
        names = names or Names()

        to_dump = []
        for schema in self.schemas:
            to_dump.append(schema.to_json(names))

        return to_dump
Beispiel #7
0
    def to_canonical_json(self, names=None):
        names = names or Names()

        to_dump = self.canonical_properties
        item_schema = self.get_prop("items")
        to_dump["items"] = item_schema.to_canonical_json(names)

        return to_dump
Beispiel #8
0
    def to_json(self, names=None):
        names = names or Names()

        to_dump = self.props.copy()
        item_schema = self.get_prop("items")
        to_dump["items"] = item_schema.to_json(names)

        return to_dump
Beispiel #9
0
    def to_json(self, names=None):
        names = names or Names()

        if self.fullname in names.names:
            return self.name_ref(names)

        names.names[self.fullname] = self
        return names.prune_namespace(self.props)
Beispiel #10
0
    def to_json(self, names=None):
        names = names or Names()

        to_dump = []
        for schema in self.schemas:
            # Don't print the system error schema
            if schema.type == "string":
                continue
            to_dump.append(schema.to_json(names))

        return to_dump
Beispiel #11
0
def parse(json_string: str, validate_enum_symbols: bool = True) -> Schema:
    """Constructs the Schema from the JSON text.

    @arg json_string: The json string of the schema to parse
    @arg validate_enum_symbols: If False, will allow enum symbols that are not valid Avro names.
    @return Schema
    """
    try:
        json_data = json.loads(json_string)
    except json.decoder.JSONDecodeError as e:
        raise avro.errors.SchemaParseException(
            f"Error parsing JSON: {json_string}, error = {e}") from e
    return make_avsc_object(json_data, Names(), validate_enum_symbols)
Beispiel #12
0
    def to_json(self, names=None):
        names = names or Names()

        # Request records don't have names
        if self.type == "request":
            return [f.to_json(names) for f in self.fields]

        if self.fullname in names.names:
            return self.name_ref(names)
        else:
            names.names[self.fullname] = self

        to_dump = names.prune_namespace(self.props.copy())
        to_dump["fields"] = [f.to_json(names) for f in self.fields]

        return to_dump
Beispiel #13
0
    def to_canonical_json(self, names=None):
        names = names or Names()

        if self.type == "request":
            raise NotImplementedError("Canonical form (probably) does not make sense on type request")

        to_dump = self.canonical_properties
        to_dump["name"] = self.fullname

        if self.fullname in names.names:
            return self.name_ref(names)

        names.names[self.fullname] = self
        to_dump["fields"] = [f.to_canonical_json(names) for f in self.fields]

        return to_dump
Beispiel #14
0
def parse(json_string, validate_enum_symbols=True):
    """Constructs the Schema from the JSON text.

    @arg json_string: The json string of the schema to parse
    @arg validate_enum_symbols: If False, will allow enum symbols that are not valid Avro names.
    @return Schema
    """
    # parse the JSON
    try:
        json_data = json.loads(json_string)
    except Exception as e:
        msg = f"Error parsing JSON: {json_string}, error = {e}"
        new_exception = avro.errors.SchemaParseException(msg)
        traceback = sys.exc_info()[2]
        raise new_exception.with_traceback(traceback)

    # Initialize the names object
    names = Names()

    # construct the Avro Schema object
    return make_avsc_object(json_data, names, validate_enum_symbols)
Beispiel #15
0
    def to_canonical_json(self, names=None):
        names = names or Names()

        return [schema.to_canonical_json(names) for schema in self.schemas]
Beispiel #16
0
def make_avsc_object(json_data: object,
                     names: Optional[avro.name.Names] = None,
                     validate_enum_symbols: bool = True) -> Schema:
    """
    Build Avro Schema from data parsed out of JSON string.

    @arg names: A Names object (tracks seen names and default space)
    @arg validate_enum_symbols: If False, will allow enum symbols that are not valid Avro names.
    """
    names = names or Names()

    # JSON object (non-union)
    if callable(getattr(json_data, "get", None)):
        json_data = cast(Mapping, json_data)
        type_ = json_data.get("type")
        other_props = get_other_props(json_data, SCHEMA_RESERVED_PROPS)
        logical_type = json_data.get("logicalType")

        if logical_type:
            logical_schema = make_logical_schema(logical_type, type_,
                                                 other_props or {})
            if logical_schema is not None:
                return cast(Schema, logical_schema)

        if type_ in NAMED_TYPES:
            name = json_data.get("name")
            if not isinstance(name, str):
                raise avro.errors.SchemaParseException(
                    f"Name {name} must be a string, but it is {type(name)}.")
            namespace = json_data.get("namespace", names.default_namespace)
            if type_ == "fixed":
                size = json_data.get("size")
                if logical_type == "decimal":
                    precision = json_data.get("precision")
                    scale = 0 if json_data.get(
                        "scale") is None else json_data.get("scale")
                    try:
                        return FixedDecimalSchema(size, name, precision, scale,
                                                  namespace, names,
                                                  other_props)
                    except avro.errors.IgnoredLogicalType as warning:
                        warnings.warn(warning)
                return FixedSchema(name, namespace, size, names, other_props)
            elif type_ == "enum":
                symbols = json_data.get("symbols")
                if not isinstance(symbols, Sequence):
                    raise avro.errors.SchemaParseException(
                        f"Enum symbols must be a sequence of strings, but it is {type(symbols)}"
                    )
                for symbol in symbols:
                    if not isinstance(symbol, str):
                        raise avro.errors.SchemaParseException(
                            f"Enum symbols must be a sequence of strings, but one symbol is a {type(symbol)}"
                        )
                doc = json_data.get("doc")
                return EnumSchema(
                    name,
                    namespace,
                    symbols,
                    names,
                    doc,
                    other_props,
                    validate_enum_symbols,
                )
            if type_ in ["record", "error"]:
                fields = json_data.get("fields")
                doc = json_data.get("doc")
                return RecordSchema(name, namespace, fields, names, type_, doc,
                                    other_props)
            raise avro.errors.SchemaParseException(
                f"Unknown Named Type: {type_}")

        if type_ in PRIMITIVE_TYPES:
            return PrimitiveSchema(type_, other_props)

        if type_ in VALID_TYPES:
            if type_ == "array":
                items = json_data.get("items")
                return ArraySchema(items, names, other_props)
            elif type_ == "map":
                values = json_data.get("values")
                return MapSchema(values, names, other_props)
            elif type_ == "error_union":
                declared_errors = json_data.get("declared_errors")
                return ErrorUnionSchema(declared_errors, names)
            else:
                raise avro.errors.SchemaParseException(
                    f"Unknown Valid Type: {type_}")
        elif type_ is None:
            raise avro.errors.SchemaParseException(
                f'No "type" property: {json_data}')
        else:
            raise avro.errors.SchemaParseException(f"Undefined type: {type_}")
    # JSON array (union)
    elif isinstance(json_data, list):
        return UnionSchema(json_data, names)
    # JSON string (primitive)
    elif json_data in PRIMITIVE_TYPES:
        return PrimitiveSchema(json_data)
    # not for us!
    fail_msg = f"Could not make an Avro Schema object from {json_data}"
    raise avro.errors.SchemaParseException(fail_msg)