2323
2424from __future__ import annotations
2525from pydantic import AnyUrl , BaseModel , ConfigDict , Field , RootModel
26- from typing import Any , Literal , Optional
26+ from typing import Literal , Optional , Union
2727
2828
2929class Example (RootModel [str ]):
3030 root : str = Field (..., pattern = "^pkg:[a-z][a-z0-9-\\ .]+/.*$" )
3131
3232
33+ class OptionalRequirement (RootModel [Literal ["optional" ]]):
34+ root : Literal ["optional" ] = Field (
35+ ...,
36+ description = "States that this PURL component is optional for a PURL type." ,
37+ title = "Component optional requirement" ,
38+ )
39+
40+
3341class PackageUrlTypeDefinition (BaseModel ):
3442 model_config = ConfigDict (
3543 extra = "forbid" ,
3644 )
37- field_schema : Optional [Any ] = Field (
38- None ,
39- alias = "$schema" ,
40- description = "Contains the URL of the JSON schema for Package-URL type definition." ,
41- title = "JSON schema" ,
45+ field_schema : Literal ["https://packageurl.org/schemas/purl-type-definition.schema-1.0.json" ] = (
46+ Field (
47+ "https://packageurl.org/schemas/purl-type-definition.schema-1.0.json" ,
48+ alias = "$schema" ,
49+ description = "Contains the URL of the JSON schema for Package-URL type definition." ,
50+ title = "JSON schema" ,
51+ )
4252 )
4353 field_id : str = Field (
4454 ...,
@@ -64,31 +74,47 @@ class PackageUrlTypeDefinition(BaseModel):
6474 ..., description = "The description of this PURL type." , title = "Description"
6575 )
6676 repository : Repository = Field (
67- ..., description = "Package repository usage for this PURL type." , title = "Repository"
77+ ..., description = "The package repository usage for this PURL type." , title = "Repository"
6878 )
6979 namespace_definition : NamespaceDefinition = Field (
7080 ...,
71- description = "Definition of the namespace component for this PURL type." ,
81+ description = (
82+ "Definition of the namespace component for this PURL type. The PURL namespace component"
83+ " must be required, optional or prohibited for a specific PURL type definition."
84+ ),
7285 title = "Namespace definition" ,
7386 )
74- name_definition : PurlComponentDefinition = Field (
87+ name_definition : NameDefinition = Field (
7588 ...,
76- description = "Definition of the name component for this PURL type." ,
89+ description = (
90+ "Definition of the name component for this PURL type. The PURL name component is"
91+ " required for all PURL type definitions."
92+ ),
7793 title = "Name definition" ,
7894 )
79- version_definition : Optional [PurlComponentDefinition ] = Field (
95+ version_definition : Optional [VersionDefinition ] = Field (
8096 None ,
81- description = "Definition of the version component for this PURL type." ,
97+ description = (
98+ "Definition of the version component for this PURL type. The PURL version component is"
99+ " optional for a specific PURL type definition."
100+ ),
82101 title = "Version definition" ,
83102 )
84103 qualifiers_definition : Optional [list [QualifiersDefinitionItem ]] = Field (
85104 None ,
86- description = "Definition for the qualifiers specific to this PURL type." ,
105+ description = (
106+ "Definition of the qualifiers specific to this PURL type. The PURL qualifiers component"
107+ " is optional for a specific PURL type, but a qualifiers key or keys may be required"
108+ " for a specific PURL type."
109+ ),
87110 title = "Qualifiers definition" ,
88111 )
89- subpath_definition : Optional [PurlComponentDefinition ] = Field (
112+ subpath_definition : Optional [SubpathDefinition ] = Field (
90113 None ,
91- description = "Definition for the subpath for this PURL type." ,
114+ description = (
115+ "The definition for the subpath for this PURL type. The PURL subpath component is"
116+ " optional for a specific PURL type definition."
117+ ),
92118 title = "Subpath definition" ,
93119 )
94120 examples : list [Example ] = Field (
@@ -105,11 +131,19 @@ class PackageUrlTypeDefinition(BaseModel):
105131 )
106132
107133
134+ class ProhibitedRequirement (RootModel [Literal ["prohibited" ]]):
135+ root : Literal ["prohibited" ] = Field (
136+ ...,
137+ description = "States that this PURL component is prohibited for a PURL type." ,
138+ title = "Component prohibited requirement" ,
139+ )
140+
141+
108142class PurlComponentDefinition (BaseModel ):
109143 permitted_characters : Optional [str ] = Field (
110144 None ,
111145 description = (
112- "Regular expression (ECMA-262 dialect) defining the 'Permitted characters' for this"
146+ "A regular expression (ECMA-262 dialect) defining the 'Permitted characters' for this"
113147 " component of this Package-URL type. If provided, this must be a subset of the"
114148 " 'Permitted characters' defined in the PURL specification."
115149 ),
@@ -148,7 +182,11 @@ class QualifiersDefinitionItem(BaseModel):
148182 extra = "forbid" ,
149183 )
150184 key : str = Field (..., description = "The key for the qualifier." , title = "Qualifier key" )
151- requirement : Optional [Requirement ] = None
185+ requirement : Optional [Union [OptionalRequirement , RequiredRequirement ]] = Field (
186+ None ,
187+ description = "States that a PURL qualifier key is optional or required for a PURL type." ,
188+ title = "Qualifier key requirement" ,
189+ )
152190 description : str = Field (
153191 ..., description = "The description of this qualifier." , title = "Description"
154192 )
@@ -168,7 +206,7 @@ class Repository(BaseModel):
168206 )
169207 use_repository : bool = Field (
170208 ...,
171- description = "true if this PURL type use a public package repository." ,
209+ description = "true if this PURL type uses a public package repository." ,
172210 title = "Use repository" ,
173211 )
174212 default_repository_url : Optional [AnyUrl ] = Field (
@@ -179,13 +217,40 @@ class Repository(BaseModel):
179217 note : Optional [str ] = Field (None , description = "Extra note text." , title = "Note" )
180218
181219
182- class Requirement (RootModel [Literal ["required" , "optional" , "prohibited " ]]):
183- root : Literal ["required" , "optional" , "prohibited" ] = Field (
220+ class RequiredRequirement (RootModel [Literal ["required" ]]):
221+ root : Literal ["required" ] = Field (
184222 ...,
185- description = "States if this PURL component is required, optional, or prohibited." ,
186- title = "Component requirement" ,
223+ description = "States that this PURL component is required for a PURL type." ,
224+ title = "Component required requirement" ,
225+ )
226+
227+
228+ class SubpathDefinition (PurlComponentDefinition ):
229+ requirement : OptionalRequirement = Field (
230+ ..., description = "States that the PURL subpath is optional." , title = "Subpath requirement"
231+ )
232+
233+
234+ class VersionDefinition (PurlComponentDefinition ):
235+ requirement : OptionalRequirement = Field (
236+ ..., description = "States that the PURL version is optional." , title = "Version requirement"
237+ )
238+
239+
240+ class NameDefinition (PurlComponentDefinition ):
241+ requirement : RequiredRequirement = Field (
242+ ...,
243+ description = "States that the PURL name component is always required." ,
244+ title = "Name component requirement" ,
187245 )
188246
189247
190248class NamespaceDefinition (PurlComponentDefinition ):
191- requirement : Requirement
249+ requirement : Union [OptionalRequirement , RequiredRequirement , ProhibitedRequirement ] = Field (
250+ ...,
251+ description = (
252+ "States that the PURL namespace component is optional, required or prohibited for a"
253+ " PURL type."
254+ ),
255+ title = "Namespace requirement" ,
256+ )
0 commit comments