2020import typing as tp
2121from urllib .parse import urljoin
2222
23+ from packaging import version as packaging_version
2324from restalchemy .dm import filters as ra_filters
2425from restalchemy .dm import models
2526from restalchemy .dm import properties
2829from restalchemy .dm import types_dynamic
2930from restalchemy .storage .sql import orm
3031
32+ from exordos_core .common import exceptions as common_exc
3133from exordos_core .common import utils
3234from exordos_core .repo import constants as rc
3335
3739 from exordos_core .repo .drivers .base import AbstractProxyRepoDriver
3840
3941
42+ def is_stable_version (version : str ) -> bool :
43+ try :
44+ return not packaging_version .parse (version ).is_prerelease
45+ except packaging_version .InvalidVersion :
46+ return False
47+
48+
4049class SyncMode (str , enum .Enum ):
4150 COPY = "copy"
4251 LAZY = "lazy"
@@ -213,10 +222,10 @@ def load_driver(self) -> "AbstractProxyRepoDriver":
213222 instantiate them with the current repository. If a driver is
214223 successfully loaded, it is stored in a cache for faster access.
215224
216- If no driver is found, a ValueError is raised.
225+ If no driver is found, a ValidateException is raised.
217226
218227 :return: The loaded driver instance
219- :raises ValueError : If no driver is found
228+ :raises ValidateException : If no driver is found
220229 """
221230 driver_key = str (self .driver_spec )
222231
@@ -234,7 +243,9 @@ def load_driver(self) -> "AbstractProxyRepoDriver":
234243 # Just try another driver
235244 pass
236245
237- raise ValueError (f"Driver for spec '{ self .driver_spec } ' not found" )
246+ raise common_exc .ValidateException (
247+ err = f"Driver for spec '{ self .driver_spec } ' not found"
248+ )
238249
239250 def iter_elements_in_inventory (
240251 self , inventory : dict | None = None
@@ -309,13 +320,15 @@ def upload(
309320 Created RepoElement instance
310321
311322 Raises:
312- ValueError : If upload is not supported by driver
323+ ValidateException : If upload is not supported by driver
313324 """
314325 driver = self .load_driver ()
315326
316327 # Check if driver supports upload
317328 if not driver .can_upload_element (element_name , element_version ):
318- raise ValueError ("Upload is not supported by this repository driver" )
329+ raise common_exc .ValidateException (
330+ err = "Upload is not supported by this repository driver"
331+ )
319332
320333 # Create element
321334 element = RepoElement (
@@ -418,6 +431,10 @@ class RepoElement(
418431 default = None ,
419432 )
420433
434+ @property
435+ def is_stable (self ) -> bool :
436+ return is_stable_version (self .version )
437+
421438 @property
422439 def dependencies (self ) -> dict [str , dict [str , str ]]:
423440 """Compute dependencies from manifest requirements.
@@ -466,7 +483,7 @@ def dependencies(self) -> dict[str, dict[str, str]]:
466483
467484 def install (self ) -> "RepoElement" :
468485 if self .installation_state != RepoElementInstallationState .UNINSTALLED :
469- raise ValueError ( "Element must be uninstalled" )
486+ raise common_exc . ValidateException ( err = "Element must be uninstalled" )
470487
471488 # Check there is no installed element with the same name
472489 existing = RepoElement .objects .get_all (
@@ -478,15 +495,17 @@ def install(self) -> "RepoElement":
478495 }
479496 )
480497 if existing :
481- raise ValueError ("Element with the same name is already installed" )
498+ raise common_exc .ValidateException (
499+ err = "Element with the same name is already installed"
500+ )
482501
483502 self .installation_state = RepoElementInstallationState .INSTALLED .value
484503 self .update ()
485504 return self
486505
487506 def uninstall (self ) -> "RepoElement" :
488507 if self .installation_state != RepoElementInstallationState .INSTALLED :
489- raise ValueError ( "Element must be installed" )
508+ raise common_exc . ValidateException ( err = "Element must be installed" )
490509
491510 # Check that no other elements depend on this one. The dependency
492511 # bindings table records transitive dependencies, so if any record
@@ -496,8 +515,8 @@ def uninstall(self) -> "RepoElement":
496515 filters = {"depends_on" : ra_filters .EQ (self .uuid )}
497516 )
498517 if dependents :
499- raise ValueError (
500- "Element cannot be uninstalled: other elements depend on it"
518+ raise common_exc . ValidateException (
519+ err = "Element cannot be uninstalled: other elements depend on it"
501520 )
502521
503522 self .installation_state = RepoElementInstallationState .UNINSTALLED .value
@@ -516,7 +535,9 @@ def uninstall(self) -> "RepoElement":
516535
517536 def upgrade (self , target : str ) -> "RepoElement" :
518537 if self .element is None :
519- raise ValueError ("Element must be installed to upgrade" )
538+ raise common_exc .ValidateException (
539+ err = "Element must be installed to upgrade"
540+ )
520541
521542 target_element = RepoElement .objects .get_one (
522543 filters = {
@@ -528,7 +549,7 @@ def upgrade(self, target: str) -> "RepoElement":
528549 target_element .installation_state
529550 != RepoElementInstallationState .UNINSTALLED
530551 ):
531- raise ValueError ( "Target element must be uninstalled" )
552+ raise common_exc . ValidateException ( err = "Target element must be uninstalled" )
532553 runtime_element = self .element
533554 self .installation_state = RepoElementInstallationState .UNINSTALLED .value
534555 self .update ()
@@ -545,20 +566,20 @@ def edit(self, manifest: dict) -> "RepoElement":
545566 manifest: New manifest dict
546567
547568 Raises:
548- ValueError : If manifest name or version does not match element name/version
569+ ValidateException : If manifest name or version does not match element name/version
549570 """
550571 # Validate that name and version in manifest match the element
551572 manifest_name = manifest .get ("name" )
552573 manifest_version = manifest .get ("version" )
553574
554575 if manifest_name != self .name :
555- raise ValueError (
556- f"Manifest name '{ manifest_name } ' does not match element name '{ self .name } '"
576+ raise common_exc . ValidateException (
577+ err = f"Manifest name '{ manifest_name } ' does not match element name '{ self .name } '"
557578 )
558579
559580 if manifest_version != self .version :
560- raise ValueError (
561- f"Manifest version '{ manifest_version } ' does not match element version '{ self .version } '"
581+ raise common_exc . ValidateException (
582+ err = f"Manifest version '{ manifest_version } ' does not match element version '{ self .version } '"
562583 )
563584
564585 self .manifest = manifest
0 commit comments