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

Object wrappers for OBS XML #1349

Merged
merged 5 commits into from
Feb 23, 2024
Merged

Object wrappers for OBS XML #1349

merged 5 commits into from
Feb 23, 2024

Conversation

dmach
Copy link
Contributor

@dmach dmach commented Jul 4, 2023

No description provided.

osc/obs_api/configuration.py Fixed Show fixed Hide fixed
osc/_private/api.py Fixed Show fixed Hide fixed
osc/_private/api.py Fixed Show fixed Hide fixed
osc/_private/api.py Fixed Show fixed Hide fixed
osc/_private/api.py Fixed Show fixed Hide fixed
test_obs_api_project.py Fixed Show fixed Hide fixed
test_obs_api_project.py Fixed Show fixed Hide fixed
osc/obs_api/xmlmodel/fields.py Fixed Show resolved Hide resolved
osc/obs_api/xmlmodel/fields.py Fixed Show fixed Hide fixed
osc/obs_api/project.py Fixed Show fixed Hide fixed
@dmach
Copy link
Contributor Author

dmach commented Jul 4, 2023

Hi,
I'd like to get your feedback on this change.

What's going on:

  • wrapping any OBS XML into objects that are generated from OBS RelaxNG schemas
    • I discussed state of the schemas with @adrianschroeter and @dirkmueller, and our conclusion was that we want rng as the source of truth
    • spme xsd schemas need to be migrated to rng
    • some schemas are missing
    • some schemas are a bit off
    • ... but all that can be fixed
  • osc.core (and other osc code) should not work with XML directly but use the new objects internally. The old code should go away eventually.
  • it should replace any custom OBS XML handling code outside osc
  • ⚠️ the code is still under development
  • ℹ️ check test_obs_api_*.py for examples

@lethliel @marcus-h @adrianschroeter @dirkmueller
@crazyscientist - https://github.com/SUSE/osc-tiny
@dcermak - https://github.com/dcermak/py-obs (and possibly also other projects)
@Vogtinator @nilxam - https://github.com/openSUSE/openSUSE-release-tools
@mimi1vx - https://github.com/openSUSE/osc-plugin-qam
@SchoolGuy - https://github.com/openSUSE/sle-prjmgr-tools

What do you think?
Do you consider this a good idea?
If you have any concerns, suggestions of feature requests, please let me know.

@Vogtinator
Copy link
Member

Sounds like a good idea.

it should replace any custom OBS XML handling code outside osc

How are the wrappers generated? Are there wrappers for XML documents not used by osc as well?

@dmach
Copy link
Contributor Author

dmach commented Jul 4, 2023

Sounds like a good idea.

it should replace any custom OBS XML handling code outside osc
How are the wrappers generated?

I have couple python scripts doing that. Extremely ugly code at the moment, but I'm planning to include it in this pull request once I clean it up.

Are there wrappers for XML documents not used by osc as well?

Not yet, because I wanted to start with the document used by osc.
Throwing anything else in is possible, but I'll do it upon request.
I just don't want to introduce API nobody uses...

@crazyscientist
Copy link
Contributor

What do you think? Do you consider this a good idea?

From the viewpoint of a developer, who needs to handle the XML directly (either to prepare a request or process a response), I certainly would consider this a good idea: Having Python objects means that the IDE can provide helpful information, which the dev does not need to look up manually. 👍

wrapping any OBS XML into objects that are generated from OBS RelaxNG schemas

"Unfortunately", I decided to use lxml for osc-tiny and let the invoking code deal with objects generated by lxml.objectify.

By the way, did you use a tool like "generateDS"?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't be here Enum's ?

from .xml import ET


class Field(property):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstract Class?

@mimi1vx
Copy link
Member

mimi1vx commented Jul 5, 2023

I think we talked about it on OSC23 :D good thing. In the worst case, I modernize my plugin

osc/obs_api/choices.py Outdated Show resolved Hide resolved
Copy link
Contributor

@dcermak dcermak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this! This new API would make py-obs more or less completely obsolete (also, the API is more or less the same 😉), except for the asyncio support, but I could live without that.

@dmach
Copy link
Contributor Author

dmach commented Jul 7, 2023

"Unfortunately", I decided to use lxml for osc-tiny and let the invoking code deal with objects generated by lxml.objectify.

lxml.objectify is great when you want to avoid dealing with XML directly, but I wanted something more robust.
Also I wanted to generate the classes so I can generate docs from them.

By the way, did you use a tool like "generateDS"?

I was looking for existing tools but I missed this one.
I ended up writing my own in the end (to be published after a massive code cleanup).

@SchoolGuy
Copy link
Contributor

I think @gyr is the better person to ask but in any case here are my two cents:

I think the big advantage is that if we are using auto-generated code changes in the XML will now cause compile-time/linter-time issues which would cause us to see breakage before it happens rather than during runtime when the XML is being parsed.

For sure you can make the XML handling code robust enough to consider that the schema has changed but it still doesn't tell you that something is wrong before it is executed.

I am overall for this change. The recursive imports are worrying me a bit but I believe that this is a WIP PR and as such this can be addressed if required at a later point. From my side please go forward with this! Maybe at some point, we can go all the way to protobuf and gRPC to not maintain our own scripting for generating the code for this.

@pep8speaks
Copy link

pep8speaks commented Feb 12, 2024

Hello @dmach! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

Line 710:121: E501 line too long (159 > 120 characters)

Comment last updated at 2024-02-21 08:47:16 UTC

Copy link

codecov bot commented Feb 12, 2024

Codecov Report

Attention: 398 lines in your changes are missing coverage. Please review.

Comparison is base (cff6a0c) 31.51% compared to head (b03f5d3) 31.43%.
Report is 8 commits behind head on master.

Files Patch % Lines
osc/util/models.py 62.65% 90 Missing ⚠️
osc/obs_api/enums.py 0.00% 67 Missing ⚠️
osc/obs_api/package.py 0.00% 46 Missing ⚠️
osc/obs_api/project.py 0.00% 44 Missing ⚠️
osc/obs_api/repository.py 0.00% 20 Missing ⚠️
osc/obs_api/repository_download.py 0.00% 17 Missing ⚠️
osc/obs_api/simple_flag.py 0.00% 14 Missing ⚠️
osc/core.py 0.00% 12 Missing ⚠️
osc/obs_api/flag.py 0.00% 11 Missing ⚠️
osc/obs_api/status_data.py 0.00% 11 Missing ⚠️
... and 12 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1349      +/-   ##
==========================================
- Coverage   31.51%   31.43%   -0.09%     
==========================================
  Files          51       71      +20     
  Lines       17938    18465     +527     
==========================================
+ Hits         5653     5804     +151     
- Misses      12285    12661     +376     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

osc/util/models.py Fixed Show resolved Hide resolved
import types
import typing

Check notice

Code scanning / CodeQL

Module is imported with 'import' and 'import from' Note

Module 'typing' is imported with both 'import' and 'import from'.

@classmethod
def xml_request(cls, method: str, apiurl: str, path: List[str], query: Optional[dict] = None, data: Optional[str] = None) -> urllib3.response.HTTPResponse:
from ..connection import http_request

Check notice

Code scanning / CodeQL

Cyclic import Note

Import of module
osc.connection
begins an import cycle.
@classmethod
def xml_request(cls, method: str, apiurl: str, path: List[str], query: Optional[dict] = None, data: Optional[str] = None) -> urllib3.response.HTTPResponse:
from ..connection import http_request
from ..core import makeurl

Check notice

Code scanning / CodeQL

Cyclic import Note

Import of module
osc.core
begins an import cycle.

IMPORTANT: This method is always interactive.
"""
from ..core import run_editor

Check notice

Code scanning / CodeQL

Cyclic import Note

Import of module
osc.core
begins an import cycle.
osc/util/models.py Dismissed Show dismissed Hide dismissed
@dmach dmach force-pushed the xmlmodel branch 3 times, most recently from 3a6af40 to 8361cf9 Compare February 13, 2024 13:02
@dmach dmach marked this pull request as ready for review February 13, 2024 13:06
@dmach dmach requested review from dcermak and mimi1vx February 13, 2024 13:06
@dmach
Copy link
Contributor Author

dmach commented Feb 13, 2024

So, this is the second (public) iteration of the object wrapper for OBS XML.
It is relatively close to pydantic which gives us a slight chance to move from custom BaseModel and Field objects to pydantic someday. I decided to avoid pydantic for now because v2 not widespread yet and there are differences between v1 and v2. Also, the latest version doesn't work on Python 3.6 which is a requirement for osc.

osc/util/models.py Outdated Show resolved Hide resolved
Comment on lines +749 to +751
edited_obj = self.__class__.from_file(f.name)
f.seek(0)
edited_data = f.read()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we truncate here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because we truncate on write() while this performs read()

@dmach dmach merged commit af24f3c into openSUSE:master Feb 23, 2024
31 of 35 checks passed
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.

7 participants