@@ -336,25 +336,14 @@ class TreeBuilder(yaml.YAMLObject):
336336 self .children [key ] = node
337337 return node
338338
339- def _insert_root (self , path : typing .Sequence [int ], name : str ) -> TreeBuilder :
339+ def _insert (self , path : typing .Sequence [int ], version : Version ) :
340340 if len (path ) == 0 :
341- self .name = name
342- self .is_root = True
343- return self
344- key = path [0 ]
345- path = path [1 :]
346- return self ._subnode (key )._insert_root (path , name )
347-
348- def _insert (self , path : typing .Sequence [int ], version : Version , * , found_root : bool = False ):
349- if len (path ) == 0 :
350- assert found_root , f'Version inserted above roots'
351341 assert self .version is None , f'Version already in tree: { version } ({ self .version } )'
352342 self .version = version
353343 return
354- found_root = found_root or self .is_root
355344 key = path [0 ]
356345 path = path [1 :]
357- self ._subnode (key )._insert (path , version , found_root = found_root )
346+ self ._subnode (key )._insert (path , version )
358347
359348 def _build_root_trees (self ) -> typing .Iterable [Tree ]:
360349 if self .is_root :
@@ -380,25 +369,61 @@ class TreeBuilder(yaml.YAMLObject):
380369 tree ._fix_tree ()
381370 return tree
382371
372+
373+ @dataclasses .dataclass
374+ class RootTrees (yaml .YAMLObject ):
375+ @staticmethod
376+ def _default_roots () -> dict [tuple [int , ...], list [tuple [str , TreeBuilder ]]]:
377+ CONFIG = {
378+ (15 , 2 ): ['Exchange Server SE' , 'Exchange Server 2019' ],
379+ (15 , 1 ): ['Exchange Server 2016' ],
380+ (15 , 0 ): ['Exchange Server 2013' ],
381+ (14 ,): ['Exchange Server 2010' ],
382+ (8 ,): ['Exchange Server 2007' ],
383+ (6 , 5 ): ['Exchange Server 2003' ],
384+ (6 , 0 ): ['Exchange 2000 Server' ],
385+ (5 , 5 ): ['Exchange Server 5.5' ],
386+ (5 , 0 ): ['Exchange Server 5.0' ],
387+ (4 , 0 ): ['Exchange Server 4.0' ],
388+ (): ['Unknown version' ],
389+ }
390+ return {
391+ version : [
392+ (name , TreeBuilder (path = version , name = name , is_root = True ))
393+ for name in names
394+ ]
395+ for version , names in CONFIG .items ()
396+ }
397+
398+ roots : dict [tuple [int , ...], tuple [str , TreeBuilder ]] = dataclasses .field (default_factory = _default_roots )
399+
400+ def _insert (self , path : typing .Sequence [int ], version : Version ):
401+ for num in reversed (range (len (path ))):
402+ tbs = self .roots .get (tuple (path [:num ]))
403+ if tbs is None :
404+ continue
405+ if len (tbs ) == 1 :
406+ tbs [0 ][1 ]._insert (path [num :], version )
407+ return
408+ # multiple versions in same "tree" - match using the name
409+ for name , tb in tbs :
410+ if version .name .startswith (name ):
411+ tb ._insert (path [num :], version )
412+ return
413+
414+ raise RuntimeError ("unknown version should have been caught by config" )
415+
416+ def _build_root_trees (self ) -> typing .Iterable [Tree ]:
417+ for tbs in self .roots .values ():
418+ for _ , tb in tbs :
419+ yield from tb ._build_root_trees ()
420+
383421 @staticmethod
384422 def from_versions (versions : typing .Iterable [Version ]) -> 'Tree' :
385- root = TreeBuilder (path = ())
386- for (path , name ) in (
387- ((15 , 2 ), 'Exchange Server 2019' ),
388- ((15 , 1 ), 'Exchange Server 2016' ),
389- ((15 , 0 ), 'Exchange Server 2013' ),
390- ((14 ,), 'Exchange Server 2010' ),
391- ((8 ,), 'Exchange Server 2007' ),
392- ((6 , 5 ), 'Exchange Server 2003' ),
393- ((6 , 0 ), 'Exchange 2000 Server' ),
394- ((5 , 5 ), 'Exchange Server 5.5' ),
395- ((5 , 0 ), 'Exchange Server 5.0' ),
396- ((4 , 0 ), 'Exchange Server 4.0' ),
397- ):
398- root ._insert_root (path , name )
423+ root_tress = RootTrees ()
399424 for version in versions :
400- root ._insert (version .num_code , version )
401- children = list (root ._build_root_trees ())
425+ root_tress ._insert (version .num_code , version )
426+ children = list (root_tress ._build_root_trees ())
402427 root = Tree (path = (), name = '' , html_name = None , version = None , children = children )
403428 for c in children :
404429 c .parent = root
@@ -482,7 +507,7 @@ class Trees:
482507 # assume content is utf-8 (html meta), although not specified in http content-type:
483508 versions = list (Version .scan (ms_release_list .content .decode ('utf-8' )))
484509
485- root = TreeBuilder .from_versions (versions )
510+ root = RootTrees .from_versions (versions )
486511 trees = Trees (trees = root .children , versions = {v .short_code : v for v in versions })
487512 if supported_cus :
488513 trees .calc_alive_supported_cus (supported_cus )
0 commit comments