Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Odata v4 #77

Draft
wants to merge 36 commits into
base: wip-odata-v4
Choose a base branch
from
Draft

Odata v4 #77

wants to merge 36 commits into from

Conversation

mamiksik
Copy link
Contributor

@mamiksik mamiksik commented Nov 21, 2019

mamiksik and others added 6 commits November 7, 2019 13:37
The current implementation of python representation of metadata and metadata parser was tightly interconnected. Support for other versions of OData was not possible as in each version elements are added, removed or modified. Therefore, we decided to split metadata representation and its parser. With this approach, we can easily define supported elements and its parsing functions in a single class. This "configuration" class is stateless and has to be a child of ODATAVersion.

Additional changes including updating directory structure and refactoring old code to accommodate for incoming ODATA V4 support.

New module model:
- builder -> MetadataBuilder was moved here to make code easier to read
elements -> All EDM elements were moved here, to make python representation of elements version independent. All parsable elements have to inherit from "from_etree_mixin".

- from_etree_callbacks -> All  from_etree static methods were moved into separated function. This is a naive approach as its premise is that all from_etree implementations will be reusable in version V4.

- types_traits -> "types traits" were moved here to make code cleaner and easier to read.

Module V2:
- __init__ -> includes OData2 definition.

- service -> function-wise nothing has been changed.

"Main" module:
- config -> class Config was moved here to make it version and model-independent. In case we will ever need a config class also for service. Also ODataVersion class lives here.

- policies -> All policies were moved here as well as ParserError enum. Again to make policies version and model-independent.

Tests were only updated to incorporate new API.
In every release of OData new types are not only added and removed but
also there are changes to the existing types notably in formatting.
Thus, there is a need to have separate type repository for each OData
version.

Let's see an example of Edm.Double JSON format:
OData V2: 3.141d
OData V4: 3.141

https://www.odata.org/documentation/odata-version-2-0/overview/#AbstractTypeSystem

http://docs.oasis-open.org/odata/odata-json-format/v4.01/odata-json-format-v4.01.html
- Enum types is working
- Complex type is working(including BaseType)
- Entity type needs editing
MixinFromEtree was removed in favour of the function called
build_element. This is because A) Not always etree was passed, so the
name was misleading. B) The purpose of splitting model and parse
function was to be able to reuse certain part of code among different
version of ODATA, but that was not fully possible with the previous
solution as you had to import given element's class(which could be
different for each version).  Thus, you would have to introduce
unnecessary inherency to solve this.

New function build_element takes two positional arguments and rest is
kwargs. First one is element's class or element's class name as a string.
Element class is preferred as it makes refactoring easier and does not
introduce magical strings to the code. The name string option is here
to solve those cases when you cant import needed element class due to
version differences. Second argument is config.
Previous test was faulty as it relied on being call before any other
test initiated ODataV2.Types.
@mamiksik mamiksik force-pushed the odata-v4 branch 2 times, most recently from 091c38f to 1f9cce9 Compare November 27, 2019 15:53
@codecov-io
Copy link

codecov-io commented Nov 29, 2019

Codecov Report

Merging #77 into wip-odata-v4 will decrease coverage by 13.00%.
The diff coverage is 77.33%.

Impacted file tree graph

@@                Coverage Diff                @@
##           wip-odata-v4      #77       +/-   ##
=================================================
- Coverage         92.14%   79.13%   -13.01%     
=================================================
  Files                 6       21       +15     
  Lines              2405     3652     +1247     
=================================================
+ Hits               2216     2890      +674     
- Misses              189      762      +573     
Impacted Files Coverage Δ
pyodata/v4/service.py 24.64% <24.64%> (ø)
pyodata/model/type_traits.py 89.13% <89.13%> (ø)
pyodata/v2/build_functions.py 89.13% <89.13%> (ø)
pyodata/v2/elements.py 90.69% <90.69%> (ø)
pyodata/model/elements.py 91.69% <91.69%> (ø)
pyodata/v4/type_traits.py 92.20% <92.20%> (ø)
pyodata/version.py 94.11% <94.11%> (ø)
pyodata/v2/__init__.py 95.23% <95.23%> (ø)
pyodata/v2/type_traits.py 95.23% <95.23%> (ø)
pyodata/model/build_functions.py 95.55% <95.55%> (ø)
... and 25 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 05243e4...1d0193d. Read the comment docs.

Functions and elements removed/replaced in V4 corresponding with
NavigationTypeProperty were moved to v2 module.
Despite implementing enum for V2 the first mention of enum in
specification is only in later versions of OData. Thus, it should not be
possible to parse enum using V2 parser.
TypeDefinitions are simply aliases for primitive types. They can be
annotated. Thus, reimplementation of annotation for V4 is included in
this commit.

Children of ODataVersion have to specify which annotations are supported
and how they should be processed. Annotation are parsed using function
'build_annotation'. As annotation are always tied to specific element
and there is no centralized repository of annotations this function must
return void.

http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part3-csdl/odata-v4.0-errata03-os-part3-csdl-complete.html#_Toc453752574
They(EnumType, EntityType, ComplexType) now handle parsing of invalid
metadata independently. Thus, you do not have to wrap build_element in
try-except block. Build function either return valid type, null type or
fails. (Last two options depend on which policy is set.)
Also imports' paths were updated to correctly reflect project structure.
In Python 3.7 importlib which resolves imports was updated. It allowed
to use "import x.y as c" in __x__.py, but as we support python 3.6 as
well we needed to optimize to work properly even with previous versions
of importlib. Thus, the reason for this commit.

All imports of files defined in the same folder as __module__.py are
now in the form of "from .x import a,b,c". Also, since now all relevant
classes for using pyodata e. g. elements, types are now directly
imported in the appropriate module. User should always use API exposed
directly from importing "pyodata.v2" or "pyodata.v4"

Moreover, to remove cyclic imports:
1) Adapter function for build_entity_set(Credit to Jakub Filak)
was added as well as class.

2) ODATAVersion was moved to separate file.

3) Redundant function schema_from_xml which required importing
pyodata.v2 was removed. Used MetadataBuilder(xml, Config(ODataV2))
instead.
Required method for parsing datetime 'fromisoformat' was added in
python version 3.7, thus backport of that method was added to
the requirements list.

Also '%z' directive was updated in python 3.7 to support timezone
information in the "+xx:xx" or "Z" format. Hence, changes were made to
allow compatibility of these notations in python 3.6 and lower.

https://docs.python.org/3/library/datetime.html
According to ODATA V4 specification when precision is not provided
it defaults to infinity. ODATA V2 specification does not provide any
information regarding the default value and ODATA V3 specification
is unclear. Thus, following the ODATA V4 specification for all versions
seams as the best idea.

https://www.odata.org/documentation/odata-version-3-0/common-schema-definition-language-csdl/#csdl5.3.4

https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/csprd06/odata-csdl-xml-v4.01-csprd06.html#sec_Precision

https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/csprd06/odata-csdl-xml-v4.01-csprd06.html#sec_Scale
Folder .htmlcov is generated by the
"make report-coverage-html"
Type hint Type[ErrorPolicy] was not resoling correctly for its children.
Before it was not possible to skip parsing of invalid
TypeDefinition node.
This is to better handle permissive parsing as otherwise we could be
catching unwanted exceptions.

Test were updated to expect different exceptions.
…rvice V2

Before developing the Service V4 I wanted to fully understand how V2 works, however without
data types it was nearly impossible to grasp the meaning of the code. Hence, this commit.
@CLAassistant
Copy link

CLAassistant commented Aug 5, 2020

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ filak-sap
❌ mamiksik
You have signed the CLA already but the status is still pending? Let us recheck it.

@jbarotin
Copy link

jbarotin commented May 5, 2021

Hi,

How can I Help to make this PR merged ?

@filak-sap
Copy link
Contributor

@jbarotin I am sorry for the late reply but I think you can find the information at #39 We currently short on humans and machines cannot do it yet ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants