Example #1
0
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
Example #2
0
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)
Example #3
0
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()
Example #4
0
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()
Example #5
0
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
Example #6
0
    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'])
Example #7
0
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
Example #8
0
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
Example #9
0
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)
Example #10
0
    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'])
Example #11
0
 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
Example #12
0
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
Example #13
0
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
Example #14
0
    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'])