|
| 1 | +from datetime import datetime |
| 2 | +from typing import List |
| 3 | + |
| 4 | +import httpx |
| 5 | +from pydantic import AliasGenerator, BaseModel, ConfigDict, HttpUrl |
| 6 | +from pydantic.alias_generators import to_pascal |
| 7 | + |
| 8 | + |
| 9 | +class ConnectorFeedBaseModel(BaseModel): |
| 10 | + """ |
| 11 | + Parent class for all Connector Feed Object Model classes |
| 12 | + Sets-up a pydantic config to serialize properties using a pascal case alias |
| 13 | + """ |
| 14 | + |
| 15 | + model_config = ConfigDict( |
| 16 | + alias_generator=AliasGenerator( |
| 17 | + validation_alias=to_pascal, |
| 18 | + ), |
| 19 | + populate_by_name=True, |
| 20 | + ) |
| 21 | + |
| 22 | + |
| 23 | +class ConnectorVersion(ConnectorFeedBaseModel): |
| 24 | + number: str |
| 25 | + url: HttpUrl |
| 26 | + os: int # this is an enum, it's properly defined in the old v2 SDK (used by Speckle.Manager.Feed) # noqa: E501 |
| 27 | + architecture: int # These are enums, they are properly defined in the old v2 SDK (used by Speckle.Manager.Feed) # noqa: E501 |
| 28 | + date: datetime |
| 29 | + prerelease: bool |
| 30 | + |
| 31 | + |
| 32 | +class ConnectorVersions(ConnectorFeedBaseModel): |
| 33 | + versions: List[ConnectorVersion] |
| 34 | + |
| 35 | + |
| 36 | +def get_latest_version(host_app_slug: str, allow_pre_release: bool) -> ConnectorVersion: |
| 37 | + """ |
| 38 | + Fetches the JSON feed for the given connector slug and |
| 39 | + Returns the latest version by date - Note, it does not consider semvers! |
| 40 | +
|
| 41 | + Arguments: |
| 42 | + host_app_slug {str} -- the host app slug to query for |
| 43 | + allow_pre_release {bool} -- if false, only stable releases will be considered |
| 44 | + Raises: |
| 45 | + HTTPStatusError: if http request failed |
| 46 | + ValidationError: response was not valid json |
| 47 | + ValueError: The feed contained no connector versions |
| 48 | + """ |
| 49 | + connector_versions = get_connector_versions(host_app_slug).versions |
| 50 | + filtered_versions = [ |
| 51 | + v for v in connector_versions if allow_pre_release or not v.prerelease |
| 52 | + ] |
| 53 | + |
| 54 | + return max(filtered_versions, key=lambda x: x.date) |
| 55 | + |
| 56 | + |
| 57 | +def get_connector_versions(host_app_slug: str) -> ConnectorVersions: |
| 58 | + """ |
| 59 | + Fetches the JSON feed for the given slug (v3 feeds only) |
| 60 | + Raises: |
| 61 | + HTTPStatusError: if http request failed |
| 62 | + ValidationError: response was not valid json |
| 63 | + """ |
| 64 | + url = f"https://releases.speckle.dev/manager2/feeds/{host_app_slug.lower()}-v3.json" |
| 65 | + |
| 66 | + res = httpx.get(url).raise_for_status() |
| 67 | + |
| 68 | + feed_data = ConnectorVersions.model_validate_json(res.text) |
| 69 | + |
| 70 | + return feed_data |
0 commit comments