5
5
import string
6
6
from configparser import RawConfigParser
7
7
from itertools import chain
8
+ from typing import IO
9
+ from typing import Any
10
+ from typing import Generator
8
11
9
12
from .. import PROJECT_HOME
10
13
from .. import exceptions
11
14
from ..utils import cached_property
12
15
from ..utils import expand_path
16
+ from ..vobject import Item
13
17
from .fetchparams import expand_fetch_params
14
18
from .utils import storage_class_from_config
15
19
@@ -29,10 +33,10 @@ def validate_section_name(name, section_type):
29
33
)
30
34
31
35
32
- def _validate_general_section (general_config ):
36
+ def _validate_general_section (general_config : dict [ str , str ] ):
33
37
invalid = set (general_config ) - GENERAL_ALL
34
38
missing = GENERAL_REQUIRED - set (general_config )
35
- problems = []
39
+ problems : list [ str ] = []
36
40
37
41
if invalid :
38
42
problems .append (
@@ -92,17 +96,22 @@ def _validate_collections_param(collections):
92
96
93
97
94
98
class _ConfigReader :
95
- def __init__ (self , f ):
96
- self ._file = f
99
+ def __init__ (self , f : IO [ Any ] ):
100
+ self ._file : IO [ Any ] = f
97
101
self ._parser = c = RawConfigParser ()
98
102
c .read_file (f )
99
- self ._seen_names = set ()
100
-
101
- self ._general = {}
102
- self ._pairs = {}
103
- self ._storages = {}
104
-
105
- def _parse_section (self , section_type , name , options ):
103
+ self ._seen_names : set = set ()
104
+
105
+ self ._general : dict [str , str ] = {}
106
+ self ._pairs : dict [str , dict [str , str ]] = {}
107
+ self ._storages : dict [str , dict [str , str ]] = {}
108
+
109
+ def _parse_section (
110
+ self ,
111
+ section_type : str ,
112
+ name : str ,
113
+ options : dict [str , Any ]
114
+ ) -> None :
106
115
validate_section_name (name , section_type )
107
116
if name in self ._seen_names :
108
117
raise ValueError (f'Name "{ name } " already used.' )
@@ -119,7 +128,9 @@ def _parse_section(self, section_type, name, options):
119
128
else :
120
129
raise ValueError ("Unknown section type." )
121
130
122
- def parse (self ):
131
+ def parse (
132
+ self
133
+ ) -> tuple [dict [str , str ], dict [str , dict [str , str ]], dict [str , dict [str , str ]]]:
123
134
for section in self ._parser .sections ():
124
135
if " " in section :
125
136
section_type , name = section .split (" " , 1 )
@@ -145,7 +156,10 @@ def parse(self):
145
156
return self ._general , self ._pairs , self ._storages
146
157
147
158
148
- def _parse_options (items , section = None ):
159
+ def _parse_options (
160
+ items : list [tuple [str , str ]],
161
+ section : str | None = None
162
+ ) -> Generator [tuple [str , dict [str , str ]], None , None ]:
149
163
for key , value in items :
150
164
try :
151
165
yield key , json .loads (value )
@@ -154,26 +168,31 @@ def _parse_options(items, section=None):
154
168
155
169
156
170
class Config :
157
- def __init__ (self , general , pairs , storages ):
171
+ def __init__ (
172
+ self ,
173
+ general : dict [str , str ],
174
+ pairs : dict [str , dict [str , str ]],
175
+ storages : dict [str , dict [str , str ]]
176
+ ) -> None :
158
177
self .general = general
159
178
self .storages = storages
160
179
for name , options in storages .items ():
161
180
options ["instance_name" ] = name
162
181
163
- self .pairs = {}
182
+ self .pairs : dict [ str , PairConfig ] = {}
164
183
for name , options in pairs .items ():
165
184
try :
166
185
self .pairs [name ] = PairConfig (self , name , options )
167
186
except ValueError as e :
168
187
raise exceptions .UserError (f"Pair { name } : { e } " )
169
188
170
189
@classmethod
171
- def from_fileobject (cls , f ):
190
+ def from_fileobject (cls , f : IO [ Any ] ):
172
191
reader = _ConfigReader (f )
173
192
return cls (* reader .parse ())
174
193
175
194
@classmethod
176
- def from_filename_or_environment (cls , fname = None ):
195
+ def from_filename_or_environment (cls , fname : str | None = None ):
177
196
if fname is None :
178
197
fname = os .environ .get ("VDIRSYNCER_CONFIG" , None )
179
198
if fname is None :
@@ -190,7 +209,7 @@ def from_filename_or_environment(cls, fname=None):
190
209
except Exception as e :
191
210
raise exceptions .UserError (f"Error during reading config { fname } : { e } " )
192
211
193
- def get_storage_args (self , storage_name ):
212
+ def get_storage_args (self , storage_name : str ):
194
213
try :
195
214
args = self .storages [storage_name ]
196
215
except KeyError :
@@ -211,13 +230,13 @@ def get_pair(self, pair_name: str) -> PairConfig:
211
230
212
231
213
232
class PairConfig :
214
- def __init__ (self , full_config , name , options ):
215
- self ._config = full_config
216
- self .name = name
217
- self .name_a = options .pop ("a" )
218
- self .name_b = options .pop ("b" )
233
+ def __init__ (self , full_config : Config , name : str , options : dict [ str , str ] ):
234
+ self ._config : Config = full_config
235
+ self .name : str = name
236
+ self .name_a : str = options .pop ("a" )
237
+ self .name_b : str = options .pop ("b" )
219
238
220
- self ._partial_sync = options .pop ("partial_sync" , None )
239
+ self ._partial_sync : str | None = options .pop ("partial_sync" , None )
221
240
self .metadata = options .pop ("metadata" , None ) or ()
222
241
223
242
self .conflict_resolution = self ._process_conflict_resolution_param (
@@ -238,7 +257,10 @@ def __init__(self, full_config, name, options):
238
257
if options :
239
258
raise ValueError ("Unknown options: {}" .format (", " .join (options )))
240
259
241
- def _process_conflict_resolution_param (self , conflict_resolution ):
260
+ def _process_conflict_resolution_param (
261
+ self ,
262
+ conflict_resolution : str | list [str ] | None
263
+ ):
242
264
if conflict_resolution in (None , "a wins" , "b wins" ):
243
265
return conflict_resolution
244
266
elif (
@@ -302,10 +324,10 @@ def partial_sync(self):
302
324
303
325
304
326
class CollectionConfig :
305
- def __init__ (self , pair , name , config_a , config_b ):
327
+ def __init__ (self , pair , name : str , config_a , config_b ):
306
328
self .pair = pair
307
329
self ._config = pair ._config
308
- self .name = name
330
+ self .name : str = name
309
331
self .config_a = config_a
310
332
self .config_b = config_b
311
333
@@ -314,7 +336,14 @@ def __init__(self, pair, name, config_a, config_b):
314
336
load_config = Config .from_filename_or_environment
315
337
316
338
317
- def _resolve_conflict_via_command (a , b , command , a_name , b_name , _check_call = None ):
339
+ def _resolve_conflict_via_command (
340
+ a ,
341
+ b ,
342
+ command ,
343
+ a_name ,
344
+ b_name ,
345
+ _check_call = None
346
+ ) -> Item :
318
347
import shutil
319
348
import tempfile
320
349
0 commit comments