def initialize(): """Find and register all rules in all plugins.""" # Find rules in plugins. for rule_class in find_components("mailman.rules", IRule): rule = rule_class() verifyObject(IRule, rule) assert rule.name not in config.rules, 'Duplicate rule "{0}" found in {1}'.format(rule.name, rule_class) config.rules[rule.name] = rule
def main(): """bin/mailman""" # Create the basic parser and add all globally common options. parser = argparse.ArgumentParser( description=_("""\ The GNU Mailman mailing list management system Copyright 1998-2013 by the Free Software Foundation, Inc. http://www.list.org """), formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument( '-v', '--version', action='version', version=MAILMAN_VERSION_FULL, help=_('Print this version string and exit')) parser.add_argument( '-C', '--config', help=_("""\ Configuration file to use. If not given, the environment variable MAILMAN_CONFIG_FILE is consulted and used if set. If neither are given, a default configuration file is loaded.""")) # Look at all modules in the mailman.bin package and if they are prepared # to add a subcommand, let them do so. I'm still undecided as to whether # this should be pluggable or not. If so, then we'll probably have to # partially parse the arguments now, then initialize the system, then find # the plugins. Punt on this for now. subparser = parser.add_subparsers(title='Commands') subcommands = [] for command_class in find_components('mailman.commands', ICLISubCommand): command = command_class() verifyObject(ICLISubCommand, command) subcommands.append(command) # --help should display the subcommands by alphabetical order, except that # 'mailman help' should be first. def sort_function(command, other): """Sorting helper.""" if command.name == 'help': return -1 elif other.name == 'help': return 1 else: return cmp(command.name, other.name) subcommands.sort(cmp=sort_function) for command in subcommands: command_parser = subparser.add_parser( command.name, help=_(command.__doc__)) command.add(parser, command_parser) command_parser.set_defaults(func=command.process) args = parser.parse_args() if len(args.__dict__) == 0: # No arguments or subcommands were given. parser.print_help() parser.exit() # Initialize the system. Honor the -C flag if given. config_path = (None if args.config is None else os.path.abspath(os.path.expanduser(args.config))) initialize(config_path) # Perform the subcommand option. args.func(args)
def initialize(): """Initialize the email commands.""" for command_class in find_components('mailman.commands', IEmailCommand): command = command_class() verifyObject(IEmailCommand, command) assert command_class.name not in config.commands, ( 'Duplicate email command "{0}" found in {1}'.format( command_class.name, command_class.__module__)) config.commands[command_class.name] = command_class()
def initialize(): """Find and register all rules in all plugins.""" # Find rules in plugins. for rule_class in find_components('mailman.rules', IRule): rule = rule_class() verifyObject(IRule, rule) assert rule.name not in config.rules, ( 'Duplicate rule "{}" found in {}'.format(rule.name, rule_class)) config.rules[rule.name] = rule
def test_find_modules_with_dotfiles(self): # Emacs creates lock files when a single file is opened by more than # one user. These files look like .#<filename>.py because of which # find_components() tries to import them but fails. All such files # should be ignored by default. with ExitStack() as resources: # Creating a temporary directory and adding it to sys.path. temp_package = resources.enter_context(TemporaryDirectory()) resources.enter_context(hack_syspath(0, temp_package)) resources.callback(clean_mypackage) # Create a module inside the above package along with a good, bad # and __init__.py file so that we can import from it. module_path = os.path.join(temp_package, 'mypackage') os.mkdir(module_path) init_file = os.path.join(module_path, '__init__.py') Path(init_file).touch() good_file = os.path.join(module_path, 'goodfile.py') bad_file = os.path.join(module_path, '.#badfile.py') with open(good_file, 'w', encoding='utf-8') as fp: print("""\ from public import public from mailman.interfaces.styles import IStyle from zope.interface import implementer @public @implementer(IStyle) class GoodStyle: name = 'good-style' def apply(self): pass """, file=fp) with open(bad_file, 'w', encoding='utf-8') as fp: print("""\ from public import public from mailman.interfaces.styles import IStyle from zope.interface import implementer @public @implementer(IStyle) class BadStyle: name = 'bad-style' def apply(self): pass """, file=fp) # Find all the IStyle components in the dummy package. This # should find GoodStyle but not BadStyle. names = [ component.name for component in find_components('mypackage', IStyle) ] self.assertEqual(names, ['good-style'])
def initialize(): """Initialize the pipelines.""" # Find all handlers in the registered plugins. for handler_class in find_components('mailman.handlers', IHandler): handler = handler_class() verifyObject(IHandler, handler) assert handler.name not in config.handlers, ( 'Duplicate handler "{}" found in {}'.format( handler.name, handler_class)) config.handlers[handler.name] = handler # Set up some pipelines. for pipeline_class in (OwnerPipeline, PostingPipeline, VirginPipeline): pipeline = pipeline_class() config.pipelines[pipeline.name] = pipeline
def initialize(): """Initialize the pipelines.""" # Find all handlers in the registered plugins. for handler_class in find_components('mailman.handlers', IHandler): handler = handler_class() verifyObject(IHandler, handler) assert handler.name not in config.handlers, ( 'Duplicate handler "{0}" found in {1}'.format( handler.name, handler_class)) config.handlers[handler.name] = handler # Set up some pipelines. for pipeline_class in (OwnerPipeline, PostingPipeline, VirginPipeline): pipeline = pipeline_class() config.pipelines[pipeline.name] = pipeline
def main(): """The `mailman` command dispatcher.""" # Create the basic parser and add all globally common options. parser = argparse.ArgumentParser( description=_("""\ The GNU Mailman mailing list management system Copyright 1998-2016 by the Free Software Foundation, Inc. http://www.list.org """), formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('-v', '--version', action='version', version=MAILMAN_VERSION_FULL, help=_('Print this version string and exit')) parser.add_argument('-C', '--config', help=_("""\ Configuration file to use. If not given, the environment variable MAILMAN_CONFIG_FILE is consulted and used if set. If neither are given, a default configuration file is loaded.""")) # Look at all modules in the mailman.bin package and if they are prepared # to add a subcommand, let them do so. I'm still undecided as to whether # this should be pluggable or not. If so, then we'll probably have to # partially parse the arguments now, then initialize the system, then find # the plugins. Punt on this for now. subparser = parser.add_subparsers(title='Commands') subcommands = [] for command_class in find_components('mailman.commands', ICLISubCommand): command = command_class() verifyObject(ICLISubCommand, command) subcommands.append(command) subcommands.sort(key=cmp_to_key(_help_sorter)) for command in subcommands: command_parser = subparser.add_parser(command.name, help=_(command.__doc__)) command.add(parser, command_parser) command_parser.set_defaults(func=command.process) args = parser.parse_args() if len(args.__dict__) <= 1: # No arguments or subcommands were given. parser.print_help() parser.exit() # Initialize the system. Honor the -C flag if given. config_path = (None if args.config is None else os.path.abspath( os.path.expanduser(args.config))) initialize(config_path) # Perform the subcommand option. with transaction(): args.func(args)
def test_find_modules_with_dotfiles(self): # Emacs creates lock files when a single file is opened by more than # one user. These files look like .#<filename>.py because of which # find_components tries to import them but fails. All such files should # be ignored by default. with ExitStack() as resources: # Creating a temporary directory and adding it to sys.path. temp_package = resources.enter_context(TemporaryDirectory()) resources.enter_context(hack_syspath(0, temp_package)) resources.callback(clean_mypackage) # Create a module inside the above package along with a good, bad # and __init__.py file so that we can import from it. module_path = os.path.join(temp_package, 'mypackage') os.mkdir(module_path) init_file = os.path.join(module_path, '__init__.py') good_file = os.path.join(module_path, 'goodfile.py') bad_file = os.path.join(module_path, '.#badfile.py') Path(init_file).touch() with open(good_file, 'w', encoding='utf-8') as fp: print("""\ from mailman import public from mailman.interfaces.styles import IStyle from zope.interface import implementer @public @implementer(IStyle) class GoodStyle: name = 'good-style' def apply(self): pass """, file=fp) with open(bad_file, 'w', encoding='utf-8') as fp: print("""\ from mailman import public from mailman.interfaces.styles import IStyle from zope.interface import implementer @public @implementer(IStyle) class BadStyle: name = 'bad-style' def apply(self): pass """, file=fp) # Find all the IStyle components in the dummy package. This # should find GoodStyle but not BadStyle. names = [component.name for component in find_components('mypackage', IStyle)] self.assertEqual(names, ['good-style'])
def populate(self): self._styles.clear() # Avoid circular imports. from mailman.config import config # Calculate the Python import paths to search. paths = filter(None, (path.strip() for path in config.styles.paths.splitlines())) for path in paths: for style_class in find_components(path, IStyle): style = style_class() verifyObject(IStyle, style) assert style.name not in self._styles, ( 'Duplicate style "{0}" found in {1}'.format( style.name, style_class)) self._styles[style.name] = style
def initialize(): """Set up chains, both built-in and from the database.""" for chain_class in find_components('mailman.chains', IChain): # FIXME 2010-12-28 barry: We need a generic way to disable automatic # instantiation of discovered classes. This is useful not just for # chains, but also for rules, handlers, etc. Ideally it should be # part of find_components(). For now, hard code the ones we do not # want to instantiate. if chain_class in (Chain, TerminalChainBase): continue chain = chain_class() verifyObject(IChain, chain) assert chain.name not in config.chains, ( 'Duplicate chain "{}" found in {} (previously: {}'.format( chain.name, chain_class, config.chains[chain.name])) config.chains[chain.name] = chain # XXX Read chains from the database and initialize them. pass
def initialize(): """Set up chains, both built-in and from the database.""" for chain_class in find_components('mailman.chains', IChain): # FIXME 2010-12-28 barry: We need a generic way to disable automatic # instantiation of discovered classes. This is useful not just for # chains, but also for rules, handlers, etc. Ideally it should be # part of find_components(). For now, hard code the ones we do not # want to instantiate. if chain_class in (Chain, TerminalChainBase): continue chain = chain_class() verifyObject(IChain, chain) assert chain.name not in config.chains, ( 'Duplicate chain "{0}" found in {1} (previously: {2}'.format( chain.name, chain_class, config.chains[chain.name])) config.chains[chain.name] = chain # XXX Read chains from the database and initialize them. pass
def test_find_components_abstract_component(self): # find_components() finds the class unless it's been # decorated with the @abstract_component decorator. with ExitStack() as resources: # Creating a temporary directory and adding it to sys.path. temp_package = resources.enter_context(TemporaryDirectory()) resources.enter_context(hack_syspath(0, temp_package)) resources.callback(clean_mypackage) # Create a module inside the above package along with an # __init__.py file so that we can import from it. module_path = os.path.join(temp_package, 'mypackage') os.mkdir(module_path) init_file = os.path.join(module_path, '__init__.py') Path(init_file).touch() component_file = os.path.join(module_path, 'components.py') with open(component_file, 'w', encoding='utf-8') as fp: print("""\ from mailman.interfaces.styles import IStyle from mailman.utilities.modules import abstract_component from public import public from zope.interface import implementer @public @implementer(IStyle) class ConcreteStyle: name = 'concrete-style' def apply(self): pass @public @implementer(IStyle) @abstract_component class AbstractStyle: name = 'abstract-style' def apply(self): pass """, file=fp) names = [ component.name for component in find_components('mypackage', IStyle) ] self.assertEqual(names, ['concrete-style'])