Skip to content

Commit 3addc27

Browse files
style: add type annotations
1 parent 022c515 commit 3addc27

1 file changed

Lines changed: 45 additions & 9 deletions

File tree

juju/constraints.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#
2020

2121
import re
22+
from typing import Dict, List, Optional, TypedDict, Union
23+
from typing_extensions import Required, NotRequired
24+
2225

2326
# Matches on a string specifying memory size
2427
MEM = re.compile('^[1-9][0-9]*[MGTP]$')
@@ -61,7 +64,28 @@
6164
SNAKE2 = re.compile('([a-z0-9])([A-Z])')
6265

6366

64-
def parse(constraints):
67+
ParsedValue = Union[int, bool, str]
68+
69+
70+
class ConstraintsDict(TypedDict, total=False):
71+
allocate_public_ip: ParsedValue
72+
arch: ParsedValue
73+
container: ParsedValue
74+
cores: ParsedValue
75+
cpu_cores: ParsedValue
76+
cpu_power: ParsedValue
77+
instance_role: ParsedValue
78+
instance_type: ParsedValue
79+
mem: ParsedValue
80+
root_disk: ParsedValue
81+
root_dist_source: ParsedValue
82+
spaces: List[ParsedValue]
83+
tags: List[ParsedValue]
84+
virt_type: ParsedValue
85+
zones: List[ParsedValue]
86+
87+
88+
def parse(constraints: Union[str, ConstraintsDict]) -> Optional[ConstraintsDict]:
6589
"""
6690
Constraints must be expressed as a string containing only spaces
6791
and key value pairs joined by an '='.
@@ -74,7 +98,7 @@ def parse(constraints):
7498
# Fowards compatibilty: already parsed
7599
return constraints
76100

77-
normalized_constraints = {}
101+
normalized_constraints: ConstraintsDict = {}
78102
for s in constraints.split(" "):
79103
if "=" not in s:
80104
raise ValueError("malformed constraint %s" % s)
@@ -89,7 +113,7 @@ def parse(constraints):
89113
return normalized_constraints
90114

91115

92-
def normalize_key(orig_key):
116+
def normalize_key(orig_key: str) -> str:
93117
key = orig_key.strip()
94118

95119
key = key.replace("-", "_") # Our _client lib wants "_" in place of "-"
@@ -103,7 +127,7 @@ def normalize_key(orig_key):
103127
return key
104128

105129

106-
def normalize_value(value):
130+
def normalize_value(value: str) -> Union[int, bool, str]:
107131
value = value.strip()
108132

109133
if MEM.match(value):
@@ -121,7 +145,7 @@ def normalize_value(value):
121145
return value
122146

123147

124-
def normalize_list_value(value):
148+
def normalize_list_value(value: str) -> List[ParsedValue]:
125149
values = value.strip().split(',')
126150
return [normalize_value(value) for value in values]
127151

@@ -130,8 +154,14 @@ def normalize_list_value(value):
130154
'(?:(?:^|(?<=,))(?:|(?P<pool>[a-zA-Z]+[-?a-zA-Z0-9]*)|(?P<count>-?[0-9]+)|(?:(?P<size>-?[0-9]+(?:\\.[0-9]+)?)(?P<size_exp>[MGTPEZY])(?:i?B)?))(?:$|,))')
131155

132156

133-
def parse_storage_constraint(constraint):
134-
storage = {'count': 1}
157+
class StorageConstraintDict(TypedDict):
158+
count: Required[int] # >= 1
159+
pool: NotRequired[str]
160+
size: NotRequired[int]
161+
162+
163+
def parse_storage_constraint(constraint: str) -> StorageConstraintDict:
164+
storage: StorageConstraintDict = {'count': 1}
135165
for m in STORAGE.finditer(constraint):
136166
pool = m.group('pool')
137167
if pool:
@@ -153,11 +183,17 @@ def parse_storage_constraint(constraint):
153183
ATTR = re.compile(';?(?P<key>[^=]+)=(?P<value>[^;]+)')
154184

155185

156-
def parse_device_constraint(constraint):
186+
class DeviceConstraintDict(TypedDict):
187+
count: Required[int]
188+
type: Required[str]
189+
attributes: NotRequired[Dict[str, str]]
190+
191+
192+
def parse_device_constraint(constraint: str) -> DeviceConstraintDict:
157193
m = DEVICE.match(constraint)
158194
if m is None:
159195
raise ValueError("device constraint does not match")
160-
device = {}
196+
device: DeviceConstraintDict = {}
161197
count = m.group('count')
162198
if count:
163199
count = int(count)

0 commit comments

Comments
 (0)