Skip to content

Commit ed5196d

Browse files
committed
Add support for NavigationTypeProperty in V4
Functions and elements removed/replaced in V4 corresponding with NavigationTypeProperty were moved to v2 module.
1 parent 03e866b commit ed5196d

File tree

15 files changed

+680
-445
lines changed

15 files changed

+680
-445
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212
- Splits python representation of metadata and metadata parsing - Martin Miksik
1313
- Separate type repositories for individual versions of OData - Martin Miksik
1414
- Support for OData V4 primitive types - Martin Miksik
15+
- Support for navigation property in OData v4 - Martin Miksik
1516

1617
### Changed
1718
- Implementation and naming schema of `from_etree` - Martin Miksik

pyodata/model/build_functions.py

Lines changed: 5 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
import logging
66

77
from pyodata.config import Config
8-
from pyodata.exceptions import PyODataParserError, PyODataModelError
8+
from pyodata.exceptions import PyODataParserError
99
from pyodata.model.elements import sap_attribute_get_bool, sap_attribute_get_string, StructType, StructTypeProperty, \
10-
Identifier, Types, EnumType, EnumMember, EntitySet, ReferentialConstraint, PrincipalRole, DependentRole, \
11-
ValueHelper, ValueHelperParameter, FunctionImportParameter, FunctionImport, metadata_attribute_get, EntityType, \
12-
ComplexType, Annotation, build_element, Association, EndRole, AssociationSetEndRole, AssociationSet
10+
Types, EnumType, EnumMember, EntitySet, ValueHelper, ValueHelperParameter, FunctionImportParameter, \
11+
FunctionImport, metadata_attribute_get, EntityType, ComplexType, Annotation, build_element
1312

1413

1514
def modlog():
@@ -55,6 +54,8 @@ def build_struct_type(config: Config, type_node, typ, schema=None):
5554
stype = copy.deepcopy(schema.get_type(base_type))
5655
except KeyError:
5756
raise PyODataParserError(f'BaseType \'{base_type.name}\' not found in schema')
57+
except AttributeError:
58+
raise PyODataParserError(f'\'{base_type.name}\' ')
5859

5960
stype._name = name
6061

@@ -168,98 +169,6 @@ def build_entity_set(config, entity_set_node):
168169
topable, req_filter, label)
169170

170171

171-
def build_end_role(config: Config, end_role_node):
172-
entity_type_info = Types.parse_type_name(end_role_node.get('Type'))
173-
multiplicity = end_role_node.get('Multiplicity')
174-
role = end_role_node.get('Role')
175-
176-
return EndRole(entity_type_info, multiplicity, role)
177-
178-
179-
def build_referential_constraint(config: Config, referential_constraint_node):
180-
principal = referential_constraint_node.xpath('edm:Principal', namespaces=config.namespaces)
181-
if len(principal) != 1:
182-
raise RuntimeError('Referential constraint must contain exactly one principal element')
183-
184-
principal_name = principal[0].get('Role')
185-
if principal_name is None:
186-
raise RuntimeError('Principal role name was not specified')
187-
188-
principal_refs = []
189-
for property_ref in principal[0].xpath('edm:PropertyRef', namespaces=config.namespaces):
190-
principal_refs.append(property_ref.get('Name'))
191-
if not principal_refs:
192-
raise RuntimeError('In role {} should be at least one principal property defined'.format(principal_name))
193-
194-
dependent = referential_constraint_node.xpath('edm:Dependent', namespaces=config.namespaces)
195-
if len(dependent) != 1:
196-
raise RuntimeError('Referential constraint must contain exactly one dependent element')
197-
198-
dependent_name = dependent[0].get('Role')
199-
if dependent_name is None:
200-
raise RuntimeError('Dependent role name was not specified')
201-
202-
dependent_refs = []
203-
for property_ref in dependent[0].xpath('edm:PropertyRef', namespaces=config.namespaces):
204-
dependent_refs.append(property_ref.get('Name'))
205-
if len(principal_refs) != len(dependent_refs):
206-
raise RuntimeError('Number of properties should be equal for the principal {} and the dependent {}'
207-
.format(principal_name, dependent_name))
208-
209-
return ReferentialConstraint(
210-
PrincipalRole(principal_name, principal_refs), DependentRole(dependent_name, dependent_refs))
211-
212-
213-
# pylint: disable=protected-access
214-
def build_association(config: Config, association_node):
215-
name = association_node.get('Name')
216-
association = Association(name)
217-
218-
for end in association_node.xpath('edm:End', namespaces=config.namespaces):
219-
end_role = build_element(EndRole, config, end_role_node=end)
220-
if end_role.entity_type_info is None:
221-
raise RuntimeError('End type is not specified in the association {}'.format(name))
222-
association._end_roles.append(end_role)
223-
224-
if len(association._end_roles) != 2:
225-
raise RuntimeError('Association {} does not have two end roles'.format(name))
226-
227-
refer = association_node.xpath('edm:ReferentialConstraint', namespaces=config.namespaces)
228-
if len(refer) > 1:
229-
raise RuntimeError('In association {} is defined more than one referential constraint'.format(name))
230-
231-
if not refer:
232-
referential_constraint = None
233-
else:
234-
referential_constraint = build_element(ReferentialConstraint, config, referential_constraint_node=refer[0])
235-
236-
association._referential_constraint = referential_constraint
237-
238-
return association
239-
240-
241-
def build_association_set_end_role(config: Config, end_node):
242-
role = end_node.get('Role')
243-
entity_set = end_node.get('EntitySet')
244-
245-
return AssociationSetEndRole(role, entity_set)
246-
247-
248-
def build_association_set(config: Config, association_set_node):
249-
end_roles = []
250-
name = association_set_node.get('Name')
251-
association = Identifier.parse(association_set_node.get('Association'))
252-
253-
end_roles_list = association_set_node.xpath('edm:End', namespaces=config.namespaces)
254-
if len(end_roles) > 2:
255-
raise PyODataModelError('Association {} cannot have more than 2 end roles'.format(name))
256-
257-
for end_role in end_roles_list:
258-
end_roles.append(build_element(AssociationSetEndRole, config, end_node=end_role))
259-
260-
return AssociationSet(name, association.name, association.namespace, end_roles)
261-
262-
263172
def build_external_annotation(config, annotations_node):
264173
target = annotations_node.get('Target')
265174

0 commit comments

Comments
 (0)