Commits

Lynn Rees committed 4520e9f

- begin refactor for 0.6.x

  • Participants
  • Parent commits 1f8daeb

Comments (0)

Files changed (7)

File appspace/__init__.py

 # -*- coding: utf-8 -*-
 '''appspace, easy application construction with easy building blocks'''
 
+from appspace.utils import key
 from appspace.registry import Registry, Manager
+from appspace.imps import appifies
 from appspace.keys import (
-    NoAppError, AppLookupError, AppspaceKey, Attribute, appifies)
+    NoAppError, AppLookupError, AppspaceKey, Attribute)
 from appspace.builders import (
     Branch, Patterns, include, space_patterns, patterns, class_patterns)
 

File appspace/builders.py

 # -*- coding: utf-8 -*-
 '''appspace builder'''
 
-from functools import partial
-from itertools import starmap
+from appspace.imps import appifies
 
-from stuf.six import strings
-from stuf.utils import selfname, exhaust, exhaustmap, twoway, imap
-
-from appspace.registry import Manager, StrictManager, lazyimport
-from appspace.keys import (
-    AAppspace, AppLookupError, NoAppError, ABranch, ANamespace, AApp, appifies,
-    AService)
-
-
-class _Filter(object):
-
-    @classmethod
-    def _filter(self, x):
-        return not x[0].startswith('_')
-
-
-class Patterns(_Filter):
-
-    '''patterns for manager configured by class'''
-
-    key = AApp
-    strict = False
-
-    @twoway
-    def _manager(self):
-        '''manager class'''
-        return StrictManager if self.strict else Manager
-
-    @classmethod
-    def build(cls):
-        '''build manager configuration from class'''
-        l = selfname(cls)
-        # set key
-        key = cls.key
-        if isinstance(key, strings):
-            # load key if string
-            key = lazyimport(key)
-        manager = cls._manager(l, key)  # pylint: disable-msg=e1121
-        b = partial(manager.keyed, ABranch)
-        m, n = manager.set, partial(manager.keyed, ANamespace)
-        t = lambda x, y: y.build(manager) if (n(y) or b(y)) else m(y, x, l)
-        exhaustmap(vars(cls), t, cls._filter)
-        return manager
-
-    @staticmethod
-    def factory(label, manager, *args):
-        '''
-        factory for manager
-
-        @param label: label for manager
-        '''
-        # build manager
-        manager = manager(label)
-        # register things in manager
-        exhaust(starmap(lambda x, y: manager.set(y, x), iter(args)))
-        return manager
-
-    @classmethod
-    def patterns(cls, label, *args):
-        '''
-        configure appspace
-
-        @param label: name of branch appspace
-        @param *args: tuple of module paths or component inclusions
-        '''
-        return cls.factory(label, cls._manager, *args)
-    
-class _PatternsMixin(object):
-
-    @classmethod
-    def _key(cls, label, manager):
-        try:
-            # lazily load key
-            key = cls.key
-            if isinstance(key, strings):
-                key = lazyimport(key)
-            # register class key
-            ez_register = manager.ez_register
-            ez_register(ANamespace, label, key)
-            exhaust(imap(
-                lambda x: ez_register(AService, x, label),
-                iter(key.names(True)),
-            ))
-        except AttributeError:
-            key = manager.key(ANamespace, label)
-
-    
-class _PatternMixin(_Filter):
-
-    @classmethod
-    def _key(cls, label, manager):
-        try:
-            # lazily load key
-            key = cls.key
-            if isinstance(key, strings):
-                key = lazyimport(key)
-            # register class key
-            manager.ez_register(ANamespace, label, key)
-        except AttributeError:
-            key = manager.key(ANamespace, label)
-
-
-@appifies(ANamespace)
-class Branch(_PatternMixin):
-
-    '''branch configuration'''
-
-    @classmethod
-    def build(cls, manager):
-        '''gather branch configuration'''
-        cls._key(selfname(cls), manager)
-        i, m = cls.include, manager.set
-        t = lambda x: not x[0].startswith('_') or isinstance(x[1], strings)
-        exhaustmap(vars(cls), lambda x, y: m(i(y), x), t)
-
-    @staticmethod
-    def include(module):
-        '''
-        configure branch appspace
-
-        @param module: module import path
-        '''
-        return ('include', module)
-    
-    
-@appifies(ANamespace)
-class Namespace(_PatternMixin):
-
-    '''configuration namespace'''
-
-    @classmethod
-    def build(cls, manager):
-        '''gather namespace configuration'''
-        label = selfname(cls)
-        cls._key(label, manager)
-        m, n = manager.set, partial(manager.keyed, ANamespace)
-        t = lambda k, v: v.build(manager) if n(v) else m(v, k, label)
-        exhaustmap(vars(cls), t, cls._filter)
+from appspace.keys import AAppspace, AppLookupError, NoAppError
 
 
 @appifies(AAppspace)
             return result
 
 
-factory = Patterns.factory
-include = Branch.include
-space_patterns = Patterns.patterns
-
-def patterns(label, *args, **kw):
-    '''
-    factory for manager
-
-    @param label: label for manager
-    '''
-    return Appspace(space_patterns(label, *args, **kw))
-
-
-def class_patterns(clspatterns):
-    '''
-    factory for manager configured with class patterns
-
-    @param clspatterns: class patterns
-    '''
-    return Appspace(clspatterns.build())
+#factory = Patterns.factory
+#include = Branch.include
+#space_patterns = Patterns.patterns
+#
+#def patterns(label, *args, **kw):
+#    '''
+#    factory for manager
+#
+#    @param label: label for manager
+#    '''
+#    return Appspace(space_patterns(label, *args, **kw))
+#
+#
+#def class_patterns(clspatterns):
+#    '''
+#    factory for manager configured with class patterns
+#
+#    @param clspatterns: class patterns
+#    '''
+#    return Appspace(clspatterns.build())

File appspace/keys.py

 # -*- coding: utf-8 -*-
 '''appspace keys'''
 
-from stuf.utils import exhaustmap
 # pylint: disable-msg=f0401
+from zope.interface import Attribute
 from zope.interface.interface import InterfaceClass
 from zope.interface.interfaces import ComponentLookupError
-from zope.interface import implementer, Attribute, implementedBy
-from zope.interface.adapter import AdapterRegistry, VerifyingAdapterRegistry
 # pylint: enable-msg=f0401
 
-keys = implementedBy
-AppStore = AdapterRegistry
-StrictAppStore = VerifyingAdapterRegistry
 # primary key
 AppspaceKey = InterfaceClass('AppspaceKey')
 # app lookup exception
 AppLookupError = ComponentLookupError
 
 
-class appifies(implementer):
-
-    '''appifier'''
-
-    def __init__(self, key, **metadata):
-        exhaustmap(metadata, key.setTaggedValue)
-        implementer.__init__(self, key)
-
-
 class AApp(AppspaceKey):
 
     '''app key'''

File appspace/registry.py

 import re
 import uuid
 import hashlib
-from inspect import isclass
-from keyword import iskeyword
+from itertools import chain
+from inspect import isclass, getmro
 from unicodedata import normalize
-from importlib import import_module
 
-from stuf.six import u, strings
-from stuf.utils import exhaustmap
+from twoq import twoq
+from stuf.six import u, strings, keys, items
+from stuf.utils import exhaustcall, selfname
 
+from appspace.utils import lazyimport, checkname
+from appspace.imps import appifies, AppStore, StrictAppStore
 from appspace.keys import (
-    ALazyLoad, AppStore, InterfaceClass, AApp, StrictAppStore, ANamespace,
-    AManager, AppLookupError, appifies, keys, ConfigurationError)
-from callchain.services.queue import KService
-
-
-def lazyimport(path, attribute=None):
-    '''
-    deferred module loader
-
-    @param path: something to load
-    @param attribute: attribute on loaded module to return
-    '''
-    if isinstance(path, strings):
-        try:
-            dot = path.rindex('.')
-            # import module
-            path = getattr(import_module(path[:dot]), path[dot + 1:])
-        # If nothing but module name, import the module
-        except (AttributeError, ValueError):
-            path = import_module(path)
-        if attribute:
-            path = getattr(path, attribute)
-    return path
-
-
-class CheckName(object):
-
-    '''ensures string is legal Python name'''
-
-    # Illegal characters for Python names
-    ic = '()[]{}@,:`=;+*/%&|^><\'"#\\$?!~'
-
-    def __call__(self, name):
-        '''
-        ensures string is legal python name
-
-        @param name: name to check
-        '''
-        # Remove characters that are illegal in a Python name
-        name = name.strip().lower().replace('-', '_').replace(
-            '.', '_'
-        ).replace(' ', '_')
-        name = ''.join(i for i in name if i not in self.ic)
-        # Add _ if value is a Python keyword
-        return name + '_' if iskeyword(name) else name
-
-
-checkname = CheckName()
+    ALazyLoad, InterfaceClass, AApp,  ANamespace,
+    AManager, AppLookupError, AService, ConfigurationError)
 
 
 @appifies(ALazyLoad)
             return thing
         app, appkey = thing.path
         key = key if not appkey else appkey
+        if appkey.isOrExtends(ANamespace):
+            ez_register = self.ez_register
+            ez_register(ANamespace, label, key)
+            exhaustcall(
+                lambda x: ez_register(AService, x, label),
+                iter(key.names(True)),
+            )
         self.register([key], key, label, app)
         return app
 
         '''
         self.ez_register(self._key, label, self._lazy(call))
 
-    def update(self, labels):
+    def update(self, *appconfs):
         '''
-        update event with other registries
+        update registry with appconfs
 
-        @param labels: eventconf
+        @param *appconfs: sequence of appconfs
         '''
-        exhaustmap(vars(labels), self.pack, lambda x: not x[0].startswith('_'))
+        def process(k, appconf):
+            
+            for k, v in items((twoq(getmro(appconf))
+                .tap(lambda x: not x.startswith('__'))
+                .alt(isclass).wrap(dict).extract().value())):
+                if isinstance(v, (tuple, strings)):
+                    self.pack(k, v)
+                elif isinstance(v, dict):
+                    process(k, v)
+        exhaustcall(
+            lambda x: process(selfname(x), x), chain.from_iterable(appconfs),
+        )    
 
 
 class ManagerMixin(object):
 
         @param label: service label
         '''
-        service = self.lookup1(KService, KService, label)
+        service = self.lookup1(AService, AService, label)
         if service is None:
             raise ConfigurationError(label)
         return service

File appspace/support.py

+# -*- coding: utf-8 -*-
+'''appspace imports'''
+
+# pylint: disable-msg=f0401
+from zope.interface import implementer, implementedBy
+from zope.interface.adapter import AdapterRegistry, VerifyingAdapterRegistry
+# pylint: enable-msg=f0401
+
+keys = implementedBy
+AppStore = AdapterRegistry
+StrictAppStore = VerifyingAdapterRegistry
+appifies = implementer
+
+
+class ConfigurationError(Exception):
+
+    '''appspace configuration exception'''
+
+
+class NoAppspaceError(Exception):
+
+    '''no appspace found error'''
+
+
+class NoAppError(Exception):
+
+    '''mo application found exception'''

File appspace/utils.py

+from inspect import isclass
+
+from functools import partial
+from itertools import starmap
+from keyword import iskeyword
+from importlib import import_module
+
+from twoq import twoq
+from stuf import stuf
+from stuf.six import items, strings
+from stuf.utils import getcls, selfname, exhaust, exhaustmap, twoway, imap
+
+from appspace.imps import appifies
+from appspace.registry import Manager, StrictManager
+from appspace.keys import ABranch, ANamespace, AApp, AService
+
+
+class key(appifies):
+
+    '''appifier'''
+
+    def __init__(self, key, **metadata):
+        exhaustmap(metadata, key.setTaggedValue)
+        appifies.__init__(self, key)
+
+
+class _Filter(object):
+
+    @classmethod
+    def _filter(self, x):
+        return not x[0].startswith('_')
+
+
+class Patterns(_Filter):
+
+    '''patterns for manager configured by class'''
+
+    key = AApp
+    strict = False
+
+    @twoway
+    def _manager(self):
+        '''manager class'''
+        return StrictManager if self.strict else Manager
+
+    @classmethod
+    def build(cls):
+        '''build manager configuration from class'''
+        l = selfname(cls)
+        # set key
+        key = cls.key
+        if isinstance(key, strings):
+            # load key if string
+            key = lazyimport(key)
+        manager = cls._manager(l, key)  # pylint: disable-msg=e1121
+        b = partial(manager.keyed, ABranch)
+        m, n = manager.set, partial(manager.keyed, ANamespace)
+        t = lambda x, y: y.build(manager) if (n(y) or b(y)) else m(y, x, l)
+        exhaustmap(vars(cls), t, cls._filter)
+        return manager
+
+    @staticmethod
+    def factory(label, manager, *args):
+        '''
+        factory for manager
+
+        @param label: label for manager
+        '''
+        # build manager
+        manager = manager(label)
+        # register things in manager
+        exhaust(starmap(lambda x, y: manager.set(y, x), iter(args)))
+        return manager
+
+    @classmethod
+    def patterns(cls, label, *args):
+        '''
+        configure appspace
+
+        @param label: name of branch appspace
+        @param *args: tuple of module paths or component inclusions
+        '''
+        return cls.factory(label, cls._manager, *args)
+    
+class _PatternsMixin(object):
+
+    @classmethod
+    def _key(cls, label, manager):
+        try:
+            # lazily load key
+            key = cls.key
+            if isinstance(key, strings):
+                key = lazyimport(key)
+            # register class key
+
+        except AttributeError:
+            key = manager.key(ANamespace, label)
+
+    
+class _PatternMixin(_Filter):
+
+    @classmethod
+    def _key(cls, label, manager):
+        try:
+            # lazily load key
+            key = cls.key
+            if isinstance(key, strings):
+                key = lazyimport(key)
+            # register class key
+            manager.ez_register(ANamespace, label, key)
+        except AttributeError:
+            key = manager.key(ANamespace, label)
+
+
+@appifies(ANamespace)
+class Branch(_PatternMixin):
+
+    '''branch configuration'''
+
+    @classmethod
+    def build(cls, manager):
+        '''gather branch configuration'''
+        cls._key(selfname(cls), manager)
+        i, m = cls.include, manager.set
+        t = lambda x: not x[0].startswith('_') or isinstance(x[1], strings)
+        exhaustmap(vars(cls), lambda x, y: m(i(y), x), t)
+
+    @staticmethod
+    def include(module):
+        '''
+        configure branch appspace
+
+        @param module: module import path
+        '''
+        return ('include', module)
+    
+    
+@appifies(ANamespace)
+class Namespace(_PatternMixin):
+
+    '''configuration namespace'''
+
+    @classmethod
+    def build(cls, manager):
+        '''gather namespace configuration'''
+        label = selfname(cls)
+        cls._key(label, manager)
+        m, n = manager.set, partial(manager.keyed, ANamespace)
+        t = lambda k, v: v.build(manager) if n(v) else m(v, k, label)
+        exhaustmap(vars(cls), t, cls._filter)
+
+def localize(self, thing, *args, **kw):
+    '''
+    local settings from thing and its base classes plus any custom settings
+
+    @param thing: some thing with local settings
+    '''
+    return (twoq([type.mro(getcls(thing)), [thing]]).smash().pick('Meta')
+    .tap(lambda x: not x[0].startswith('__')).members()
+    .reup().wrap(stuf).map().invoke('update', *args, **kw).value())
+
+
+def lazyimport(path, attribute=None):
+    '''
+    deferred module loader
+
+    @param path: something to load
+    @param attribute: attribute on loaded module to return
+    '''
+    if isinstance(path, strings):
+        try:
+            dot = path.rindex('.')
+            # import module
+            path = getattr(import_module(path[:dot]), path[dot + 1:])
+        # If nothing but module name, import the module
+        except (AttributeError, ValueError):
+            path = import_module(path)
+        if attribute:
+            path = getattr(path, attribute)
+    return path
+
+
+class CheckName(object):
+
+    '''ensures string is legal Python name'''
+
+    # Illegal characters for Python names
+    ic = '()[]{}@,:`=;+*/%&|^><\'"#\\$?!~'
+
+    def __call__(self, name):
+        '''
+        ensures string is legal python name
+
+        @param name: name to check
+        '''
+        # Remove characters that are illegal in a Python name
+        name = name.strip().lower().replace('-', '_').replace(
+            '.', '_'
+        ).replace(' ', '_')
+        name = ''.join(i for i in name if i not in self.ic)
+        # Add _ if value is a Python keyword
+        return name + '_' if iskeyword(name) else name
+
+
+checkname = CheckName()

File requirements.txt

 zope.interface>=3.8.0
-stuf>=0.8.12
+twoq>=0.4.12