|
5 | 5 | import json |
6 | 6 | import logging |
7 | 7 | import pkgutil |
8 | | -import re |
9 | 8 | from copy import deepcopy |
10 | 9 | from importlib import metadata |
11 | | -from typing import Any, Dict, Iterator, List, Mapping, Optional, Tuple |
| 10 | +from typing import Any, Dict, Iterator, List, Mapping, Optional |
| 11 | +from packaging.version import Version, InvalidVersion |
12 | 12 |
|
13 | 13 | import yaml |
14 | 14 | from airbyte_cdk.models import ( |
@@ -245,45 +245,54 @@ def _validate_source(self) -> None: |
245 | 245 | "Validation against json schema defined in declarative_component_schema.yaml schema failed" |
246 | 246 | ) from e |
247 | 247 |
|
248 | | - cdk_version = metadata.version("airbyte_cdk") |
249 | | - cdk_major, cdk_minor, cdk_patch = self._get_version_parts(cdk_version, "airbyte-cdk") |
250 | | - manifest_version = self._source_config.get("version") |
251 | | - if manifest_version is None: |
| 248 | + cdk_version_str = metadata.version("airbyte_cdk") |
| 249 | + cdk_version = self._parse_version(cdk_version_str, "airbyte-cdk") |
| 250 | + manifest_version_str = self._source_config.get("version") |
| 251 | + if manifest_version_str is None: |
252 | 252 | raise RuntimeError( |
253 | 253 | "Manifest version is not defined in the manifest. This is unexpected since it should be a required field. Please contact support." |
254 | 254 | ) |
255 | | - manifest_major, manifest_minor, manifest_patch = self._get_version_parts( |
256 | | - manifest_version, "manifest" |
257 | | - ) |
| 255 | + manifest_version = self._parse_version(manifest_version_str, "manifest") |
258 | 256 |
|
259 | | - if cdk_version.startswith("0.0.0"): |
| 257 | + if (cdk_version.major, cdk_version.minor, cdk_version.micro) == (0, 0, 0): |
260 | 258 | # Skipping version compatibility check on unreleased dev branch |
261 | 259 | pass |
262 | | - elif cdk_major < manifest_major or ( |
263 | | - cdk_major == manifest_major and cdk_minor < manifest_minor |
| 260 | + elif (cdk_version.major, cdk_version.minor) < ( |
| 261 | + manifest_version.major, |
| 262 | + manifest_version.minor, |
264 | 263 | ): |
265 | 264 | raise ValidationError( |
266 | | - f"The manifest version {manifest_version} is greater than the airbyte-cdk package version ({cdk_version}). Your " |
| 265 | + f"The manifest version {manifest_version!s} is greater than the airbyte-cdk package version ({cdk_version!s}). Your " |
267 | 266 | f"manifest may contain features that are not in the current CDK version." |
268 | 267 | ) |
269 | | - elif manifest_major == 0 and manifest_minor < 29: |
| 268 | + elif (manifest_version.major, manifest_version.minor) < (0, 29): |
270 | 269 | raise ValidationError( |
271 | 270 | f"The low-code framework was promoted to Beta in airbyte-cdk version 0.29.0 and contains many breaking changes to the " |
272 | | - f"language. The manifest version {manifest_version} is incompatible with the airbyte-cdk package version " |
273 | | - f"{cdk_version} which contains these breaking changes." |
| 271 | + f"language. The manifest version {manifest_version!s} is incompatible with the airbyte-cdk package version " |
| 272 | + f"{cdk_version!s} which contains these breaking changes." |
274 | 273 | ) |
275 | 274 |
|
276 | 275 | @staticmethod |
277 | | - def _get_version_parts(version: str, version_type: str) -> Tuple[int, int, int]: |
278 | | - """ |
279 | | - Takes a semantic version represented as a string and splits it into a tuple of its major, minor, and patch versions. |
| 276 | + def _parse_version( |
| 277 | + version: str, |
| 278 | + version_type: str, |
| 279 | + ) -> Version: |
| 280 | + """Takes a semantic version represented as a string and splits it into a tuple. |
| 281 | +
|
| 282 | + The fourth part (prerelease) is not returned in the tuple. |
| 283 | +
|
| 284 | + Returns: |
| 285 | + Version: the parsed version object |
280 | 286 | """ |
281 | | - version_parts = re.split(r"\.", version) |
282 | | - if len(version_parts) != 3 or not all([part.isdigit() for part in version_parts]): |
| 287 | + try: |
| 288 | + parsed_version = Version(version) |
| 289 | + except InvalidVersion as ex: |
283 | 290 | raise ValidationError( |
284 | | - f"The {version_type} version {version} specified is not a valid version format (ex. 1.2.3)" |
285 | | - ) |
286 | | - return tuple(int(part) for part in version_parts) # type: ignore # We already verified there were 3 parts and they are all digits |
| 291 | + f"The {version_type} version '{version}' is not a valid version format." |
| 292 | + ) from ex |
| 293 | + else: |
| 294 | + # No exception |
| 295 | + return parsed_version |
287 | 296 |
|
288 | 297 | def _stream_configs(self, manifest: Mapping[str, Any]) -> List[Dict[str, Any]]: |
289 | 298 | # This has a warning flag for static, but after we finish part 4 we'll replace manifest with self._source_config |
|
0 commit comments