Нужен дизайн шаблона предложения - PullRequest
0 голосов
/ 03 ноября 2018

Мне нужна помощь, чтобы украсить этот код :) Метод defineAction будет вызывать класс, основанный на аргументах. Есть некоторый способ обобщить этот кусок кода, принимая во внимание, что классы похожи. Заранее спасибо

Основной класс

def defineAction(args):

    if args.classabc is not None:
        for host in config.getList('ABC', 'hosts'):
            class_abc = ClassABC(config.getConfigs('ABC', host), args.version[0], user, password)
            class_abc.action(args.classabc)

    if args.classxyz is not None:
        for host in config.getList('XYZ', 'hosts'):
            class_xyz = ClassXYZ(config.getConfigs('XYZ', host), args.version[0], user, password)
            class_xyz.action(args.classxyz)

    # ...

def main():

    parser.add_argument('--classabc', choices=['cmd'])
    parser.add_argument('--classxyz', choices=['cmd'])
    # ...
    args = parser.parse_args()
    defineAction(args)

подклассы

class ClassABC:
    def __init__(self, configs, user, password):
        self.hostConfigs = configs['host']
        self.host_username = user
        self.host_password = password

    def a_method(self):
        # This Method is equal in all subclasses
    def b_method(self):
        # This Method is different all subclasses

    def action(self, action):
        self.a_method()
        self.b_method()

        if action == 'cmd':
            self.execute_cmd()

ФАЙЛ КОНФИГ.

[ABC]
hosts=abc_host1
var_abc=value1

[XYZ]
hosts=xyz_host1,xyz_host2
var_xyz=value2

1 Ответ

0 голосов
/ 03 ноября 2018

Я работаю в предположении, что переключатели являются взаимоисключающими (в этом случае вы действительно хотите использовать взаимоисключающую группу аргументов ).

Вы хотите, чтобы действие argparser установило class . Если вашему параметру командной строки не нужно принимать никаких аргументов, тогда я бы использовал action="store_const" здесь:

parser.add_argument(
    '--classabc', dest="class_", const=ClassABC,
    action="store_const")
parser.add_argument(
    '--classxyz', dest="class_", const=ClassXYZ,
    action="store_const")

При разборе вышеуказанные действия устанавливают args.class_ в ClassABC или ClassXYZ, когда используется тот или иной переключатель. Дайте классам метод класса или атрибут, чтобы определить, в какой раздел конфигурации искать, не указывайте эти имена жестко где-либо еще.

Например, если оба класса имеют атрибут config_section (установлен 'ABC' для ClassABC и 'XYZ' для ClassXZY), то вы можете использовать этот атрибут в цикле создания экземпляров:

if args.class_:
    for host in config.getList(class_.config_section, 'hosts'):
        instance = args.class_(config.getConfig(class_.config_section, host), ...)

Идея состоит в том, чтобы не переключаться на основе args атрибутов, вы можете оставить это значение на argparse, так как оно уже определяет различные варианты для вас.

Если оба параметра командной строки требуют дополнительного аргумента, создайте пользовательский Action подкласс :

class StoreClassAction(argparse.Action):
    def __call__(self, parser, namespace, values, **kwargs):
        setattr(namespace, self.dest, (self.const, values)

затем используйте это как:

parser.add_argument(
    '--classabc', dest="class_", choices=['cmd'], const=ClassABC,
    action=StoreClassAction)
parser.add_argument(
    '--classxyz', dest="class_", choices=['cmd'], const=ClassXYZ,
     action=StoreClassAction)

Теперь аргумент args.class_ установлен на (classobject, argumentvalue), поэтому вы можете использовать:

if args.class_:
    cls, action = args.class_
    for host in config.getList(cls.config_section, 'hosts'):
        instance = args.class_(config.getConfig(cls.config_section, host), ...)
        instance.action(action)
...