1
1
"""
2
- Support parsing pyinfra plugins and parsing
3
- their metadata to docs generator.
2
+ Support parsing pyinfra-metadata.toml
3
+
4
+ Currently just parses plugins their metadata.
4
5
"""
5
6
6
7
import tomllib
7
- from dataclasses import dataclass
8
8
from typing import Literal
9
9
10
+ from pydantic import BaseModel , TypeAdapter , field_validator
11
+
10
12
AllowedTagType = Literal [
11
13
"boot" ,
12
14
"containers" ,
25
27
]
26
28
27
29
28
- @dataclass (frozen = True )
29
- class Tag :
30
+ class Tag (BaseModel ):
30
31
"""Representation of a plugin tag."""
31
32
32
33
value : AllowedTagType
33
34
34
- def __post_init__ (self ):
35
+ @field_validator ("value" , mode = "before" )
36
+ def _validate_value (cls , v ) -> AllowedTagType :
35
37
allowed_tags = set (AllowedTagType .__args__ )
36
- if self . value not in allowed_tags :
38
+ if v not in allowed_tags :
37
39
raise ValueError (f"Invalid tag: { self .value } . Allowed: { allowed_tags } " )
40
+ return v
38
41
39
42
@property
40
43
def title_case (self ) -> str :
@@ -48,11 +51,10 @@ def __eq__(self, other):
48
51
return NotImplemented
49
52
50
53
51
- ALLOWED_TAGS = [Tag (tag ) for tag in set (AllowedTagType .__args__ )]
54
+ ALLOWED_TAGS = [Tag (value = tag ) for tag in set (AllowedTagType .__args__ )]
52
55
53
56
54
- @dataclass
55
- class Plugin :
57
+ class Plugin (BaseModel ):
56
58
"""Representation of a pyinfra plugin."""
57
59
58
60
name : str
@@ -61,18 +63,16 @@ class Plugin:
61
63
type : Literal ["operation" , "fact" , "connector" , "deploy" ]
62
64
tags : list [Tag ]
63
65
66
+ @field_validator ("tags" , mode = "before" )
67
+ def _wrap_tags (cls , v ):
68
+ return [Tag (value = tag ) if not isinstance (tag , Tag ) else tag for tag in v ]
69
+
64
70
65
71
def parse_plugins (metadata_text : str ) -> list [Plugin ]:
66
72
"""Given the contents of a pyinfra-metadata.toml parse out the plugins."""
67
73
pyinfra_metadata = tomllib .loads (metadata_text ).get ("pyinfra" , None )
68
74
if not pyinfra_metadata :
69
75
raise ValueError ("Missing [pyinfra.plugins] section in pyinfra-metadata.toml" )
70
-
71
- plugins = []
72
- for p in pyinfra_metadata ["plugins" ]:
73
- data = pyinfra_metadata ["plugins" ][p ]
74
- # ensure Tag types and not strings
75
- data ["tags" ] = [Tag (t ) for t in data ["tags" ]]
76
- plugin = Plugin (** data )
77
- plugins .append (plugin )
78
- return plugins
76
+ return TypeAdapter (list [Plugin ]).validate_python (
77
+ pyinfra_metadata ["plugins" ].values ()
78
+ )
0 commit comments