|
6 | 6 |
|
7 | 7 | from pyodata.policies import ParserError
|
8 | 8 | from pyodata.config import Config
|
9 |
| -from pyodata.exceptions import PyODataParserError, PyODataModelError |
| 9 | +from pyodata.exceptions import PyODataParserError, PyODataModelError, PyODataException |
10 | 10 | from pyodata.model.elements import sap_attribute_get_bool, sap_attribute_get_string, StructType, StructTypeProperty, \
|
11 | 11 | Types, EnumType, EnumMember, EntitySet, ValueHelper, ValueHelperParameter, FunctionImportParameter, \
|
12 |
| - FunctionImport, metadata_attribute_get, EntityType, ComplexType, build_element |
| 12 | + FunctionImport, metadata_attribute_get, EntityType, ComplexType, build_element, NullType |
13 | 13 |
|
14 | 14 | # pylint: disable=cyclic-import
|
15 | 15 | # When using `import xxx as yyy` it is not a problem and we need this dependency
|
@@ -83,75 +83,87 @@ def build_struct_type(config: Config, type_node, typ, schema=None):
|
83 | 83 |
|
84 | 84 |
|
85 | 85 | def build_complex_type(config: Config, type_node, schema=None):
|
86 |
| - return build_element(StructType, config, type_node=type_node, typ=ComplexType, schema=schema) |
| 86 | + try: |
| 87 | + return build_element(StructType, config, type_node=type_node, typ=ComplexType, schema=schema) |
| 88 | + except (PyODataException, KeyError, AttributeError) as ex: |
| 89 | + config.err_policy(ParserError.COMPLEX_TYPE).resolve(ex) |
| 90 | + return NullType(type_node.get('Name')) |
87 | 91 |
|
88 | 92 |
|
89 | 93 | # pylint: disable=protected-access
|
90 | 94 | def build_entity_type(config: Config, type_node, schema=None):
|
91 |
| - etype = build_element(StructType, config, type_node=type_node, typ=EntityType, schema=schema) |
| 95 | + try: |
| 96 | + etype = build_element(StructType, config, type_node=type_node, typ=EntityType, schema=schema) |
92 | 97 |
|
93 |
| - for proprty in type_node.xpath('edm:Key/edm:PropertyRef', namespaces=config.namespaces): |
94 |
| - etype._key.append(etype.proprty(proprty.get('Name'))) |
| 98 | + for proprty in type_node.xpath('edm:Key/edm:PropertyRef', namespaces=config.namespaces): |
| 99 | + etype._key.append(etype.proprty(proprty.get('Name'))) |
95 | 100 |
|
96 |
| - for proprty in type_node.xpath('edm:NavigationProperty', namespaces=config.namespaces): |
97 |
| - navp = build_element('NavigationTypeProperty', config, node=proprty) |
| 101 | + for proprty in type_node.xpath('edm:NavigationProperty', namespaces=config.namespaces): |
| 102 | + navp = build_element('NavigationTypeProperty', config, node=proprty) |
98 | 103 |
|
99 |
| - if navp.name in etype._nav_properties: |
100 |
| - raise KeyError('{0} already has navigation property {1}'.format(etype, navp.name)) |
| 104 | + if navp.name in etype._nav_properties: |
| 105 | + raise KeyError('{0} already has navigation property {1}'.format(etype, navp.name)) |
101 | 106 |
|
102 |
| - etype._nav_properties[navp.name] = navp |
| 107 | + etype._nav_properties[navp.name] = navp |
103 | 108 |
|
104 |
| - return etype |
| 109 | + return etype |
| 110 | + except (KeyError, AttributeError) as ex: |
| 111 | + config.err_policy(ParserError.ENTITY_TYPE).resolve(ex) |
| 112 | + return NullType(type_node.get('Name')) |
105 | 113 |
|
106 | 114 |
|
107 | 115 | # pylint: disable=protected-access, too-many-locals
|
108 | 116 | def build_enum_type(config: Config, type_node, namespace):
|
109 |
| - ename = type_node.get('Name') |
110 |
| - is_flags = type_node.get('IsFlags') |
| 117 | + try: |
| 118 | + ename = type_node.get('Name') |
| 119 | + is_flags = type_node.get('IsFlags') |
111 | 120 |
|
112 |
| - # namespace = kwargs['namespace'] |
| 121 | + # namespace = kwargs['namespace'] |
113 | 122 |
|
114 |
| - underlying_type = type_node.get('UnderlyingType') |
| 123 | + underlying_type = type_node.get('UnderlyingType') |
115 | 124 |
|
116 |
| - # https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/csprd04/odata-csdl-json-v4.01-csprd04.html#sec_EnumerationType |
117 |
| - if underlying_type is None: |
118 |
| - underlying_type = 'Edm.Int32' |
| 125 | + # https://docs.oasis-open.org/odata/odata-csdl-json/v4.01/csprd04/odata-csdl-json-v4.01-csprd04.html#sec_EnumerationType |
| 126 | + if underlying_type is None: |
| 127 | + underlying_type = 'Edm.Int32' |
119 | 128 |
|
120 |
| - valid_types = { |
121 |
| - 'Edm.Byte': [0, 2 ** 8 - 1], |
122 |
| - 'Edm.Int16': [-2 ** 15, 2 ** 15 - 1], |
123 |
| - 'Edm.Int32': [-2 ** 31, 2 ** 31 - 1], |
124 |
| - 'Edm.Int64': [-2 ** 63, 2 ** 63 - 1], |
125 |
| - 'Edm.SByte': [-2 ** 7, 2 ** 7 - 1] |
126 |
| - } |
| 129 | + valid_types = { |
| 130 | + 'Edm.Byte': [0, 2 ** 8 - 1], |
| 131 | + 'Edm.Int16': [-2 ** 15, 2 ** 15 - 1], |
| 132 | + 'Edm.Int32': [-2 ** 31, 2 ** 31 - 1], |
| 133 | + 'Edm.Int64': [-2 ** 63, 2 ** 63 - 1], |
| 134 | + 'Edm.SByte': [-2 ** 7, 2 ** 7 - 1] |
| 135 | + } |
127 | 136 |
|
128 |
| - if underlying_type not in valid_types: |
129 |
| - raise PyODataParserError( |
130 |
| - f'Type {underlying_type} is not valid as underlying type for EnumType - must be one of {valid_types}') |
| 137 | + if underlying_type not in valid_types: |
| 138 | + raise PyODataParserError( |
| 139 | + f'Type {underlying_type} is not valid as underlying type for EnumType - must be one of {valid_types}') |
131 | 140 |
|
132 |
| - mtype = Types.from_name(underlying_type, config) |
133 |
| - etype = EnumType(ename, is_flags, mtype, namespace) |
| 141 | + mtype = Types.from_name(underlying_type, config) |
| 142 | + etype = EnumType(ename, is_flags, mtype, namespace) |
134 | 143 |
|
135 |
| - members = type_node.xpath('edm:Member', namespaces=config.namespaces) |
| 144 | + members = type_node.xpath('edm:Member', namespaces=config.namespaces) |
136 | 145 |
|
137 |
| - next_value = 0 |
138 |
| - for member in members: |
139 |
| - name = member.get('Name') |
140 |
| - value = member.get('Value') |
| 146 | + next_value = 0 |
| 147 | + for member in members: |
| 148 | + name = member.get('Name') |
| 149 | + value = member.get('Value') |
141 | 150 |
|
142 |
| - if value is not None: |
143 |
| - next_value = int(value) |
| 151 | + if value is not None: |
| 152 | + next_value = int(value) |
144 | 153 |
|
145 |
| - vtype = valid_types[underlying_type] |
146 |
| - if not vtype[0] < next_value < vtype[1]: |
147 |
| - raise PyODataParserError(f'Value {next_value} is out of range for type {underlying_type}') |
| 154 | + vtype = valid_types[underlying_type] |
| 155 | + if not vtype[0] < next_value < vtype[1]: |
| 156 | + raise PyODataParserError(f'Value {next_value} is out of range for type {underlying_type}') |
148 | 157 |
|
149 |
| - emember = EnumMember(etype, name, next_value) |
150 |
| - etype._member.append(emember) |
| 158 | + emember = EnumMember(etype, name, next_value) |
| 159 | + etype._member.append(emember) |
151 | 160 |
|
152 |
| - next_value += 1 |
| 161 | + next_value += 1 |
153 | 162 |
|
154 |
| - return etype |
| 163 | + return etype |
| 164 | + except (PyODataParserError, AttributeError) as ex: |
| 165 | + config.err_policy(ParserError.ENUM_TYPE).resolve(ex) |
| 166 | + return NullType(type_node.get('Name')) |
155 | 167 |
|
156 | 168 |
|
157 | 169 | def build_entity_set(config, entity_set_node):
|
|
0 commit comments