Skip to content

Commit b59b1bc

Browse files
committed
wip - imports? another try
I wish for python 4 with better way of handling imports. :(
1 parent 4f2bf88 commit b59b1bc

File tree

14 files changed

+404
-391
lines changed

14 files changed

+404
-391
lines changed

pyodata/model/build_functions.py

Lines changed: 77 additions & 75 deletions
Large diffs are not rendered by default.

pyodata/model/builder.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import io
44
from lxml import etree
55

6-
from pyodata.config import Config
7-
from pyodata.exceptions import PyODataParserError
8-
from pyodata.model.elements import ValueHelperParameter, Schema, build_element
6+
import pyodata.config as pyodata
7+
import pyodata.exceptions as exceptions
8+
import pyodata.model.elements as elements
99
import pyodata.v2 as v2
1010

1111

@@ -15,11 +15,11 @@
1515
}
1616

1717
SAP_VALUE_HELPER_DIRECTIONS = {
18-
'com.sap.vocabularies.Common.v1.ValueListParameterIn': ValueHelperParameter.Direction.In,
19-
'com.sap.vocabularies.Common.v1.ValueListParameterInOut': ValueHelperParameter.Direction.InOut,
20-
'com.sap.vocabularies.Common.v1.ValueListParameterOut': ValueHelperParameter.Direction.Out,
21-
'com.sap.vocabularies.Common.v1.ValueListParameterDisplayOnly': ValueHelperParameter.Direction.DisplayOnly,
22-
'com.sap.vocabularies.Common.v1.ValueListParameterFilterOnly': ValueHelperParameter.Direction.FilterOnly
18+
'com.sap.vocabularies.Common.v1.ValueListParameterIn': elements.ValueHelperParameter.Direction.In,
19+
'com.sap.vocabularies.Common.v1.ValueListParameterInOut': elements.ValueHelperParameter.Direction.InOut,
20+
'com.sap.vocabularies.Common.v1.ValueListParameterOut': elements.ValueHelperParameter.Direction.Out,
21+
'com.sap.vocabularies.Common.v1.ValueListParameterDisplayOnly': elements.ValueHelperParameter.Direction.DisplayOnly,
22+
'com.sap.vocabularies.Common.v1.ValueListParameterFilterOnly': elements.ValueHelperParameter.Direction.FilterOnly
2323
}
2424

2525

@@ -44,12 +44,12 @@ def __init__(self, xml, config=None):
4444
self._xml = xml
4545

4646
if config is None:
47-
config = Config(v2.ODataV2)
47+
config = pyodata.Config(v2.ODataV2)
4848
self._config = config
4949

5050
# pylint: disable=missing-docstring
5151
@property
52-
def config(self) -> Config:
52+
def config(self) -> pyodata.Config:
5353
return self._config
5454

5555
def build(self):
@@ -69,26 +69,26 @@ def build(self):
6969
try:
7070
dataservices = next((child for child in edmx if etree.QName(child.tag).localname == 'DataServices'))
7171
except StopIteration:
72-
raise PyODataParserError('Metadata document is missing the element DataServices')
72+
raise exceptions.PyODataParserError('Metadata document is missing the element DataServices')
7373

7474
try:
7575
schema = next((child for child in dataservices if etree.QName(child.tag).localname == 'Schema'))
7676
except StopIteration:
77-
raise PyODataParserError('Metadata document is missing the element Schema')
77+
raise exceptions.PyODataParserError('Metadata document is missing the element Schema')
7878

7979
if 'edmx' not in self._config.namespaces:
8080
namespace = etree.QName(edmx.tag).namespace
8181

8282
if namespace not in self.EDMX_WHITELIST:
83-
raise PyODataParserError(f'Unsupported Edmx namespace - {namespace}')
83+
raise exceptions.PyODataParserError(f'Unsupported Edmx namespace - {namespace}')
8484

8585
namespaces['edmx'] = namespace
8686

8787
if 'edm' not in self._config.namespaces:
8888
namespace = etree.QName(schema.tag).namespace
8989

9090
if namespace not in self.EDM_WHITELIST:
91-
raise PyODataParserError(f'Unsupported Schema namespace - {namespace}')
91+
raise exceptions.PyODataParserError(f'Unsupported Schema namespace - {namespace}')
9292

9393
namespaces['edm'] = namespace
9494

@@ -100,10 +100,10 @@ def build(self):
100100
self.update_alias(self.get_aliases(xml, self._config), self._config)
101101

102102
edm_schemas = xml.xpath('/edmx:Edmx/edmx:DataServices/edm:Schema', namespaces=self._config.namespaces)
103-
return build_element(Schema, self._config, schema_nodes=edm_schemas)
103+
return elements.build_element(elements.Schema, self._config, schema_nodes=edm_schemas)
104104

105105
@staticmethod
106-
def get_aliases(edmx, config: Config):
106+
def get_aliases(edmx, config: pyodata.Config):
107107
"""Get all aliases"""
108108

109109
# aliases = collections.defaultdict(set)
@@ -121,7 +121,7 @@ def get_aliases(edmx, config: Config):
121121
return aliases
122122

123123
@staticmethod
124-
def update_alias(aliases, config: Config):
124+
def update_alias(aliases, config: pyodata.Config):
125125
"""Update config with aliases"""
126126
config.aliases = aliases
127127
helper_direction_keys = list(config.sap_value_helper_directions.keys())
@@ -139,7 +139,7 @@ def schema_from_xml(metadata_xml, namespaces=None):
139139

140140
meta = MetadataBuilder(
141141
metadata_xml,
142-
config=Config(
142+
config=pyodata.Config(
143143
v2.ODataV2,
144144
xml_namespaces=namespaces,
145145
))

pyodata/model/elements.py

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@
33
import collections
44
import itertools
55
import logging
6+
67
from abc import abstractmethod
78
from enum import Enum
89
from typing import Union
910

10-
from pyodata.policies import ParserError
11-
from pyodata.config import Config
12-
from pyodata.exceptions import PyODataModelError, PyODataException, PyODataParserError
1311

14-
from pyodata.model.type_traits import TypTraits, EdmStructTypTraits, EnumTypTrait
12+
import pyodata.config as pyodata
13+
import pyodata.policies as policies
14+
import pyodata.exceptions as exceptions
15+
import pyodata.model.type_traits as base_traits
1516

1617

1718
IdentifierInfo = collections.namedtuple('IdentifierInfo', 'namespace name')
@@ -22,7 +23,7 @@ def modlog():
2223
return logging.getLogger("Elements")
2324

2425

25-
def build_element(element_name: Union[str, type], config: Config, **kwargs):
26+
def build_element(element_name: Union[str, type], config: pyodata.Config, **kwargs):
2627
"""
2728
This function is responsible for resolving which implementation is to be called for parsing EDM element. It's a
2829
primitive implementation of dynamic dispatch, thus there exist table where all supported elements are assigned
@@ -48,10 +49,10 @@ def build_element(element_name: Union[str, type], config: Config, **kwargs):
4849
if element_name == clb.__name__:
4950
return callbacks[clb](config, **kwargs)
5051

51-
raise PyODataParserError(f'{element_name} is unsupported in {config.odata_version.__name__}')
52+
raise exceptions.PyODataParserError(f'{element_name} is unsupported in {config.odata_version.__name__}')
5253

5354

54-
def build_annotation(term: str, config: Config, **kwargs):
55+
def build_annotation(term: str, config: pyodata.Config, **kwargs):
5556
"""
5657
Similarly to build_element this function purpoas is to resolve build function for annotations. There are two
5758
main differences:
@@ -80,27 +81,30 @@ def build_annotation(term: str, config: Config, **kwargs):
8081
annotations[annotation](config, **kwargs)
8182
return
8283

83-
raise PyODataParserError(f'Annotation with term {term} is unsupported in {config.odata_version.__name__}')
84-
except PyODataException as ex:
85-
config.err_policy(ParserError.ANNOTATION).resolve(ex)
84+
raise exceptions.PyODataParserError(
85+
f'Annotation with term {term} is unsupported in {config.odata_version.__name__}')
86+
except exceptions.PyODataException as ex:
87+
config.err_policy(policies.ParserError.ANNOTATION).resolve(ex)
8688

8789

8890
class NullType:
8991
def __init__(self, name):
9092
self.name = name
9193

9294
def __getattr__(self, item):
93-
raise PyODataModelError(f'Cannot access this type. An error occurred during parsing type stated in '
94-
f'xml({self.name}) was not found, therefore it has been replaced with NullType.')
95+
raise exceptions.PyODataModelError(
96+
f'Cannot access this type. An error occurred during parsing type stated in xml({self.name}) was not found, '
97+
f'therefore it has been replaced with NullType.')
9598

9699

97100
class NullAnnotation:
98101
def __init__(self, term):
99102
self.term = term
100103

101104
def __getattr__(self, item):
102-
raise PyODataModelError(f'Cannot access this annotation. An error occurred during parsing '
103-
f'annotation(term = {self.term}), therefore it has been replaced with NullAnnotation.')
105+
raise exceptions.PyODataModelError(
106+
f'Cannot access this annotation. An error occurred during parsing annotation(term = {self.term}), '
107+
f'therefore it has been replaced with NullAnnotation.')
104108

105109

106110
class Identifier:
@@ -139,7 +143,7 @@ class Types:
139143
"""
140144

141145
@staticmethod
142-
def register_type(typ: 'Typ', config: Config):
146+
def register_type(typ: 'Typ', config: pyodata.Config):
143147
"""Add new type to the ODATA version type repository as well as its collection variant"""
144148

145149
o_version = config.odata_version
@@ -155,7 +159,7 @@ def register_type(typ: 'Typ', config: Config):
155159
o_version.Types[collection_name] = collection_typ
156160

157161
@staticmethod
158-
def from_name(name, config: Config) -> 'Typ':
162+
def from_name(name, config: pyodata.Config) -> 'Typ':
159163
o_version = config.odata_version
160164

161165
# build types hierarchy on first use (lazy creation)
@@ -199,7 +203,7 @@ class Typ(Identifier):
199203
Kinds = Enum('Kinds', 'Primitive Complex')
200204

201205
# pylint: disable=line-too-long
202-
def __init__(self, name, null_value, traits=TypTraits(), kind=None):
206+
def __init__(self, name, null_value, traits=base_traits.TypTraits(), kind=None):
203207
super(Typ, self).__init__(name)
204208

205209
self._null_value = null_value
@@ -262,14 +266,14 @@ def traits(self):
262266
# pylint: disable=no-self-use
263267
def to_literal(self, value):
264268
if not isinstance(value, list):
265-
raise PyODataException('Bad format: invalid list value {}'.format(value))
269+
raise exceptions.PyODataException('Bad format: invalid list value {}'.format(value))
266270

267271
return [self._item_type.traits.to_literal(v) for v in value]
268272

269273
# pylint: disable=no-self-use
270274
def from_json(self, value):
271275
if not isinstance(value, list):
272-
raise PyODataException('Bad format: invalid list value {}'.format(value))
276+
raise exceptions.PyODataException('Bad format: invalid list value {}'.format(value))
273277

274278
return [self._item_type.traits.from_json(v) for v in value]
275279

@@ -338,8 +342,8 @@ def scale(self):
338342

339343
def _check_scale_value(self):
340344
if self._scale > self._precision:
341-
raise PyODataModelError('Scale value ({}) must be less than or equal to precision value ({})'
342-
.format(self._scale, self._precision))
345+
raise exceptions.PyODataModelError('Scale value ({}) must be less than or equal to precision value ({})'
346+
.format(self._scale, self._precision))
343347

344348

345349
class Schema:
@@ -422,7 +426,7 @@ def __getitem__(self, key):
422426
except KeyError:
423427
raise KeyError('There is no Schema Namespace {}'.format(key))
424428

425-
def __init__(self, config: Config):
429+
def __init__(self, config: pyodata.Config):
426430
super(Schema, self).__init__()
427431

428432
self._decls = Schema.Declarations()
@@ -547,7 +551,7 @@ def get_type(self, type_info):
547551
except KeyError:
548552
pass
549553

550-
raise PyODataModelError(
554+
raise exceptions.PyODataModelError(
551555
'Neither primitive types nor types parsed from service metadata contain requested type {}'
552556
.format(type_info.name))
553557

@@ -607,17 +611,17 @@ def check_role_property_names(self, role, entity_type_name, namespace):
607611
try:
608612
entity_type = self.entity_type(entity_type_name, namespace)
609613
except KeyError:
610-
raise PyODataModelError('EntityType {} does not exist in Schema Namespace {}'
611-
.format(entity_type_name, namespace))
614+
raise exceptions.PyODataModelError('EntityType {} does not exist in Schema Namespace {}'
615+
.format(entity_type_name, namespace))
612616
try:
613617
entity_type.proprty(proprty)
614618
except KeyError:
615-
raise PyODataModelError('Property {} does not exist in {}'.format(proprty, entity_type.name))
619+
raise exceptions.PyODataModelError('Property {} does not exist in {}'.format(proprty, entity_type.name))
616620

617621

618622
class StructType(Typ):
619623
def __init__(self, name, label, is_value_list):
620-
super(StructType, self).__init__(name, None, EdmStructTypTraits(self), Typ.Kinds.Complex)
624+
super(StructType, self).__init__(name, None, base_traits.EdmStructTypTraits(self), Typ.Kinds.Complex)
621625

622626
self._label = label
623627
self._is_value_list = is_value_list
@@ -654,7 +658,7 @@ def null_value(self):
654658
@property
655659
def traits(self):
656660
# return self._traits
657-
return EdmStructTypTraits(self)
661+
return base_traits.EdmStructTypTraits(self)
658662

659663

660664
class ComplexType(StructType):
@@ -688,7 +692,7 @@ def __init__(self, name, is_flags, underlying_type, namespace):
688692
super(EnumType, self).__init__(name)
689693
self._member = list()
690694
self._underlying_type = underlying_type
691-
self._traits = TypTraits()
695+
self._traits = base_traits.TypTraits()
692696
self._namespace = namespace
693697

694698
if is_flags == 'True':
@@ -702,7 +706,7 @@ def __str__(self):
702706
def __getattr__(self, item):
703707
member = next(filter(lambda x: x.name == item, self._member), None)
704708
if member is None:
705-
raise PyODataException(f'EnumType {self} has no member {item}')
709+
raise exceptions.PyODataException(f'EnumType {self} has no member {item}')
706710

707711
return member
708712

@@ -713,7 +717,7 @@ def __getitem__(self, item):
713717

714718
member = next(filter(lambda x: x.value == int(item), self._member), None)
715719
if member is None:
716-
raise PyODataException(f'EnumType {self} has no member with value {item}')
720+
raise exceptions.PyODataException(f'EnumType {self} has no member with value {item}')
717721

718722
return member
719723

@@ -723,7 +727,7 @@ def is_flags(self):
723727

724728
@property
725729
def traits(self):
726-
return EnumTypTrait(self)
730+
return base_traits.EnumTypTrait(self)
727731

728732
@property
729733
def namespace(self):
@@ -750,7 +754,7 @@ def nav_proprty(self, property_name):
750754
try:
751755
return self._nav_properties[property_name]
752756
except KeyError as ex:
753-
raise PyODataModelError(f'{self} does not contain navigation property {property_name}') from ex
757+
raise exceptions.PyODataModelError(f'{self} does not contain navigation property {property_name}') from ex
754758

755759

756760
class EntitySet(Identifier):

pyodata/model/type_traits.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import re
44

5-
from pyodata.exceptions import PyODataException, PyODataModelError
5+
import pyodata.exceptions as exceptions
66

77

88
class EdmStructTypeSerializer:
@@ -21,7 +21,7 @@ def to_literal(edm_type, value):
2121

2222
# pylint: disable=no-self-use
2323
if not edm_type:
24-
raise PyODataException('Cannot encode value {} without complex type information'.format(value))
24+
raise exceptions.PyODataException('Cannot encode value {} without complex type information'.format(value))
2525

2626
result = {}
2727
for type_prop in edm_type.proprties():
@@ -35,7 +35,7 @@ def from_json(edm_type, value):
3535

3636
# pylint: disable=no-self-use
3737
if not edm_type:
38-
raise PyODataException('Cannot decode value {} without complex type information'.format(value))
38+
raise exceptions.PyODataException('Cannot decode value {} without complex type information'.format(value))
3939

4040
result = {}
4141
for type_prop in edm_type.proprties():
@@ -49,7 +49,7 @@ def from_literal(edm_type, value):
4949

5050
# pylint: disable=no-self-use
5151
if not edm_type:
52-
raise PyODataException('Cannot decode value {} without complex type information'.format(value))
52+
raise exceptions.PyODataException('Cannot decode value {} without complex type information'.format(value))
5353

5454
result = {}
5555
for type_prop in edm_type.proprties():
@@ -93,7 +93,7 @@ def to_literal(self, value):
9393
def from_literal(self, value):
9494
matches = re.match("^{}'(.*)'$".format(self._prefix), value)
9595
if not matches:
96-
raise PyODataModelError(
96+
raise exceptions.PyODataModelError(
9797
"Malformed value {0} for primitive Edm type. Expected format is {1}'value'".format(value, self._prefix))
9898
return matches.group(1)
9999

0 commit comments

Comments
 (0)