55from models_library .services import ServiceMetaDataPublished
66from models_library .services_regex import DYNAMIC_SERVICE_KEY_RE
77from packaging .version import Version
8- from pydantic import ConfigDict , Field , HttpUrl , StringConstraints
8+ from pydantic import BaseModel , ConfigDict , Field , HttpUrl , StringConstraints
99from simcore_service_api_server .models .schemas ._utils import ApiServerOutputSchema
1010
1111from ...models ._utils_pydantic import UriSchema
2727]
2828
2929
30- class Program (ApiServerOutputSchema ):
31- """A released solver with a specific version"""
32-
33- id : Annotated [ProgramKeyId , Field (..., description = "Program identifier" )]
30+ class BaseResource (BaseModel ):
31+ id : Annotated [str , Field (..., description = "Resource identifier" )]
3432 version : Annotated [
35- VersionStr , Field (..., description = "semantic version number of the node " )
33+ VersionStr , Field (..., description = "Semantic version number of the resource " )
3634 ]
3735 title : Annotated [
3836 str ,
@@ -42,12 +40,40 @@ class Program(ApiServerOutputSchema):
4240 description : Annotated [
4341 str | None ,
4442 StringConstraints (max_length = 500 ),
45- Field (None , description = "Description of the program " ),
43+ Field (default = None , description = "Description of the resource " ),
4644 ]
4745 url : Annotated [
4846 HttpUrl | None , UriSchema (), Field (..., description = "Link to get this resource" )
4947 ]
5048
49+ @property
50+ def pep404_version (self ) -> Version :
51+ """Rich version type that can be used e.g. to compare"""
52+ return packaging .version .parse (self .version )
53+
54+ @property
55+ def url_friendly_id (self ) -> str :
56+ """Use to pass id as parameter in URLs"""
57+ return urllib .parse .quote_plus (self .id )
58+
59+ @property
60+ def resource_name (self ) -> str :
61+ """Relative resource name"""
62+ return self .compose_resource_name (self .id , self .version )
63+
64+ @property
65+ def name (self ) -> str :
66+ """API standards notation (see api_resources.py)"""
67+ return self .resource_name
68+
69+ @classmethod
70+ def compose_resource_name (cls , key : str , version : str ) -> str :
71+ raise NotImplementedError ("Subclasses must implement this method" )
72+
73+
74+ class Program (BaseResource , ApiServerOutputSchema ):
75+ """A released program with a specific version"""
76+
5177 model_config = ConfigDict (
5278 extra = "ignore" ,
5379 json_schema_extra = {
@@ -67,7 +93,6 @@ def create_from_image(cls, image_meta: ServiceMetaDataPublished) -> "Program":
6793 data = image_meta .model_dump (
6894 include = {"name" , "key" , "version" , "description" , "contact" },
6995 )
70-
7196 return cls (
7297 id = data .pop ("key" ),
7398 version = data .pop ("version" ),
@@ -76,26 +101,6 @@ def create_from_image(cls, image_meta: ServiceMetaDataPublished) -> "Program":
76101 ** data ,
77102 )
78103
79- @property
80- def pep404_version (self ) -> Version :
81- """Rich version type that can be used e.g. to compare"""
82- return packaging .version .parse (self .version )
83-
84- @property
85- def url_friendly_id (self ) -> str :
86- """Use to pass id as parameter in urls"""
87- return urllib .parse .quote_plus (self .id )
88-
89- @property
90- def resource_name (self ) -> str :
91- """Relative resource name"""
92- return self .compose_resource_name (self .id , self .version )
93-
94- @property
95- def name (self ) -> str :
96- """API standards notation (see api_resources.py)"""
97- return self .resource_name
98-
99104 @classmethod
100105 def compose_resource_name (
101106 cls , program_key : ProgramKeyId , program_version : VersionStr
0 commit comments