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

Sort by repo of OCA #14

Open
AnizR opened this issue Oct 24, 2024 · 5 comments · May be fixed by #15
Open

Sort by repo of OCA #14

AnizR opened this issue Oct 24, 2024 · 5 comments · May be fixed by #15
Assignees
Labels
enhancement New feature or request

Comments

@AnizR
Copy link
Collaborator

AnizR commented Oct 24, 2024

It would be great to have the name of repository such as OCA/_repo_name when sorting addons.

An idea would be to exploit the 'website' in the manifest.

@sbidoul
Copy link
Member

sbidoul commented Oct 24, 2024

Unfortunately, I realize we don't have the manifests of the dependencies available when running in pre-commit.

However the website field of the Odoo manifest is stored into the Home-Page metadata of the distribution package, so we can obtain that on PyPI. The script below illlustrates how to do this.

One attention point is that it will download a bit more data from the index than the simple HEAD request we currently make. When run locally, this will be fine due to the cache, but this may mean we'll need to use the GitLab/GitHub CI cache when pre-commit runs in CI.

# /// script
# requires-python = ">=3.10"
# dependencies = [
#   "manifestoo_core",
#   "mousebender",
#   "packaging",
#   "httpx",
# ]
# ///

from email.parser import Parser as MetadataParser

import httpx
from manifestoo_core.odoo_series import OdooSeries
from manifestoo_core.metadata import addon_name_to_distribution_name
from mousebender import simple
from packaging.specifiers import SpecifierSet
from packaging.utils import parse_wheel_filename

INDEX_URL = "https://pypi.org/simple/"


def get_oca_repo(addon_name: str, odoo_series: OdooSeries) -> str | None:
    specifier = SpecifierSet(f"=={odoo_series.value}.*")
    distribution_name = addon_name_to_distribution_name(addon_name, odoo_series)
    # get avaialble releases
    project_url = simple.create_project_url(INDEX_URL, distribution_name)
    response = httpx.get(project_url, headers={"Accept": simple.ACCEPT_JSON_V1})
    if response.status_code == 404:
        # project not found
        return None
    response.raise_for_status()
    data = response.text
    content_type = response.headers["Content-Type"]
    project_details = simple.parse_project_details(data, content_type, distribution_name)
    # find the first version that matches the requested Odoo version;
    # we assume all releases come from the same repo for a given Odoo series
    for file in project_details["files"]:
        if file.get("yanked"):
            continue
        filename = file["filename"]
        if not filename.endswith(".whl"):
            continue
        _, version, _, _ = parse_wheel_filename(filename)
        if specifier.contains(version, prereleases=True):
            # found a release that matches the requested Odoo version
            break
    else:
        # no release found that matches the requested Odoo version
        return None
    if not file.get("data-dist-info-metadata"):
        return "UNKNOWN"
    metadata_url = file["url"] + ".metadata"
    response = httpx.get(metadata_url)
    response.raise_for_status()
    metadata = MetadataParser().parsestr(response.text)
    return metadata.get("Home-Page")


print(get_oca_repo("mis_builder", OdooSeries.v16_0))

@AnizR AnizR self-assigned this Oct 26, 2024
@AnizR AnizR added the enhancement New feature or request label Oct 26, 2024
@AnizR
Copy link
Collaborator Author

AnizR commented Oct 26, 2024

Thanks for your suggestion!

I opted to use the JSON API of PyPI, as it appeared to be a simpler approach compared to parsing the wheel metadata. Do you have any thoughts on that?

One attention point is that it will download a bit more data from the index than the simple HEAD request we currently make. When run locally, this will be fine due to the cache, but this may mean we'll need to use the GitLab/GitHub CI cache when pre-commit runs in CI.

I already had a cache setup to retrieve the 'category' of an add-on, so I simply reused that. I'm unsure if I need to do anything further for the CI cache—should this be defined within the repository or when setting up CI?

@sbidoul
Copy link
Member

sbidoul commented Oct 26, 2024

I opted to use the JSON API of PyPI, as it appeared to be a simpler approach compared to parsing the wheel metadata. Do you have any thoughts on that?

The drawback of the PyPI JSON API is that it is not standardized, so other package indexes than PyPI may not support it.

CI cache—should this be defined within the repository or when setting up CI?

That's when setting up the CI indeed.

@AnizR
Copy link
Collaborator Author

AnizR commented Oct 26, 2024

The drawback of the PyPI JSON API is that it is not standardized, so other package indexes than PyPI may not support it.

Oh, okay, you made your point 😄 I'll get back to the parsing of the Metadata as suggeted.

@sbidoul
Copy link
Member

sbidoul commented Oct 28, 2024

To parse the metadata, it would be better to use packaging.metadata rather than email.parser: https://packaging.pypa.io/en/stable/metadata.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
2 participants