1- import cmd
2- import csv
3- import functools
4- import re
51from abc import ABC , abstractmethod
2+ import cmd
63from collections .abc import Mapping
4+ import csv
75from dataclasses import dataclass
86from enum import Enum
7+ import functools
8+ import itertools
99from pathlib import Path
10+ import re
11+ from typing import Iterable
1012
1113import sqlalchemy
1214from prettytable import PrettyTable
@@ -1518,15 +1520,18 @@ def do_unset(self, _arg):
15181520 self .set_generator (None )
15191521 self ._go_next ()
15201522
1521- def do_merge (self , arg : str ):
1522- """ Add this column(s) to the specified column(s), so one generator covers them all. """
1523+ def merge_columns (self , arg : str ) -> bool :
1524+ """
1525+ Add this column(s) to the specified column(s), so one generator covers them all.
1526+ :return: True if everything worked, False if there is an error
1527+ """
15231528 cols = arg .split ()
15241529 if not cols :
15251530 self .print ("Error: merge requires a column argument" )
15261531 table_entry : GeneratorCmdTableEntry = self .get_table ()
15271532 if table_entry is None :
15281533 self .print (self .ERROR_NO_SUCH_TABLE )
1529- return
1534+ return False
15301535 cols_available = functools .reduce (lambda x , y : x | y , [
15311536 frozenset (gen .columns )
15321537 for gen in table_entry .new_generators
@@ -1536,14 +1541,14 @@ def do_merge(self, arg: str):
15361541 if unknown_cols :
15371542 for uc in unknown_cols :
15381543 self .print (self .ERROR_NO_SUCH_COLUMN , uc )
1539- return
1544+ return False
15401545 gen_info = table_entry .new_generators [self .generator_index ]
15411546 current_columns = frozenset (gen_info .columns )
15421547 stated_current_columns = cols_to_merge & current_columns
15431548 if stated_current_columns :
15441549 for c in stated_current_columns :
15451550 self .print (self .ERROR_COLUMN_ALREADY_MERGED , c )
1546- return
1551+ return False
15471552 # Remove cols_to_merge from each generator
15481553 new_new_generators : list [GeneratorInfo ] = []
15491554 for gen in table_entry .new_generators :
@@ -1570,6 +1575,11 @@ def do_merge(self, arg: str):
15701575 )
15711576 table_entry .new_generators = new_new_generators
15721577 self .set_prompt ()
1578+ return True
1579+
1580+ def do_merge (self , arg : str ):
1581+ """ Add this column(s) to the specified column(s), so one generator covers them all. """
1582+ self .merge_columns (arg )
15731583
15741584 def complete_merge (self , text : str , _line : str , _begidx : int , _endidx : int ):
15751585 last_arg = text .split ()[- 1 ]
@@ -1632,6 +1642,35 @@ def complete_unmerge(self, text: str, _line: str, _begidx: int, _endidx: int):
16321642 if column .startswith (last_arg )
16331643 ]
16341644
1645+ def get_current_columns (self ) -> set [str ]:
1646+ table_entry : GeneratorCmdTableEntry = self .get_table ()
1647+ gen_info = table_entry .new_generators [self .generator_index ]
1648+ return set (gen_info .columns )
1649+
1650+ def set_merged_columns (self , first_col : str , other_cols : str ) -> bool :
1651+ """
1652+ Merge columns, after unmerging everything we don't want
1653+ :param first_col: The first column we want in the merge, must already
1654+ be in this column set.
1655+ :param other_cols: all the columns we want merged other than
1656+ first_col, in order, space-separated.
1657+ :return: True if the merge worked, false if there was an error
1658+ """
1659+ existing = self .get_current_columns ()
1660+ existing .discard (first_col )
1661+ for to_remove in existing :
1662+ self .do_unmerge (to_remove )
1663+ return self .merge_columns (other_cols )
1664+
1665+
1666+ def try_setting_generator (gc : GeneratorCmd , gens : Iterable [str ]) -> bool :
1667+ for gen in gens :
1668+ new_gen = gc .get_proposed_generator_by_name (gen )
1669+ if new_gen is not None :
1670+ gc .set_generator (new_gen )
1671+ return True
1672+ return False
1673+
16351674
16361675def update_config_generators (
16371676 src_dsn : str ,
@@ -1649,9 +1688,13 @@ def update_config_generators(
16491688 for line in csv .reader (spec ):
16501689 line_no += 1
16511690 if line :
1652- if len (line ) != 3 :
1653- logger .error ("line {0} of file {1} does not have three values" , line_no , spec_path )
1654- if gc .go_to (f"{ line [0 ]} .{ line [1 ]} " ):
1655- gc .do_set (line [2 ])
1691+ if len (line ) < 3 :
1692+ logger .error ("line {0} of file {1} has fewer than three values" , line_no , spec_path )
1693+ cols = line [1 ].split (maxsplit = 1 )
1694+ if gc .go_to (f"{ line [0 ]} .{ cols [0 ]} " ):
1695+ if len (cols ) == 1 or gc .set_merged_columns (cols [0 ], cols [1 ]):
1696+ try_setting_generator (gc , itertools .islice (line , 2 , None ))
1697+ else :
1698+ logger .warning ("no such column {0}[{1}]" , line [0 ], line [1 ])
16561699 gc .do_quit ("yes" )
16571700 return gc .config
0 commit comments