33# This work is licensed under the terms of the BSD-3-Clause license.
44# For a copy, see <https://opensource.org/license/bsd-3-clause>.
55
6+ from __future__ import annotations
7+
68import re
79
10+ from pydantic import RootModel , model_validator
11+
812from cpp_dev .common .types import SemanticVersion
913
1014###############################################################################
1115# Public API ###
1216###############################################################################
1317
1418
15- class ConanPackageReference :
16- CONAN_REFERENCE_PATTERN = r"(?P<name>[a-zA-Z0-9_]+)/(?P<version>\d+\.\d+\.\d+)@(?P<user>[a-zA-Z0-9_]+)/(?P<channel>[a-zA-Z0-9_]+)"
17-
18- def __init__ (self , ref_str : str ) -> None :
19- """
20- Initialize a ConanPackageReference object.
21-
22- This method parses a Conan package reference string and extracts its components.
23- It also validates the semantic version format. A Conan package reference has the format:
24-
25- name/version@user/channel
26- """
27- match = re .match (self .CONAN_REFERENCE_PATTERN , ref_str )
19+ class ConanPackageReference (RootModel ):
20+ """A Conan package reference in the format name/version@user/channel."""
21+
22+ root : str
23+
24+ @model_validator (mode = "after" )
25+ def validate_reference (self ) -> ConanPackageReference :
26+ CONAN_REFERENCE_PATTERN = r"(?P<name>[a-zA-Z0-9_]+)/(?P<version>\d+\.\d+\.\d+)@(?P<user>[a-zA-Z0-9_]+)/(?P<channel>[a-zA-Z0-9_]+)"
27+ match = re .match (CONAN_REFERENCE_PATTERN , self .root )
2828 if not match :
29- raise ValueError (f"Invalid Conan package reference: { ref_str } " )
30-
31- self .name = match .group ('name' )
32- self .version = SemanticVersion (match .group ('version' ))
33- self .user = match .group ('user' )
34- self .channel = match .group ('channel' )
29+ raise ValueError (f"Invalid Conan package reference: { self .root } " )
30+
31+ self ._name = match .group ("name" )
32+ self ._version = SemanticVersion (match .group ("version" ))
33+ self ._user = match .group ("user" )
34+ self ._channel = match .group ("channel" )
35+
36+ @property
37+ def name (self ) -> str :
38+ return self ._name
39+
40+ @property
41+ def version (self ) -> SemanticVersion :
42+ return self ._version
43+
44+ @property
45+ def user (self ) -> str :
46+ return self ._user
47+
48+ @property
49+ def channel (self ) -> str :
50+ return self ._channel
51+
52+ def __hash__ (self ) -> int :
53+ return hash (self .root )
3554
3655 def __str__ (self ) -> str :
37- return f"{ self .name } /{ self .version } @{ self .user } /{ self .channel } "
56+ return f"{ self ._name } /{ self ._version } @{ self ._user } /{ self ._channel } "
0 commit comments