Coverage for r11k/forge.py: 100%
10 statements
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-13 23:29 +0100
« prev ^ index » next coverage.py v7.2.1, created at 2023-03-13 23:29 +0100
1"""
2Python instances of all objects returned by the Puppet Forge API.
4This code could have been generated from their OpenAPI specification,
5but the Python tools for it doesn't feel mature enough. Due to that
6the names below are a bit arbitrary.
8Full documentation about each field can be found at
9https://forgeapi.puppet.com/
10"""
12from typing import (
13 Any,
14 Literal,
15 Optional,
16 TypedDict,
17 Union,
18)
19from datetime import datetime
20from semver import VersionInfo
21from r11k.puppet import PuppetMetadata
24def _parse_date(date: str) -> datetime:
25 """Parse date from the format puppet forge uses (almost ISO8601)."""
26 return datetime.strptime(date, "%Y-%m-%d %H:%M:%S %z")
29class Superseeded(TypedDict): # pragma: no cover
30 """Info about which modulesuperseeded the current module."""
32 uri: str
33 slug: str
36class Owner(TypedDict): # pragma: no cover
37 """Owner of a given puppet module."""
39 uri: str
40 slug: str
41 username: str
42 gravatar_id: str
45class Release:
46 """
47 Release info about a puppet module.
49 Returned by `/v3/releases` (the list and search endpoint).
50 """
52 def __init__(self,
53 uri: str,
54 slug: str,
55 version: Union[str, VersionInfo],
56 created_at: Union[str, datetime],
57 deleted_at: Optional[Union[str, datetime]],
58 file_uri: str,
59 file_size: int,
60 **_: Any): # pragma: no cover
61 self.uri = uri
62 self.slug = slug
63 self.version: VersionInfo
65 if isinstance(version, VersionInfo):
66 self.version = version
67 else:
68 self.version = VersionInfo.parse(version)
70 self.file_uri = file_uri
71 self.file_size = file_size
73 self.created_at: datetime
74 if isinstance(created_at, datetime):
75 self.created_at = created_at
76 else:
77 self.created_at = _parse_date(created_at)
79 self.deleted_at: Optional[datetime] = None
80 if isinstance(deleted_at, datetime):
81 self.deleted_at = deleted_at
82 elif isinstance(deleted_at, str):
83 self.deleted_at = _parse_date(deleted_at)
86class ForgeModule:
87 """
88 Data about a puppet module.
90 Return value of `/v3/modules` (the list and search endpoint).
91 """
93 def __init__(self,
94 uri: str,
95 slug: str,
96 name: str,
97 deprecated_at: Optional[Union[str, datetime]],
98 owner: Owner,
99 **_: Any): # pragma: no cover
100 self.uri = uri
101 self.slug = slug
102 self.name = name
103 self.deprecated_at: Optional[datetime] = None
104 if isinstance(deprecated_at, datetime):
105 self.deprecated_at = deprecated_at
106 elif isinstance(deprecated_at, str):
107 self.deprecated_at = _parse_date(deprecated_at)
108 self.owner = owner
111class CurrentRelease(Release):
112 """
113 Extended release info about a puppet module.
115 Superset of Releases for the currently active version (or an older
116 if explicitly specified).
117 """
119 def __init__(self,
120 uri: str,
121 slug: str,
122 module: Union[ForgeModule, dict],
123 version: Union[str, VersionInfo],
124 metadata: Union[PuppetMetadata, dict],
125 tags: list[str],
126 pdk: bool,
127 validation_score: int,
128 file_uri: str,
129 file_size: int,
130 file_md5: str,
131 file_sha256: str,
132 downloads: int,
133 readme: str,
134 changelog: str,
135 license: str,
136 reference: str,
137 tasks: list[dict],
138 plans: list[dict],
139 created_at: Union[str, datetime],
140 updated_at: Union[str, datetime],
141 deleted_at: Optional[Union[str, datetime]],
142 deleted_for: Optional[str],
143 pe_compatibility: Optional[list[str]] = None,
144 **_: Any): # pragma: no cover
145 super().__init__(uri, slug, version, created_at, deleted_at,
146 file_uri, file_size)
147 self.module: ForgeModule
148 if isinstance(module, ForgeModule):
149 self.module = module
150 else:
151 self.module = ForgeModule(**module)
153 self.metadata: PuppetMetadata
154 if isinstance(metadata, PuppetMetadata):
155 self.metadata = metadata
156 else:
157 self.metadata = PuppetMetadata(**metadata)
159 self.tags = tags
160 self.pdk = pdk
161 self.validation_score = validation_score
162 self.file_md5 = file_md5
163 self.file_sha256 = file_sha256
164 self.downloads = downloads
165 self.readme = readme
166 self.changelog = changelog
167 self.license = license
168 self.reference = reference
169 self.pe_compatibility = pe_compatibility
170 self.tasks = tasks
171 self.plans = plans
173 self.updated_at: datetime
174 if isinstance(updated_at, datetime):
175 self.updated_at = updated_at
176 else:
177 self.updated_at = _parse_date(updated_at)
178 self.deleted_for = deleted_for
181class FullForgeModule(ForgeModule):
182 """
183 Extended data about a puppet module.
185 The extended superset when only checking a single module.
187 Return value of `/v3/modules/{module_slug}`.
188 """
190 def __init__(self,
191 uri: str,
192 slug: str,
193 name: str,
194 downloads: int,
195 created_at: Union[str, datetime],
196 updated_at: Union[str, datetime],
197 deprecated_at: Optional[Union[str, datetime]],
198 deprecated_for: Optional[str],
199 superseded_by: Optional[Superseeded],
200 endorsement: Optional[Union[Literal['supported'],
201 Literal['approved'],
202 Literal['partner']]],
203 module_group: Union[Literal['base'], Literal['pe_only']],
204 premium: bool,
205 owner: Owner,
206 current_release: Union[CurrentRelease, dict],
207 releases: list[Union[Release, dict]],
208 feedback_score: int,
209 homepage_url: str,
210 issues_url: str,
211 **_: Any): # pragma: no cover
212 super().__init__(uri, slug, name, deprecated_at, owner)
213 self.downloads = downloads
215 self.created_at: datetime
216 if isinstance(created_at, datetime):
217 self.created_at = created_at
218 else:
219 self.created_at = _parse_date(created_at)
221 self.update_at: datetime
222 if isinstance(updated_at, datetime):
223 self.updated_at = updated_at
224 else:
225 self.updated_at = _parse_date(updated_at)
227 self.deprecated_for = deprecated_for
228 self.superseded_by = superseded_by
229 self.endorsement = endorsement
230 self.module_group = module_group
231 self.premium = premium
232 self.owner = owner
234 self.current_release: CurrentRelease
235 if isinstance(current_release, CurrentRelease):
236 self.current_release = current_release
237 else:
238 self.current_release = CurrentRelease(**current_release)
240 self.releases: list[Release]
241 self.releases = [x if isinstance(x, Release) else Release(**x) for x in releases]
243 self.feedback_score = feedback_score
244 self.homepage_url = homepage_url
245 self.issues_url = issues_url