def test_is_object(): assert json_schema.is_object({'type': ['object']}) assert json_schema.is_object({'properties': {}}) assert json_schema.is_object({}) assert not json_schema.is_object({'anyOf': [ {'type': ['object', 'null'], 'properties': {'i': {'type': ['integer']}}}, {'type': ['string', 'null'], 'format': 'date-time'}]})
def _denest_schema(table_path, table_json_schema, key_prop_schemas, subtables, level=-1): new_properties = {} for prop, item_json_schema in _denest_schema__singular_schemas( table_json_schema): if json_schema.is_object(item_json_schema): _denest_schema_helper(table_path + (prop, ), (prop, ), item_json_schema, json_schema.is_nullable(item_json_schema), new_properties, key_prop_schemas, subtables, level) elif json_schema.is_iterable(item_json_schema): _create_subtable(table_path + (prop, ), item_json_schema, key_prop_schemas, subtables, level + 1) elif json_schema.is_literal(item_json_schema): if (prop, ) in new_properties: new_properties[(prop, )]['anyOf'].append(item_json_schema) else: new_properties[(prop, )] = {'anyOf': [item_json_schema]} table_json_schema['properties'] = new_properties
def _denest_schema_helper(table_path, prop_path, table_json_schema, nullable, top_level_schema, key_prop_schemas, subtables, level): for prop, item_json_schema in _denest_schema__singular_schemas( table_json_schema): if json_schema.is_object(item_json_schema): _denest_schema_helper(table_path + (prop, ), prop_path + (prop, ), item_json_schema, nullable, top_level_schema, key_prop_schemas, subtables, level) elif json_schema.is_iterable(item_json_schema): _create_subtable(table_path + (prop, ), item_json_schema, key_prop_schemas, subtables, level + 1) elif json_schema.is_literal(item_json_schema): if nullable: item_json_schema = json_schema.make_nullable(item_json_schema) p = prop_path + (prop, ) if p in top_level_schema: top_level_schema[p]['anyOf'].append(item_json_schema) else: top_level_schema[p] = {'anyOf': [item_json_schema]}
def _create_subtable(table_path, table_json_schema, key_prop_schemas, subtables, level): if json_schema.is_object(table_json_schema['items']): new_properties = table_json_schema['items']['properties'] else: new_properties = {singer.VALUE: table_json_schema['items']} key_properties = [] for pk, item_json_schema in key_prop_schemas.items(): key_properties.append(singer.SOURCE_PK_PREFIX + pk) new_properties[singer.SOURCE_PK_PREFIX + pk] = item_json_schema new_properties[singer.SEQUENCE] = {'type': ['null', 'integer']} for i in range(0, level + 1): new_properties[singer.LEVEL_FMT.format(i)] = {'type': ['integer']} new_schema = { 'type': [json_schema.OBJECT], 'properties': new_properties, 'level': level, 'key_properties': key_properties } _denest_schema(table_path, new_schema, key_prop_schemas, subtables, level=level) subtables[table_path] = new_schema
def test_complex_objects__logical_statements(): every_type = { 'type': ['null', 'integer', 'number', 'boolean', 'string', 'array', 'object'], 'items': { 'type': 'integer' }, 'format': 'date-time', 'properties': { 'a': { 'type': 'integer' }, 'b': { 'type': 'number' }, 'c': { 'type': 'boolean' } } } assert json_schema.is_iterable(every_type) assert json_schema.is_nullable(every_type) assert json_schema.is_iterable(every_type) assert json_schema.is_object(every_type)
def denest_schema(self, table_name, table_json_schema, key_prop_schemas, subtables, current_path=None, level=-1): new_properties = {} for prop, item_json_schema in table_json_schema['properties'].items(): if current_path: next_path = current_path + self.NESTED_SEPARATOR + prop else: next_path = prop if json_schema.is_object(item_json_schema): not_null = 'null' not in item_json_schema['type'] self.denest_schema_helper( table_name + self.NESTED_SEPARATOR + next_path, item_json_schema, not_null, new_properties, next_path, key_prop_schemas, subtables, level) elif json_schema.is_iterable(item_json_schema): self.create_subtable( table_name + self.NESTED_SEPARATOR + next_path, item_json_schema, key_prop_schemas, subtables, level + 1) else: new_properties[prop] = item_json_schema table_json_schema['properties'] = new_properties
def _denest_schema__singular_schemas(table_json_schema): ret = [] assert json_schema.is_object( table_json_schema ), 'Cannot denest non-object json_schema for tables. Passed: {}'.format( table_json_schema) for prop, sub_schema in table_json_schema['properties'].items(): singular_sub_schemas = [sub_schema] if json_schema.is_anyof(sub_schema): singular_sub_schemas = sub_schema['anyOf'] for s in singular_sub_schemas: assert json_schema.is_object(s) or json_schema.is_iterable(s) or json_schema.is_literal(s), \ 'Table schema cannot be denested due to: {} {}'.format( s, table_json_schema) ret.append((prop, s)) return ret
def _literal_only_schema(schema): ret = deepcopy(schema) ret_type = json_schema.get_type(ret) if json_schema.is_object(ret): ret_type.remove(json_schema.OBJECT) if json_schema.is_iterable(ret): ret_type.remove(json_schema.ARRAY) ret['type'] = ret_type return ret
def _denest_schema_helper(table_path, table_json_schema, nullable, top_level_schema, key_prop_schemas, subtables, level): for prop, item_json_schema in table_json_schema['properties'].items(): if json_schema.is_object(item_json_schema): _denest_schema_helper(table_path + (prop, ), item_json_schema, nullable, top_level_schema, key_prop_schemas, subtables, level) if json_schema.is_iterable(item_json_schema): _create_subtable(table_path + (prop, ), item_json_schema, key_prop_schemas, subtables, level + 1) if json_schema.is_literal(item_json_schema): if nullable and not json_schema.is_nullable(item_json_schema): item_json_schema['type'].append('null') top_level_schema[table_path + (prop, )] = _literal_only_schema(item_json_schema)
def denest_schema_helper(self, table_name, table_json_schema, not_null, top_level_schema, current_path, key_prop_schemas, subtables, level): for prop, item_json_schema in table_json_schema['properties'].items(): next_path = current_path + self.NESTED_SEPARATOR + prop if json_schema.is_object(item_json_schema): self.denest_schema_helper(table_name, item_json_schema, not_null, top_level_schema, next_path, key_prop_schemas, subtables, level) elif json_schema.is_iterable(item_json_schema): self.create_subtable(table_name + self.NESTED_SEPARATOR + prop, item_json_schema, key_prop_schemas, subtables, level + 1) else: if not_null and json_schema.is_nullable(item_json_schema): item_json_schema['type'].remove('null') elif not json_schema.is_nullable(item_json_schema): item_json_schema['type'].append('null') top_level_schema[next_path] = item_json_schema
def _literal_only_schema(schema): ret_types = json_schema.get_type(schema) if json_schema.is_object(schema): ret_types.remove(json_schema.OBJECT) if json_schema.is_iterable(schema): ret_types.remove(json_schema.ARRAY) if json_schema.is_nullable(schema): ret_types.remove(json_schema.NULL) ret_schemas = [] for t in ret_types: s = deepcopy(schema) s['type'] = [t] if json_schema.is_nullable(schema): s = json_schema.make_nullable(s) ret_schemas.append(s) return {'anyOf': ret_schemas}
def _denest_schema(table_path, table_json_schema, key_prop_schemas, subtables, level=-1): new_properties = {} for prop, item_json_schema in table_json_schema['properties'].items(): if json_schema.is_object(item_json_schema): _denest_schema_helper(table_path + (prop, ), item_json_schema, json_schema.is_nullable(item_json_schema), new_properties, key_prop_schemas, subtables, level) if json_schema.is_iterable(item_json_schema): _create_subtable(table_path + (prop, ), item_json_schema, key_prop_schemas, subtables, level + 1) if json_schema.is_literal(item_json_schema): new_properties[(prop, )] = _literal_only_schema(item_json_schema) table_json_schema['properties'] = new_properties
def create_subtable(self, table_name, table_json_schema, key_prop_schemas, subtables, level): if json_schema.is_object(table_json_schema['items']): new_properties = table_json_schema['items']['properties'] else: new_properties = {'value': table_json_schema['items']} for pk, item_json_schema in key_prop_schemas.items(): new_properties[SINGER_SOURCE_PK_PREFIX + pk] = item_json_schema new_properties[SINGER_SEQUENCE] = {'type': ['null', 'integer']} for i in range(0, level + 1): new_properties[SINGER_LEVEL.format(i)] = {'type': ['integer']} new_schema = {'type': ['object'], 'properties': new_properties} self.denest_schema(table_name, new_schema, key_prop_schemas, subtables, level=level) subtables[table_name] = new_schema
def test_is_object(): assert json_schema.is_object({'type': ['object']}) assert json_schema.is_object({'properties': {}}) assert json_schema.is_object({})
def test_simplify__allOf__objects(): assert json_schema.is_object(json_schema.simplify( {'allOf': [{'type': ['object']}]} ))