diff options
| author | J08nY | 2017-08-07 19:00:49 +0200 |
|---|---|---|
| committer | J08nY | 2017-08-07 19:00:49 +0200 |
| commit | ee9da27283ffb7adc836f764f1442cd06e3fb2a5 (patch) | |
| tree | 2b687f39714580b1de70baf9e3dd9957326c4989 /src/mailman/utilities | |
| parent | d107fd41f03b57f7731b60bb7ba921febc3ce3b9 (diff) | |
| parent | b902d7858d8302d248add89a5983c521c3581c4c (diff) | |
| download | mailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.tar.gz mailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.tar.zst mailman-ee9da27283ffb7adc836f764f1442cd06e3fb2a5.zip | |
Diffstat (limited to 'src/mailman/utilities')
| -rw-r--r-- | src/mailman/utilities/importer.py | 17 | ||||
| -rw-r--r-- | src/mailman/utilities/modules.py | 27 | ||||
| -rw-r--r-- | src/mailman/utilities/plugins.py | 3 | ||||
| -rw-r--r-- | src/mailman/utilities/tests/test_import.py | 22 | ||||
| -rw-r--r-- | src/mailman/utilities/tests/test_modules.py | 4 |
5 files changed, 44 insertions, 29 deletions
diff --git a/src/mailman/utilities/importer.py b/src/mailman/utilities/importer.py index 578e95dff..c5e73bcc5 100644 --- a/src/mailman/utilities/importer.py +++ b/src/mailman/utilities/importer.py @@ -35,14 +35,16 @@ from mailman.interfaces.digests import DigestFrequency from mailman.interfaces.errors import MailmanError from mailman.interfaces.languages import ILanguageManager from mailman.interfaces.mailinglist import ( - IAcceptableAliasSet, IHeaderMatchList, Personalization, ReplyToMunging, - SubscriptionPolicy) + IAcceptableAliasSet, IHeaderMatchList, Personalization, ReplyToMunging) from mailman.interfaces.member import DeliveryMode, DeliveryStatus, MemberRole from mailman.interfaces.nntp import NewsgroupModeration from mailman.interfaces.template import ITemplateManager from mailman.interfaces.usermanager import IUserManager from mailman.utilities.filesystem import makedirs from mailman.utilities.i18n import search +from mailman.workflows.subscription import ( + ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy, + ModerationSubscriptionPolicy, OpenSubscriptionPolicy) from public import public from sqlalchemy import Boolean from zope.component import getUtility @@ -138,6 +140,15 @@ def action_to_chain(value): }[value] +def sub_policy_to_class(value): + return { + 0: OpenSubscriptionPolicy, + 1: ConfirmSubscriptionPolicy, + 2: ModerationSubscriptionPolicy, + 3: ConfirmModerationSubscriptionPolicy + }[value] + + def check_language_code(code): if code is None: return None @@ -180,7 +191,7 @@ TYPES = dict( personalize=Personalization, preferred_language=check_language_code, reply_goes_to_list=ReplyToMunging, - subscription_policy=SubscriptionPolicy, + subscription_policy=sub_policy_to_class, ) diff --git a/src/mailman/utilities/modules.py b/src/mailman/utilities/modules.py index 155a34ed2..eb8f7184a 100644 --- a/src/mailman/utilities/modules.py +++ b/src/mailman/utilities/modules.py @@ -71,19 +71,18 @@ def call_name(dotted_name, *args, **kws): def scan_module(module, interface): - """Return all the object in a module that conform to an interface. + """Return all the items in a module that conform to an interface. Scan every item named in the module's `__all__`. If that item conforms to the given interface, *and* the item is not declared as an - `@abstract_component`, then instantiate the item and return the resulting - instance. + `@abstract_component`, then return the item. :param module: A module object. :type module: module :param interface: The interface that returned objects must conform to. :type interface: `Interface` - :return: The sequence of instantiated matching components. - :rtype: instantiated objects implementing `interface` + :return: The sequence of matching components. + :rtype: items implementing `interface` """ missing = object() for name in module.__all__: @@ -99,7 +98,7 @@ def scan_module(module, interface): # where the marker has been placed. The value of # __abstract_component__ doesn't matter, only its presence. and '__abstract_component__' not in component.__dict__): - yield component() + yield component @public @@ -107,15 +106,15 @@ def find_components(package, interface): """Find components which conform to a given interface. Search all the modules in a given package, returning an iterator over all - objects found that conform to the given interface, unless that object is + items found that conform to the given interface, unless that object is decorated with `@abstract_component`. :param package: The package path to search. :type package: string :param interface: The interface that returned objects must conform to. :type interface: `Interface` - :return: The sequence of instantiated matching components. - :rtype: instantiated objects implementing `interface` + :return: The sequence of matching components. + :rtype: items implementing `interface` """ for filename in resource_listdir(package, ''): basename, extension = os.path.splitext(filename) @@ -135,9 +134,10 @@ def add_components(package, interface, mapping): Similarly to `find_components()` this inspects all modules in a given package looking for objects that conform to a given interface. All such - found objects (unless decorated with `@abstract_component`) are added to - the given mapping, keyed by the object's `.name` attribute, which is - required. It is a fatal error if that key already exists in the mapping. + found objects (unless decorated with `@abstract_component`) are + instantiated and added to the given mapping, keyed by the object's `.name` + attribute, which is required. It is a fatal error if that key already + exists in the mapping. :param package: The package path to search. :type package: string @@ -150,7 +150,8 @@ def add_components(package, interface, mapping): containment tests (e.g. `in` and `not in`) and `__setitem__()`. :raises RuntimeError: when a duplicate key is found. """ - for component in find_components(package, interface): + for component_class in find_components(package, interface): + component = component_class() if component.name in mapping: raise RuntimeError( 'Duplicate key "{}" found in {}; previously {}'.format( diff --git a/src/mailman/utilities/plugins.py b/src/mailman/utilities/plugins.py index aad909056..1a8c6d461 100644 --- a/src/mailman/utilities/plugins.py +++ b/src/mailman/utilities/plugins.py @@ -68,7 +68,8 @@ def add_pluggable_components(subpackage, interface, mapping): containment tests (e.g. `in` and `not in`) and `__setitem__()`. :raises RuntimeError: when a duplicate key is found. """ - for component in find_pluggable_components(subpackage, interface): + for component_class in find_pluggable_components(subpackage, interface): + component = component_class() if component.name in mapping: raise RuntimeError( # pragma: nocover 'Duplicate key "{}" found in {}; previously {}'.format( diff --git a/src/mailman/utilities/tests/test_import.py b/src/mailman/utilities/tests/test_import.py index b1b4764ff..6db0c4a4a 100644 --- a/src/mailman/utilities/tests/test_import.py +++ b/src/mailman/utilities/tests/test_import.py @@ -33,8 +33,7 @@ from mailman.interfaces.bans import IBanManager from mailman.interfaces.bounce import UnrecognizedBounceDisposition from mailman.interfaces.domain import IDomainManager from mailman.interfaces.languages import ILanguageManager -from mailman.interfaces.mailinglist import ( - IAcceptableAliasSet, SubscriptionPolicy) +from mailman.interfaces.mailinglist import IAcceptableAliasSet from mailman.interfaces.member import DeliveryMode, DeliveryStatus from mailman.interfaces.nntp import NewsgroupModeration from mailman.interfaces.template import ITemplateLoader, ITemplateManager @@ -44,6 +43,9 @@ from mailman.testing.layers import ConfigLayer from mailman.utilities.filesystem import makedirs from mailman.utilities.importer import ( Import21Error, check_language_code, import_config_pck) +from mailman.workflows.subscription import ( + ConfirmModerationSubscriptionPolicy, ConfirmSubscriptionPolicy, + ModerationSubscriptionPolicy, OpenSubscriptionPolicy) from pickle import load from pkg_resources import resource_filename from unittest import mock @@ -295,32 +297,32 @@ class TestBasicImport(unittest.TestCase): self.assertEqual(self._mlist.encode_ascii_prefixes, True) def test_subscription_policy_open(self): - self._mlist.subscription_policy = SubscriptionPolicy.confirm + self._mlist.subscription_policy = ConfirmSubscriptionPolicy self._pckdict['subscribe_policy'] = 0 self._import() self.assertEqual(self._mlist.subscription_policy, - SubscriptionPolicy.open) + OpenSubscriptionPolicy) def test_subscription_policy_confirm(self): - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._pckdict['subscribe_policy'] = 1 self._import() self.assertEqual(self._mlist.subscription_policy, - SubscriptionPolicy.confirm) + ConfirmSubscriptionPolicy) def test_subscription_policy_moderate(self): - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._pckdict['subscribe_policy'] = 2 self._import() self.assertEqual(self._mlist.subscription_policy, - SubscriptionPolicy.moderate) + ModerationSubscriptionPolicy) def test_subscription_policy_confirm_then_moderate(self): - self._mlist.subscription_policy = SubscriptionPolicy.open + self._mlist.subscription_policy = OpenSubscriptionPolicy self._pckdict['subscribe_policy'] = 3 self._import() self.assertEqual(self._mlist.subscription_policy, - SubscriptionPolicy.confirm_then_moderate) + ConfirmModerationSubscriptionPolicy) def test_header_matches(self): # This test containes real cases of header_filter_rules. diff --git a/src/mailman/utilities/tests/test_modules.py b/src/mailman/utilities/tests/test_modules.py index 82d44cff4..08ec3848a 100644 --- a/src/mailman/utilities/tests/test_modules.py +++ b/src/mailman/utilities/tests/test_modules.py @@ -99,8 +99,8 @@ class BadStyle: in find_components('mypackage', IStyle)] self.assertEqual(names, ['good-style']) - def test_find_components_no_instantiate(self): - # find_components() now instantiates the class unless it's been + 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. |
