Commits

Lynn Rees committed eaa563f

- consolidate

Comments (0)

Files changed (58)

callchain/active_auto/chain.py

-# -*- coding: utf-8 -*-
-'''active auto-balancing chains appconf'''
-
-from appspace import appifies
-from twoq.active import AutoResultMixin
-
-from callchain.route import Chains
-from callchain.root import RootMixin
-from callchain.config import Defaults
-from callchain.mixins import ChainMixin, PriorityMixin
-from callchain.keys.core import KRootResults, KRootThings
-
-
-###############################################################################
-## thing chain ################################################################
-###############################################################################
-
-
-class thingchain:
-    dumps = 'callchain.services.dumps.Dumps'
-    loads = 'callchain.services.loads.Loads'
-    logger = 'callchain.services.core.loglet'
-
-
-thingchain = Chains(thingchain, Defaults)
-
-
-@appifies(KRootThings)
-@thingchain
-class callchain(RootMixin, ChainMixin, AutoResultMixin):
-
-    '''active queued auto-balancing lite call chain'''
-
-
-@appifies(KRootThings)
-@thingchain
-class prioritychain(RootMixin, PriorityMixin, AutoResultMixin):
-
-    '''active priority queued auto-balancing lite call chain'''
-
-
-###############################################################################
-## result chain ###############################################################
-###############################################################################
-
-
-class chain:
-    collect = 'callchain.active_auto.chainlet.collectchain'
-    combine = 'callchain.active_auto.chainlet.combinechain'
-    delay = 'callchain.active_auto.chainlet.delaychain'
-    dumps = 'callchain.services.dumps.Dumps'
-    filter = 'callchain.active_auto.chainlet.filterchain'
-    loads = 'callchain.services.loads.Loads'
-    logger = 'callchain.services.core.loglet'
-    map = 'callchain.active_auto.chainlet.mapchain'
-    math = 'callchain.active_auto.chainlet.mathchain'
-    order = 'callchain.active_auto.chainlet.orderchain'
-    random = 'callchain.active_auto.chainlet.randomchain'
-    reduce = 'callchain.active_auto.chainlet.reducechain'
-    repeat = 'callchain.active_auto.chainlet.repeatchain'
-    set = 'callchain.active_auto.chainlet.setchain'
-    slice = 'callchain.active_auto.chainlet.slicechain'
-    truth = 'callchain.active_auto.chainlet.truthchain'
-
-chain = Chains(chain, Defaults)
-
-
-@appifies(KRootResults)
-@chain
-class chainq(RootMixin, ChainMixin, AutoResultMixin):
-
-    '''active queued auto-balancing call chain'''
-
-
-@appifies(KRootResults)
-@chain
-class priorityq(RootMixin, PriorityMixin, AutoResultMixin):
-
-    '''active priority queued auto-balancing lite call chain'''

callchain/active_auto/chainlet.py

 '''active auto-balancing chainlets'''
 
 from appspace import appifies
-from twoq.active import AutoQMixin, AutoResultMixin
+from twoq.active import AutoQMixin
 from twoq.mapping import DelayMixin, RepeatMixin, MapMixin
 from twoq.reducing import MathMixin, TruthMixin, ReduceMixin
 from twoq.ordering import RandomMixin, OrderMixin, CombineMixin
 from twoq.filtering import FilterMixin, CollectMixin, SetMixin, SliceMixin
 
-from callchain.keys.core import KLinked
-from callchain.keys.map import KDelay, KRepeat, KMap
-from callchain.mixins import ChainMixin, PriorityMixin
-from callchain.keys.reduce import KMath, KReduce, KTruth
-from callchain.keys.order import KRandom, KOrder, KCombine
-from callchain.branch import (
-    BranchMixin, BranchletMixin, ChainletMixin, LinkedMixin)
-from callchain.keys.filter import KCollect, KSet, KSlice, KFilter
+from callchain.chainlet import qkeys
+from callchain.chainlet.base import Chainlet
 
 
-class chainlet(ChainletMixin, BranchMixin, BranchletMixin, AutoQMixin):
+class chainlet(Chainlet, AutoQMixin):
 
-    '''chainlet mixin'''
+    '''chainlet'''
 
 
-@appifies(KDelay)
-class delaychain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    DelayMixin,
-):
+@appifies(qkeys.KDelay)
+class delaylet(Chainlet, AutoQMixin, DelayMixin):
 
     '''delayed mapping chainlet'''
 
 
-@appifies(KRepeat)
-class repeatchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    RepeatMixin,
-):
+@appifies(qkeys.KRepeat)
+class repeatlet(Chainlet, AutoQMixin, RepeatMixin):
 
     '''repeat chainlet'''
 
 
-@appifies(KMap)
-class mapchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    MapMixin,
-):
+@appifies(qkeys.KMap)
+class maplet(Chainlet, AutoQMixin, MapMixin):
 
     '''mapping chainlet'''
 
 
-@appifies(KCollect)
-class collectchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    CollectMixin,
-):
+@appifies(qkeys.KCollect)
+class collectlet(Chainlet, AutoQMixin, CollectMixin):
 
     '''collecting chainlet'''
 
 
-@appifies(KSet)
-class setchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    SetMixin,
-):
+@appifies(qkeys.KSet)
+class setlet(Chainlet, AutoQMixin, SetMixin):
 
     '''seting chainlet'''
 
 
-@appifies(KSlice)
-class slicechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    SliceMixin,
-):
+@appifies(qkeys.KSlice)
+class slicelet(Chainlet, AutoQMixin, SliceMixin):
 
     '''slicing chainlet'''
 
 
-@appifies(KFilter)
-class filterchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    FilterMixin,
-):
+@appifies(qkeys.KFilter)
+class filterlet(Chainlet, AutoQMixin, FilterMixin):
 
     '''filtering chainlet'''
 
 
-@appifies(KRandom)
-class randomchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    RandomMixin,
-):
+@appifies(qkeys.KRandom)
+class randomlet(Chainlet, AutoQMixin, RandomMixin):
 
     '''randomizing chainlet'''
 
 
-@appifies(KOrder)
-class orderchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    OrderMixin,
-):
+@appifies(qkeys.KOrder)
+class orderlet(Chainlet, AutoQMixin, OrderMixin):
 
     '''ordering chainlet'''
 
 
-@appifies(KMath)
-class mathchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    MathMixin,
-):
+@appifies(qkeys.KMath)
+class mathlet(Chainlet, AutoQMixin, MathMixin):
 
     '''mathing chainlet'''
 
 
-@appifies(KReduce)
-class reducechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    ReduceMixin,
-):
+@appifies(qkeys.KReduce)
+class reducelet(Chainlet, AutoQMixin, ReduceMixin):
 
     '''reducing chainlet'''
 
 
-@appifies(KCombine)
-class combinechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    CombineMixin,
-):
+@appifies(qkeys.KCombine)
+class combinelet(Chainlet, AutoQMixin, CombineMixin):
 
     '''combining chainlet'''
 
 
-@appifies(KTruth)
-class truthchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    AutoQMixin,
-    TruthMixin,
-):
+@appifies(qkeys.KTruth)
+class truthlet(Chainlet, AutoQMixin, TruthMixin):
 
     '''truthing chainlet'''
-
-
-@appifies(KLinked)
-class chainlink(BranchMixin, LinkedMixin, ChainMixin, AutoResultMixin):
-
-    '''linked chain'''
-
-
-@appifies(KLinked)
-class prioritylink(BranchMixin, LinkedMixin, PriorityMixin, AutoResultMixin):
-
-    '''priority linked chain'''

callchain/active_auto/event.py

-# -*- coding: utf-8 -*-
-'''active auto-balancing event chains appconf'''
-
-from appspace import appifies
-from twoq.active import AutoResultMixin
-
-from callchain.config import Defaults
-from callchain.keys.apps import events
-from callchain.root import EventRootMixin
-from callchain.mixins import EventMixin
-from callchain.route import Chains, Events
-from callchain.keys.mixin import KEvent
-
-###############################################################################
-## thing event chain ##########################################################
-###############################################################################
-
-
-class thingevent:
-    chain = 'callchain.active_auto.chainlet.chainlink'
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-
-
-thingevent = Events(thingevent, events, Defaults)
-
-
-@appifies(KEvent)
-@thingevent(thingevent, events, defaults=Defaults)
-class eventchain(EventRootMixin, EventMixin, AutoResultMixin):
-
-    '''active queued auto-balancing lite event chain'''
-
-
-###############################################################################
-## result event chain #########################################################
-###############################################################################
-
-
-class event(Chains, Defaults):
-    chain = 'callchain.active_auto.chainlet.chainlink'
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-    filter = 'callchain.active_auto.eventlet.filterevent'
-    collect = 'callchain.active_auto.eventlet.collectevent'
-    combine = 'callchain.active_auto.eventlet.combineevent'
-    set = 'callchain.active_auto.eventlet.setevent'
-    slice = 'callchain.active_auto.eventlet.sliceevent'
-    map = 'callchain.active_auto.eventlet.mapevent'
-    delay = 'callchain.active_auto.eventlet.delayevent'
-    repeat = 'callchain.active_auto.eventlet.repeatevent'
-    order = 'callchain.active_auto.eventlet.orderevent'
-    random = 'callchain.active_auto.eventlet.randomevent'
-    reduce = 'callchain.active_auto.eventlet.reduceevent'
-    math = 'callchain.active_auto.eventlet.mathevent'
-    truth = 'callchain.active_auto.eventlet.truthevent'
-
-
-event = Events(event, events, Defaults)
-
-
-@appifies(KEvent)
-@event(event, events, defaults=Defaults)
-class eventq(EventRootMixin, EventMixin, AutoResultMixin):
-
-    '''active queued auto-balancing event chain'''

callchain/active_auto/eventlet.py

 '''active auto-balancing eventlets'''
 
 from appspace import appifies
-from twoq.active import AutoQMixin, AutoResultMixin
+from twoq.active import AutoQMixin
 from twoq.mapping import DelayMixin, RepeatMixin, MapMixin
 from twoq.reducing import MathMixin, TruthMixin, ReduceMixin
 from twoq.ordering import RandomMixin, OrderMixin, CombineMixin
 from twoq.filtering import FilterMixin, CollectMixin, SetMixin, SliceMixin
 
-from callchain.call import EventMixin
-from callchain.keys.core import KResult
-from callchain.keys.map import KDelay, KRepeat, KMap
-from callchain.keys.reduce import KMath, KReduce, KTruth
-from callchain.keys.order import KRandom, KOrder, KCombine
-from callchain.chain import (
-    ChainletMixin, EventBranchMixin, BranchletMixin, LinkedMixin)
-from callchain.keys.filter import KCollect, KSet, KSlice, KFilter
-from callchain.keys.base import KEventCall, KEvent, KLinked, KConfig
+from callchain.chainlet import qkeys
+from callchain.chainlet.base import Eventlet
 
 
-class eventlet(ChainletMixin, EventBranchMixin, BranchletMixin, AutoQMixin):
+class eventlet(Eventlet, AutoQMixin):
 
-    '''eventlet mixin'''
+    '''eventlet'''
 
 
-@appifies(KDelay)
-class delayevent(eventlet, DelayMixin):
+@appifies(qkeys.KDelay)
+class delaylet(Eventlet, AutoQMixin, DelayMixin):
 
     '''delayed mapping eventlet'''
 
 
-@appifies(KRepeat)
-class repeatevent(eventlet, RepeatMixin):
+@appifies(qkeys.KRepeat)
+class repeatlet(Eventlet, AutoQMixin, RepeatMixin):
 
     '''repeat eventlet'''
 
 
-@appifies(KMap)
-class mapevent(eventlet, MapMixin):
+@appifies(qkeys.KMap)
+class maplet(Eventlet, AutoQMixin, MapMixin):
 
     '''mapping eventlet'''
 
 
-@appifies(KCollect)
-class collectevent(eventlet, CollectMixin):
+@appifies(qkeys.KCollect)
+class collectlet(Eventlet, AutoQMixin, CollectMixin):
 
     '''collecting eventlet'''
 
 
-@appifies(KSet)
-class setevent(eventlet, SetMixin):
+@appifies(qkeys.KSet)
+class setlet(Eventlet, AutoQMixin, SetMixin):
 
     '''seting eventlet'''
 
 
-@appifies(KSlice)
-class sliceevent(eventlet, SliceMixin):
+@appifies(qkeys.KSlice)
+class slicelet(Eventlet, AutoQMixin, SliceMixin):
 
     '''slicing eventlet'''
 
 
-@appifies(KFilter)
-class filterevent(eventlet, FilterMixin):
+@appifies(qkeys.KFilter)
+class filterlet(Eventlet, AutoQMixin, FilterMixin):
 
     '''filtering eventlet'''
 
 
-@appifies(KRandom)
-class randomevent(eventlet, RandomMixin):
+@appifies(qkeys.KRandom)
+class randomlet(Eventlet, AutoQMixin, RandomMixin):
 
     '''randomizing eventlet'''
 
 
-@appifies(KOrder)
-class orderevent(eventlet, OrderMixin):
+@appifies(qkeys.KOrder)
+class orderlet(Eventlet, AutoQMixin, OrderMixin):
 
     '''ordering eventlet'''
 
 
-@appifies(KMath)
-class mathevent(eventlet, MathMixin):
+@appifies(qkeys.KMath)
+class mathlet(Eventlet, AutoQMixin, MathMixin):
 
     '''mathing eventlet'''
 
 
-@appifies(KReduce)
-class reduceevent(eventlet, ReduceMixin):
+@appifies(qkeys.KReduce)
+class reducelet(Eventlet, AutoQMixin, ReduceMixin):
 
     '''reducing eventlet'''
 
 
-@appifies(KCombine)
-class combineevent(eventlet, CombineMixin):
+@appifies(qkeys.KCombine)
+class combinelet(Eventlet, AutoQMixin, CombineMixin):
 
     '''combining eventlet'''
 
 
-@appifies(KTruth)
-class truthevent(eventlet, TruthMixin):
+@appifies(qkeys.KTruth)
+class truthlet(Eventlet, AutoQMixin, TruthMixin):
 
     '''truthing eventlet'''
-
-
-@appifies(KLinked, KConfig, KEventCall, KEvent, KResult)
-class eventlink(EventBranchMixin, LinkedMixin, EventMixin, AutoResultMixin):
-
-    '''lite linked event chain'''

callchain/active_man/chain.py

-# -*- coding: utf-8 -*-
-'''active manually balanced chains appconf'''
-
-from appspace import appifies
-from twoq.active import ManResultMixin
-
-from callchain.chain import RootMixin
-from callchain.config import Defaults
-from callchain.patterns import Chains, Nameways
-from callchain.keys.core import KThings, KResult
-from callchain.keys.base import KRoot, KCall, KChain
-from callchain.call import ChainMixin, PriorityMixin, internal
-
-###############################################################################
-## thing chain ################################################################
-###############################################################################
-
-
-class thingchain(Chains):
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-
-
-@appifies(KThings, KRoot, KChain, KCall)
-@internal(thingchain, defaults=Defaults)
-class callchain(RootMixin, ChainMixin, ManResultMixin):
-
-    ''''active queued manually balanced lite call chain'''
-
-
-@appifies(KThings, KRoot, KChain, KCall)
-@internal(thingchain, defaults=Defaults)
-class prioritychain(RootMixin, PriorityMixin, ManResultMixin):
-
-    '''active priority queued manually balanced lite call chain'''
-
-
-###############################################################################
-## result chain ###############################################################
-###############################################################################
-
-
-class chain(Chains):
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-    filter = 'callchain.active_man.chainlet.filterchain'
-    collect = 'callchain.active_man.chainlet.collectchain'
-    set = 'callchain.active_man.chainlet.setchain'
-    slice = 'callchain.active_man.chainlet.slicechain'
-    combine = 'callchain.active_man.chainlet.combinechain'
-    map = 'callchain.active_man.chainlet.mapchain'
-    delay = 'callchain.active_man.chainlet.delaychain'
-    repeat = 'callchain.active_man.chainlet.repeatchain'
-    order = 'callchain.active_man.chainlet.orderchain'
-    random = 'callchain.active_man.chainlet.randomchain'
-    reduce = 'callchain.active_man.chainlet.reducechain'
-    math = 'callchain.active_man.chainlet.mathchain'
-    truth = 'callchain.active_man.chainlet.truthchain'
-
-
-@appifies(KResult, KRoot, KChain, KCall)
-@internal(chain, defaults=Defaults)
-class chainq(RootMixin, ChainMixin, ManResultMixin):
-
-    '''active queued manually balanced call chain'''
-
-
-@appifies(KThings, KRoot, KChain, KCall)
-@internal(chain, defaults=Defaults)
-class priorityq(RootMixin, PriorityMixin, ManResultMixin):
-
-    '''active priority queued manually balanced lite call chain'''

callchain/active_man/chainlet.py

 '''active manually balanced chainlets'''
 
 from appspace import appifies
-from twoq.active import ManQMixin, ManResultMixin
+from twoq.active import ManQMixin
 from twoq.mapping import DelayMixin, RepeatMixin, MapMixin
 from twoq.reducing import MathMixin, TruthMixin, ReduceMixin
 from twoq.ordering import RandomMixin, OrderMixin, CombineMixin
 from twoq.filtering import FilterMixin, CollectMixin, SetMixin, SliceMixin
 
-from callchain.keys.core import KResult
-from callchain.call import ChainMixin, PriorityMixin
-from callchain.keys.map import KDelay, KRepeat, KMap
-from callchain.keys.reduce import KMath, KReduce, KTruth
-from callchain.chain import (
-    BranchMixin, BranchletMixin, ChainletMixin, LinkedMixin)
-from callchain.keys.order import KRandom, KOrder, KCombine
-from callchain.keys.base import KCall, KChain, KConfig, KLinked
-from callchain.keys.filter import KCollect, KSet, KSlice, KFilter
+from callchain.chainlet import qkeys
+from callchain.chainlet.base import Chainlet
 
 
-class chainlet(ChainletMixin, BranchMixin, BranchletMixin, ManQMixin):
+class chainlet(Chainlet, ManQMixin):
 
-    '''chainlet mixin'''
+    '''chainlet'''
 
 
-@appifies(KDelay)
-class delaychain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    DelayMixin,
-):
+@appifies(qkeys.KDelay)
+class delaylet(Chainlet, ManQMixin, DelayMixin):
 
     '''delayed mapping chainlet'''
 
 
-@appifies(KRepeat)
-class repeatchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    RepeatMixin,
-):
+@appifies(qkeys.KRepeat)
+class repeatlet(Chainlet, ManQMixin, RepeatMixin):
 
     '''repeat chainlet'''
 
 
-@appifies(KMap)
-class mapchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    MapMixin,
-):
+@appifies(qkeys.KMap)
+class maplet(Chainlet, ManQMixin, MapMixin):
 
     '''mapping chainlet'''
 
 
-@appifies(KCollect)
-class collectchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    CollectMixin,
-):
+@appifies(qkeys.KCollect)
+class collectlet(Chainlet, ManQMixin, CollectMixin):
 
     '''collecting chainlet'''
 
 
-@appifies(KSet)
-class setchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    SetMixin,
-):
+@appifies(qkeys.KSet)
+class setlet(Chainlet, ManQMixin, SetMixin):
 
     '''seting chainlet'''
 
 
-@appifies(KSlice)
-class slicechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    SliceMixin,
-):
+@appifies(qkeys.KSlice)
+class slicelet(Chainlet, ManQMixin, SliceMixin):
 
     '''slicing chainlet'''
 
 
-@appifies(KFilter)
-class filterchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    FilterMixin,
-):
+@appifies(qkeys.KFilter)
+class filterlet(Chainlet, ManQMixin, FilterMixin):
 
     '''filtering chainlet'''
 
 
-@appifies(KRandom)
-class randomchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    RandomMixin,
-):
+@appifies(qkeys.KRandom)
+class randomlet(Chainlet, ManQMixin, RandomMixin):
 
     '''randomizing chainlet'''
 
 
-@appifies(KOrder)
-class orderchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    OrderMixin,
-):
+@appifies(qkeys.KOrder)
+class orderlet(Chainlet, ManQMixin, OrderMixin):
 
     '''ordering chainlet'''
 
 
-@appifies(KMath)
-class mathchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    MathMixin,
-):
+@appifies(qkeys.KMath)
+class mathlet(Chainlet, ManQMixin, MathMixin):
 
     '''mathing chainlet'''
 
 
-@appifies(KReduce)
-class reducechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    ReduceMixin,
-):
+@appifies(qkeys.KReduce)
+class reducelet(Chainlet, ManQMixin, ReduceMixin):
 
     '''reducing chainlet'''
 
 
-@appifies(KCombine)
-class combinechain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    CombineMixin,
-):
+@appifies(qkeys.KCombine)
+class combinelet(Chainlet, ManQMixin, CombineMixin):
 
     '''combining chainlet'''
 
 
-@appifies(KTruth)
-class truthchain(
-    ChainletMixin,
-    BranchMixin,
-    BranchletMixin,
-    ManQMixin,
-    TruthMixin,
-):
+@appifies(qkeys.KTruth)
+class truthlet(Chainlet, ManQMixin, TruthMixin):
 
     '''truthing chainlet'''
-
-
-@appifies(KLinked, KConfig, KCall, KChain, KResult)
-class chainlink(BranchMixin, LinkedMixin, ChainMixin, ManResultMixin):
-
-    '''linked chain'''
-
-
-@appifies(KLinked, KConfig, KCall, KChain, KResult)
-class prioritylink(BranchMixin, LinkedMixin, PriorityMixin, ManResultMixin):
-
-    '''priority linked chain'''

callchain/active_man/event.py

-# -*- coding: utf-8 -*-
-'''active manually balanced event chains appconf'''
-
-from appspace import appifies
-from twoq.active import ManResultMixin
-
-from callchain.config import Defaults
-from callchain.keys.apps import events
-from callchain.chain import EventRootMixin
-from callchain.call import EventMixin, internal_events
-from callchain.keys.core import KThings, KResult
-from callchain.patterns import Chains
-from callchain.keys.base import KEvent, KEventRoot, KEventCall
-
-###############################################################################
-## thing event chain ##########################################################
-###############################################################################
-
-
-class thingevent(Chains):
-    chain = 'callchain.active_man.chainlet.chainlink'
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-
-
-@appifies(KThings, KEventRoot, KEvent, KEventCall)
-@internal_events(thingevent, events, defaults=Defaults)
-class eventchain(EventRootMixin, EventMixin, ManResultMixin):
-
-    '''active queued manually balanced lite event chain'''
-
-
-###############################################################################
-## result event chain #########################################################
-###############################################################################
-
-
-class event(Chains):
-    chain = 'callchain.active_man.chainlet.chainlink'
-    loads = 'callchain.services.loads.Loads'
-    dumps = 'callchain.services.dumps.Dumps'
-    logger = 'callchain.services.core.loglet'
-    filter = 'callchain.active_man.eventlet.filterevent'
-    collect = 'callchain.active_man.eventlet.collectevent'
-    combine = 'callchain.active_man.eventlet.combineevent'
-    set = 'callchain.active_man.eventlet.setevent'
-    slice = 'callchain.active_man.eventlet.sliceevent'
-    map = 'callchain.active_man.eventlet.mapevent'
-    delay = 'callchain.active_man.eventlet.delayevent'
-    repeat = 'callchain.active_man.eventlet.repeatevent'
-    order = 'callchain.active_man.eventlet.orderevent'
-    random = 'callchain.active_man.eventlet.randomevent'
-    reduce = 'callchain.active_man.eventlet.reduceevent'
-    math = 'callchain.active_man.eventlet.mathevent'
-    truth = 'callchain.active_man.eventlet.truthevent'
-
-
-@appifies(KResult, KEventRoot, KEvent, KEventCall)
-@internal_events(event, events, defaults=Defaults)
-class eventq(EventRootMixin, EventMixin, ManResultMixin):
-
-    '''active queued manually balanced event chain'''

callchain/active_man/eventlet.py

 '''active manually balanced eventlets'''
 
 from appspace import appifies
-from twoq.active import ManQMixin, ManResultMixin
+from twoq.active import ManQMixin
 from twoq.mapping import DelayMixin, RepeatMixin, MapMixin
 from twoq.reducing import MathMixin, TruthMixin, ReduceMixin
 from twoq.ordering import RandomMixin, OrderMixin, CombineMixin
 from twoq.filtering import FilterMixin, CollectMixin, SetMixin, SliceMixin
 
-from callchain.call import EventMixin
-from callchain.keys.core import KResult
-from callchain.keys.map import KDelay, KRepeat, KMap
-from callchain.keys.reduce import KMath, KReduce, KTruth
-from callchain.keys.order import KRandom, KOrder, KCombine
-from callchain.chain import (
-    ChainletMixin, EventBranchMixin, BranchletMixin, LinkedMixin)
-from callchain.keys.filter import KCollect, KSet, KSlice, KFilter
-from callchain.keys.base import KEventCall, KEvent, KLinked, KConfig
+from callchain.chainlet import qkeys
+from callchain.chainlet.base import Eventlet
 
 
-class eventlet(ChainletMixin, EventBranchMixin, BranchletMixin, ManQMixin):
+class eventlet(Eventlet, ManQMixin):
 
-    '''eventlet mixin'''
+    '''eventlet'''
 
 
-@appifies(KDelay)
-class delayevent(eventlet, DelayMixin):
+@appifies(qkeys.KDelay)
+class delaylet(Eventlet, ManQMixin, DelayMixin):
 
     '''delayed mapping eventlet'''
 
 
-@appifies(KRepeat)
-class repeatevent(eventlet, RepeatMixin):
+@appifies(qkeys.KRepeat)
+class repeatlet(Eventlet, ManQMixin, RepeatMixin):
 
     '''repeat eventlet'''
 
 
-@appifies(KMap)
-class mapevent(eventlet, MapMixin):
+@appifies(qkeys.KMap)
+class maplet(Eventlet, ManQMixin, MapMixin):
 
     '''mapping eventlet'''
 
 
-@appifies(KCollect)
-class collectevent(eventlet, CollectMixin):
+@appifies(qkeys.KCollect)
+class collectlet(Eventlet, ManQMixin, CollectMixin):
 
     '''collecting eventlet'''
 
 
-@appifies(KSet)
-class setevent(eventlet, SetMixin):
+@appifies(qkeys.KSet)
+class setlet(Eventlet, ManQMixin, SetMixin):
 
     '''seting eventlet'''
 
 
-@appifies(KSlice)
-class sliceevent(eventlet, SliceMixin):
+@appifies(qkeys.KSlice)
+class slicelet(Eventlet, ManQMixin, SliceMixin):
 
     '''slicing eventlet'''
 
 
-@appifies(KFilter)
-class filterevent(eventlet, FilterMixin):
+@appifies(qkeys.KFilter)
+class filterlet(Eventlet, ManQMixin, FilterMixin):
 
     '''filtering eventlet'''
 
 
-@appifies(KRandom)
-class randomevent(eventlet, RandomMixin):
+@appifies(qkeys.KRandom)
+class randomlet(Eventlet, ManQMixin, RandomMixin):
 
     '''randomizing eventlet'''
 
 
-@appifies(KOrder)
-class orderevent(eventlet, OrderMixin):
+@appifies(qkeys.KOrder)
+class orderlet(Eventlet, ManQMixin, OrderMixin):
 
     '''ordering eventlet'''
 
 
-@appifies(KMath)
-class mathevent(eventlet, MathMixin):
+@appifies(qkeys.KMath)
+class mathlet(Eventlet, ManQMixin, MathMixin):
 
     '''mathing eventlet'''
 
 
-@appifies(KReduce)
-class reduceevent(eventlet, ReduceMixin):
+@appifies(qkeys.KReduce)
+class reducelet(Eventlet, ManQMixin, ReduceMixin):
 
     '''reducing eventlet'''
 
 
-@appifies(KCombine)
-class combineevent(eventlet, CombineMixin):
+@appifies(qkeys.KCombine)
+class combinelet(Eventlet, ManQMixin, CombineMixin):
 
     '''combining eventlet'''
 
 
-@appifies(KTruth)
-class truthevent(eventlet, TruthMixin):
+@appifies(qkeys.KTruth)
+class truthlet(Eventlet, ManQMixin, TruthMixin):
 
     '''truthing eventlet'''
-
-
-@appifies(KLinked, KConfig, KEventCall, KEvent, KResult)
-class eventlink(EventBranchMixin, LinkedMixin, EventMixin, ManResultMixin):
-
-    '''lite linked event chain'''

callchain/apps.py

-# -*- coding: utf-8 -*-
-'''callchain appconf'''
-
-
-class lookups:
-    _choice = 'random.choice'
-    _clsname = 'stuf.utils.clsname'
-    _contains = 'operator.contains'
-    _counter = 'twoq.support.Counter'
-    _deek = 'collections.deque'
-    _filterfalse = 'twoq.support.filterfalse'
-    _fsum = 'math.fsum'
-    _groupby = 'itertools.groupby'
-    _ichain = 'itertools.chain.from_iterable'
-    _ifilter = 'twoq.support.ifilter'
-    _imap = 'twoq.support.imap'
-    _ireduce = 'functools.reduce'
-    _islice = 'itertools.islice'
-    _items = 'twoq.support.items'
-    _iterz = 'builtins.iter'
-    _join = 'itertools.chain'
-    _len = 'builtins.len'
-    _list = 'builtins.list'
-    _max = 'builtins.max'
-    _methodcaller = 'operator.methodcaller'
-    _min = 'builtins.min'
-    _next = 'builtins.next'
-    _partial = 'functools.partial'
-    _range = 'support.range'
-    _repeat = 'itertools.repeat'
-    _reversed = 'builtins.reversed'
-    _sample = 'random.sample'
-    _shuffle = 'random/shuffle'
-    _sleep = 'time.sleep'
-    _sorted = 'builtins.sorted'
-    _split = 'itertools.tee'
-    _starmap = 'itertools.starmap'
-    _sum = 'builtins.sum'
-    _truediv = 'operator.truediv'
-    _zip = 'six.moves.zip'
-
-
-class chaincore:
-    _settings = 'callchain.settings.Settings'
-    _queue = 'twoq.twoq'
-    _porting = 'twoq.port'
-    _E = 'callchain.chainlets.registry.EventRegistry'

callchain/branch.py

-# -*- coding: utf-8 -*-
-'''root chain mixins'''
-
-from appspace import NoAppError
-
-from callchain.base import ResetLocalMixin, CoreMixin
-from callchain.mixins import (
-    BranchMixin, EventBranchMixin, ChainMixin, PriorityMixin, EventMixin)
-
-
-class LinkedMixin(ResetLocalMixin):
-
-    '''linked chain mixin'''
-
-    def close(self):
-        '''close out linked chain and switch to root chain'''
-        return self.root.back(self)
-
-
-class BranchletMixin(CoreMixin):
-
-    '''chainlet mixin'''
-
-    def _setup(self, root):
-        '''
-        configure chainlet
-
-        @param root: root chain
-        '''
-        super(BranchletMixin, self)._setup(root)
-        # sync with root postitional arguments
-        self._args = root._args
-        # sync with root keyword arguments
-        self._kw = root._kw
-        # sync with root callable
-        self._call = root._call
-        # sync with root incoming things and outgoing things
-        self.inclear().extend(root.incoming).outextend(root.outgoing)
-
-
-class ChainletMixin(ResetLocalMixin):
-
-    '''chainlet mixin'''
-
-    def _load(self, label):
-        '''
-        silent internal switch back...
-
-        @param label: appspaced thing label
-        '''
-        # fetch appspaced thing...
-        try:
-            return super(ChainletMixin, self)._load(label)
-        # ...or revert to root chain
-        except NoAppError:
-            return getattr(self.back(), label)
-
-    def _syncback(self, key, value):
-        '''
-        sync chainlet with root chain
-
-        @param key: key of value
-        @param value: value of value
-        '''
-        self.__dict__[key] = self.root.__dict__[key] = value
-
-    def back(self):
-        '''switch back to root chain'''
-        return self.root.back(self)
-
-
-###############################################################################
-## chainlet ###################################################################
-###############################################################################
-
-
-class chainlet(ChainletMixin, BranchMixin, CoreMixin):
-
-    '''generic chainlet mixin'''
-
-
-class eventlet(ChainletMixin, EventBranchMixin, CoreMixin):
-
-    '''generic eventlet mixin'''
-
-
-###############################################################################
-## linked chain ###############################################################
-###############################################################################
-
-
-class chainlink(BranchMixin, LinkedMixin, ChainMixin):
-
-    '''generic linked chain'''
-
-
-class prioritylink(BranchMixin, LinkedMixin, PriorityMixin):
-
-    '''generic priority linked chain'''
-
-
-class eventlink(EventBranchMixin, LinkedMixin, EventMixin):
-
-    '''generic linked event chain'''

callchain/chainlet/__init__.py

+# -*- coding: utf-8 -*-
+'''callchain service keys'''

callchain/chainlet/base.py

+# -*- coding: utf-8 -*-
+'''root chain mixins'''
+
+from appspace import NoAppError
+
+from callchain.base import ResetLocalMixin, CoreMixin
+from callchain.mixins import BranchMixin, EventBranchMixin
+
+
+class ThingletMixin(CoreMixin):
+
+    '''chainlet mixin'''
+
+    def _setup(self, root):
+        '''
+        configure chainlet
+
+        @param root: root chain
+        '''
+        super(ThingletMixin, self)._setup(root)
+        # sync with root postitional arguments
+        self._args = root._args
+        # sync with root keyword arguments
+        self._kw = root._kw
+        # sync with root callable
+        self._call = root._call
+        # sync with root incoming things and outgoing things
+        self.inclear().extend(root.incoming).outextend(root.outgoing)
+
+
+class ChainletMixin(ResetLocalMixin):
+
+    '''chainlet mixin'''
+
+    def _load(self, label):
+        '''
+        silent internal switch back...
+
+        @param label: appspaced thing label
+        '''
+        # fetch appspaced thing...
+        try:
+            return super(ChainletMixin, self)._load(label)
+        # ...or revert to root chain
+        except NoAppError:
+            return getattr(self.back(), label)
+
+    def _syncback(self, key, value):
+        '''
+        sync chainlet with root chain
+
+        @param key: key of value
+        @param value: value of value
+        '''
+        self.__dict__[key] = self.root.__dict__[key] = value
+
+    def back(self):
+        '''switch back to root chain'''
+        return self.root.back(self)
+
+
+class Chainlet(ChainletMixin, ThingletMixin, BranchMixin):
+
+    '''chainlet'''
+
+
+class Eventlet(ChainletMixin, ThingletMixin, EventBranchMixin):
+
+    '''generic eventlet mixin'''
+
+
+class chainlet(ChainletMixin, BranchMixin, CoreMixin):
+
+    '''generic chainlet mixin'''
+
+
+class eventlet(ChainletMixin, EventBranchMixin, CoreMixin):
+
+    '''generic eventlet mixin'''

callchain/chainlet/core.py

+# -*- coding: utf-8 -*-
+'''callchain chainlet core'''
+
+import sys
+import logging
+from logging.handlers import HTTPHandler, SysLogHandler
+from logging.handlers import TimedRotatingFileHandler, SMTPHandler
+
+from appspace import appifies
+from stuf.utils import clsname
+
+from callchain.chainlet.keys import KLogger
+from callchain.chainlet.base import chainlet
+
+
+class _LogStdout(object):
+
+    '''file-like object for sending stdout output to a logger.'''
+
+    def __init__(self, logger, level=logging.DEBUG):
+        '''
+        build stdout logger
+
+        @param logger: logger
+        @param level: logging level (default: `logging.DEBUG`
+        '''
+        # Set logger level
+        if level == logging.DEBUG:
+            self.logger = logger.debug
+        elif level == logging.CRITICAL:
+            self.logger = logger.critical
+        elif level == logging.ERROR:
+            self.logger = logger.error
+        elif level == logging.WARNING:
+            self.logger = logger.warning
+        elif level == logging.INFO:
+            self.logger = logger.info
+
+    def write(self, msg):
+        '''Writes non-empty strings to logger.'''
+        if msg.lstrip().rstrip() != '':
+            self.logger(msg)
+
+
+@appifies(KLogger)
+class loglet(chainlet):
+
+    '''logging chainlet'''
+
+    def _setup(self, root):
+        '''
+        build logger
+
+        @param root: root chain
+        '''
+        super(loglet, self)._setup(root)
+        settings = self._G.log
+        self.logger = logging.getLogger(settings.get('NAME', clsname(root)))
+        # set logging level
+        self.logger.setLevel(settings.LEVEL)
+        # log formatter
+        format = logging.Formatter(
+            # log entry format
+            settings.ENTRY,
+            # date format
+            settings.DATE,
+        )
+        # coroutine to setup log handlers
+        def setlog(thislog): #@IgnorePep8
+            thislog.setFormatter(format)
+            self.logger.addHandler(thislog)
+        # log to STDOUT
+        if settings.stream:
+            setlog(logging.StreamHandler())
+            # redirect STDOUT to the logger
+            if settings.stream.STDOUT:
+                # sets log level STDOUT is displayed under
+                sys.stdout = _LogStdout(self.logger, settings.stream.LEVEL)
+        # log to a rotating file that with periodic backup deletions
+        if settings.rotating.ENABLED:
+            setlog(TimedRotatingFileHandler(
+                # log file path
+                settings.rotating.PATH,
+                # interval to backup log file
+                settings.rotating.INTERVAL,
+                # number of backups to keep
+                settings.rotating.BACKUPS,
+            ))
+        # email log entries to an email address
+        if settings.email.ENABLED:
+            setlog(SMTPHandler(
+                # mail server
+                settings.email.HOST,
+                # from email address
+                settings.email.FROM,
+                # to email address
+                settings.email.TO,
+                # email subject
+                settings.email.SUBJECT,
+            ))
+        # send log entries to a web server
+        if settings.http.ENABLED:
+            setlog(HTTPHandler(
+                # web server host
+                settings.http.HOST,
+                # web url
+                settings.http.URL,
+                # http method
+                settings.http.METHOD,
+            ))
+        # send log entries to syslog
+        if settings.syslog.ENABLED:
+            setlog(SysLogHandler(
+                # syslog host
+                (settings.syslog.HOST, settings.syslog.PORT),
+                # syslog user
+                settings.syslog.FACILITY,
+            ))
+        assert self.logger.handlers, 'configure at least one logging handler'
+
+    def debug(self, msg):
+        '''log debug message'''
+        self.logger.debug(msg)
+        return self
+
+    def warning(self, msg):
+        '''log warning message'''
+        self.logger.warning(msg)
+        return self
+
+    def info(self, msg):
+        '''log info message'''
+        self.logger.info(msg)
+        return self
+
+    def error(self, msg):
+        '''log error message'''
+        self.logger.error(msg)
+        return self
+
+    def critical(self, msg):
+        '''log critical message'''
+        self.logger.critical(msg)
+        return self
+
+    def exception(self, msg):
+        '''log exception message'''
+        self.logger.exception(msg)
+        return self

callchain/chainlet/imps.py

+# -*- coding: utf-8 -*-
+'''callchain services imports'''
+
+from callchain.support import (
+    StringIO, xmlrpc, parse_qs, plist_loads, plist_dumps, xrange)
+try:
+    import yaml
+except ImportError:
+    pass
+try:
+    import simplejson as json
+except ImportError:
+    import json
+try:
+    from bencode import bdecode, bencode
+except ImportError:
+    pass
+try:
+    from lxml import etree
+except ImportError:
+    import xml.etree.ElementTree as etree
+try:
+    import msgpack
+except ImportError:
+    pass
+try:
+    import tnetstring
+except ImportError:
+    pass
+try:
+    import thrift.TSerialization as thrift
+except ImportError:
+    pass
+try:
+    import bson
+except ImportError:
+    pass
+try:
+    import jsonpickle
+except ImportError:
+    pass
+try:
+    import netstring
+except ImportError:
+    pass
+try:
+    import html
+except ImportError:
+    pass
+try:
+    from requests.packages.urllib3.filepost import encode_multipart_formdata
+except ImportError:
+    try:
+        from urllib3.filepost import encode_multipart_formdata
+    except ImportError:
+        pass
+try:
+    import xlwt
+    import xlrd
+except ImportError:
+    pass

callchain/chainlet/io.py

+# -*- coding: utf-8 -*-
+'''callchain dumpers'''
+
+import csv
+import codecs
+import marshal
+from operator import setitem
+from cgi import parse_multipart
+
+from appspace import appifies
+from stuf.utils import exhaustmap
+
+from callchain import ResetLocalMixin
+
+from callchain.chainlet import imps
+from callchain.chainlet.base import Chainlet
+from callchain.chainlet.keys import KDumps, KLoads, KIO
+
+
+class _Package(ResetLocalMixin):
+
+    '''data package'''
+
+    def __init__(self, data, mime, charset=None):
+        super(_Package, self).__init__()
+        self.data = data
+        self.mime = mime
+        self.charset = charset
+
+
+class iolet(Chainlet):
+
+    '''input/output mixin'''
+
+    def _process(self, encoder, mime, charset=None):
+        with self._context():
+            self._xtend(self._map(
+                lambda x: _Package(encoder(x), mime, charset), self._iterable,
+            ))
+        return self
+
+
+@appifies(KIO)
+class filet(Chainlet):
+
+    '''file input/output chainlet'''
+
+    def read(self, mode='rb', encoding=None, errors='strict', *paths):
+        '''
+        read incoming things from files
+
+        @param mode: mode to open files (default: 'r')
+        @param encoding: encoding for text data (default: `None`)
+        @param errors: error handling in encoding text data (default: 'strict')
+        @param *paths: sequence of filesystem paths
+        '''
+        with self._context:
+            append = self._append
+            for path in paths:
+                with codecs.open(path, mode, encoding) as f:
+                    append(f.read())
+        return self
+
+    def write(self, mode='rb', encoding=None, errors='strict', *paths):
+        '''
+        write outgoing things to files
+
+        @param mode: mode to open files (default: 'r')
+        @param encoding: encoding for text data (default: `None`)
+        @param errors: error handling in encoding text data (default: 'strict')
+        @param *paths: sequence of filesystem paths
+        '''
+        values = self.value()
+        for idx, path in enumerate(paths):
+            with codecs.open(path, mode, encoding) as f:
+                f.write(values[idx])
+        return self
+
+
+@appifies(KDumps)
+class Dumps(iolet):
+
+    '''dumper'''
+
+    def bencode(self):
+        '''
+        bencode dumper
+
+        http://en.wikipedia.org/wiki/Bencode
+        http://pypi.python.org/pypi/bencode/
+        '''
+        try:
+            return self._process(imps.bencode, 'application/x-bittorrent')
+        except AttributeError:
+            raise ImportError('requires "bencode" library')
+
+    def bson(self):
+        '''
+        binary JSON dumper
+
+        http://en.wikipedia.org/wiki/BSON
+        http://pypi.python.org/pypi/bson/
+        '''
+        try:
+            return self._process(imps.bson.dumps, 'application/x-bson')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires "bson" library')
+
+    def csv(self, **kw):
+        '''comma-separated values dumper'''
+        def dumps(data, **kw):
+            dumped = imps.StringIO()
+            csvw = csv.writer(dumped, **kw)
+            for row in data:
+                csvw.writerow(row)
+            return dumped.getvalue()
+        return self._process(lambda x: dumps(x, **kw), 'text/csv')
+
+    def excel(self, **kw):
+        '''
+        M$ excel dumper
+
+        http://pypi.python.org/pypi/xlrd/
+        http://pypi.python.org/pypi/xlwt/
+        '''
+        try:
+            workbook = imps.xlwt.Workbook  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires the "xlrd" and "xlwt" libraries')
+        def dumps(data, **kw): #@IgnorePep8
+            wb = workbook(encoding='utf8', **kw)
+            ws = wb.add_sheet(kw.get('title', 'Worksheet 1'))
+            write = ws.write
+            for i, row in enumerate(data):
+                for j, col in enumerate(row):
+                    write(i, j, col)
+            stream = imps.StringIO()
+            wb.save(stream)
+            return stream.getvalue()
+        return self._process(
+            self._partial(dumps, **kw), 'application/vnd.ms-excel',
+        )
+
+    def html(self, **kw):
+        '''
+        html dumper
+
+        http://pypi.python.org/pypi/lxml/
+        '''
+        try:
+            return self._process(
+                lambda x: imps.html.tostring(x, **kw), 'text/html',  # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires "lxml" library')
+
+    def json(self, **kw):
+        '''JavaScript Object Notation (JSON) dumper'''
+        return self._process(
+            lambda x: imps.json.dumps(x, use_decimal=True, **kw),
+            'application/json',
+        )
+
+    def jsonpickle(self):
+        '''JavaScript Object Notation (JSON) pickle dumper'''
+        try:
+            return self._process(imps.jsonpickle.encode, 'application/json')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires the "jsonpickle" library')
+
+    def marshal(self):
+        '''
+        python marshal talker (not guaranteed to interoperate between major
+        Python releases)
+
+        ACCEPTING ARBITRARY MARSHAL DATA MAY BE UNSAFE!!!
+        '''
+        return self._process(marshal.dumps, 'application/x-python-marshal')
+
+    def message_pack(self):
+        '''
+        message pack dumper
+
+        http://msgpack.org/
+        http://wiki.msgpack.org/display/MSGPACK/QuickStart+for+Python
+
+        http://pypi.python.org/pypi/msgpack-python/
+        '''
+        try:
+            return self._process(imps.msgpack.packb, 'application/x-msgpack')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires "msgpack" library')
+
+    def multipart(self):
+        '''form multipart dumper'''
+        try:
+            return self._process(
+                lambda x: imps.encode_multipart_formdata(
+                    x, boundary='----------AaB03x',
+                ),
+                'multipart/form-data; boundary=----------AaB03x',
+            )
+        except AttributeError:
+            raise ImportError('requires "requests" or "urllib3" packages')
+
+    def netstring(self):
+        '''
+        netstring dumper
+
+        http://cr.yp.to/proto/netstrings.txt
+
+        http://pypi.python.org/pypi/netstring
+        '''
+        try:
+            return self._process(
+                imps.netstring.encode, 'application/x-netstring',   # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires "netstring" library')
+
+    def pickle(self):
+        '''
+        python pickle talker (not guaranteed to interoperate between major
+        Python releases. ACCEPTING ARBITRARY PICKLE DATA MAY BE UNSAFE!!!
+        '''
+        pickle = imps.pickle  # @UndefinedVariable
+        return self._process(
+            lambda x: pickle.dumps(x, protocol=pickle.HIGHEST_PROTOCOL), 
+            'application/python-pickle',
+        )
+
+    def plist(self):
+        '''property list dumper'''
+        return self._process(imps.plist_dumps, 'application/x-plist')
+
+    def protobuf(self):
+        '''
+        google protocol buffers dumper
+
+        http://code.google.com/p/protobuf/
+
+        http://pypi.python.org/pypi/protobuf/
+        '''
+        return self._process(
+            lambda x: x.SerializeToString(), 'application/x-protobuf',
+        )
+
+    def thrift(self):
+        '''
+        thrift dumper
+    
+        http://thrift.apache.org/
+    
+        http://pypi.python.org/pypi/thrift/
+        '''
+        try:
+            return self._process(imps.thrift.serialize, 'application/x-thrift')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires "thrift" library')
+
+    def tnetstring(self):
+        '''
+        tnetstring loader
+    
+        http://pypi.python.org/pypi/tnetstring/
+        '''
+        try:
+            return self._process(
+                imps.tnetstring.dumps, 'application/x-tnetstring',  # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires "tnetstring" library')
+
+    def urlencode(self, **kw):
+        '''urlencode dumper'''
+        return self._process(
+            lambda x: imps.urlencode(x, **kw),  # @UndefinedVariable @IgnorePep8
+            'application/x-www-form-urlencoded',
+        )
+
+    def xml(self, **kw):
+        '''
+        extensible markup language loader
+
+        http://pypi.python.org/pypi/lxml/
+        '''
+        return self._process(
+            lambda x: imps.etree.tostring(x, **kw), 'text/xml',
+        )
+
+    def xmlrpc(self, **kw):
+        '''
+        extensible markup language remote procedure call dumper
+        '''
+        return self._process(
+            lambda x: imps.xmlrpc.dumps(x, **kw), 'text/xml',   # @UndefinedVariable @IgnorePep8
+        )
+
+    def yaml(self, **kw):
+        '''
+        YAML ain't markup language dumper
+
+        http://en.wikipedia.org/wiki/YAML
+
+        http://pypi.python.org/pypi/PyYAML/
+        '''
+        try:
+            return self._process(
+                lambda x: imps.yaml.dump(x, **kw), 'application/x-yaml',  # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires PyYaml module')
+
+
+@appifies(KLoads)
+class Loads(iolet):
+
+    '''loader'''
+
+    def bencode(self):
+        '''
+        bencode dumper
+
+        http://en.wikipedia.org/wiki/Bencode
+        http://pypi.python.org/pypi/bencode/
+        '''
+        try:
+            return self._process(imps.bdecode, 'application/x-bittorrent')
+        except AttributeError:
+            raise ImportError('requires "bencode" library')
+
+    def bson(self):
+        '''
+        binary JSON loader
+
+        http://en.wikipedia.org/wiki/BSON
+        http://pypi.python.org/pypi/bson/
+        '''
+        try:
+            return self._process(imps.bson.loads, 'application/x-bson')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires "bson" library')
+
+    def csv(self, **kw):
+        '''comma-separated values loader'''
+        def loads(data, **kw):
+            return list(r for r in csv.reader(imps.StringIO(data), **kw))
+        return self._process(lambda x: loads(x, **kw), 'text/csv')
+
+    def excel(self, **kw):
+        '''
+        M$ excel serialization
+
+        http://pypi.python.org/pypi/xlrd/
+        http://pypi.python.org/pypi/xlwt/
+        '''
+        try:
+            workbook = imps.xlrd.open_workbook  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires the "xlrd" and "xlwt" libraries')
+        def loads(data, **kw): #@IgnorePep8
+            wb = workbook(file_contents=data, **kw)
+            new_workbook = list()
+            oappend = new_workbook.append
+            for sheet in wb.sheets():
+                cellvalue = sheet.cell_value
+                new_sheet = list()
+                nappend = new_sheet.append
+                for row in range(sheet.nrows):
+                    new_row = list()
+                    iappend = new_row.append
+                    for col in xrange(sheet.ncols):
+                        iappend(cellvalue(row, col))
+                    nappend(new_row)
+                oappend(new_sheet)
+            return new_workbook
+        return self._process(
+            lambda x: loads(x, **kw), 'application/vnd.ms-excel',
+        )
+
+    def html(self, **kw):
+        '''
+        html serialization
+
+        http://pypi.python.org/pypi/lxml/
+        '''
+        return self._process(
+            lambda x: imps.html.fromstring(x, **kw), 'text/html',  # @UndefinedVariable @IgnorePep8
+        )
+
+    def json(self, **kw):
+        '''JavaScript Object Notation (JSON) serialization'''
+        return self._process(
+            lambda x: imps.json.loads(x, use_decimal=True, **kw),
+            'application/json',
+        )
+
+    def jsonpickle(self):
+        '''JavaScript Object Notation (JSON) pickle serialization'''
+        try:
+            return self._process(imps.jsonpickle.decode, 'application/json')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires the "jsonpickle" library')
+
+    def marshal(self):
+        '''
+        python marshal talker (not guaranteed to interoperate between major
+        Python releases)
+
+        ACCEPTING ARBITRARY MARSHAL DATA MAY BE UNSAFE!!!
+        '''
+        return self._process(marshal.loads, 'application/x-python-marshal')
+
+    def message_pack(self):
+        '''
+        message pack serialization key
+
+        http://msgpack.org/
+        http://wiki.msgpack.org/display/MSGPACK/QuickStart+for+Python
+
+        http://pypi.python.org/pypi/msgpack-python/
+        '''
+        try:
+            return self._process(imps.msgpack.unpackb, 'application/x-msgpack')  # @UndefinedVariable @IgnorePep8
+        except AttributeError:
+            raise ImportError('requires "msgpack" library')
+
+    def multipart(self):
+        '''form multipart serialization'''
+        def loads(data):
+            q = parse_multipart(
+                imps.StringIO(data), dict(boundary='----------AaB03x')
+            )
+            exhaustmap(
+                q, lambda x, y: setitem(q, x, y[0]), lambda x: len(x[1]) == 1
+            )
+            return q
+        return self._process(
+            loads, 'multipart/form-data; boundary=----------AaB03x',
+        )
+
+    def netstring(self):
+        '''
+        netstring serialization key
+
+        http://cr.yp.to/proto/netstrings.txt
+
+        http://pypi.python.org/pypi/netstring
+        '''
+        try:
+            return self._process(
+                lambda x: imps.netstring.decode(x)[0],  # @UndefinedVariable @IgnorePep8
+                'application/x-netstring',
+            )
+        except AttributeError:
+            raise ImportError('requires "netstring" library')
+
+    def pickle(self):
+        '''
+        python pickle talker (not guaranteed to interoperate between major
+        Python releases. ACCEPTING ARBITRARY PICKLE DATA MAY BE UNSAFE!!!
+        '''
+        return self._process(imps.pickle.loads, 'application/x-python-pickle')  # @UndefinedVariable @IgnorePep8
+
+    def plist(self):
+        '''property list serialization key'''
+        return self._process(imps.plist_loads, 'application/x-plist')
+
+    def protobuf(self, **kw):
+        '''
+        google protocol buffers serialization
+
+        http://code.google.com/p/protobuf/
+
+        http://pypi.python.org/pypi/protobuf/
+        '''
+        proto = kw.get('proto')
+        def load(data): #@IgnorePep8
+            p = proto()
+            p.ParseFromString(data)
+            return p
+        return self._process(load, 'application/x-protobuf')
+
+    def thrift(self, base):
+        '''
+        thrift serialization key
+    
+        http://thrift.apache.org/
+    
+        http://pypi.python.org/pypi/thrift/
+        '''
+        try:
+            return self._process(
+               lambda x: imps.thrift.deserialize(x, base),  # @UndefinedVariable @IgnorePep8
+               'application/x-thrift',
+            )
+        except AttributeError:
+            raise ImportError('requires "thrift" library')
+
+    def tnetstring(self):
+        '''
+        tnetstring loader
+    
+        http://pypi.python.org/pypi/tnetstring/
+        '''
+        try:
+            return self._process(
+                imps.tnetstring.loads, 'application/x-tnetstring',  # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires "tnetstring" library')
+
+    def urlencode(self, **kw):
+        '''urlencode loader'''
+        def loads(data, **kw):
+            q = imps.parse_qs(data, **kw)
+            exhaustmap(
+                q, lambda x, y: setitem(q, x, y[0]), lambda x: len(x[1]) == 1,
+            )
+            return q
+        return self._process(lambda x: loads(x, **kw))
+
+    def xml(self, **kw):
+        '''
+        extensible markup language loader
+
+        http://pypi.python.org/pypi/lxml/
+        '''
+        return self._process(
+            lambda x: imps.etree.fromstring(x, **kw), 'text/xml', 'utf-8',
+        )
+
+    def xmlrpc(self, **kw):
+        '''
+        extensible markup language remote procedure call serialization key
+        '''
+        return self._process(
+            lambda x: imps.xmlrpc.loads(x, type, **kw)[0], 'text/xml',  # @UndefinedVariable @IgnorePep8
+        )
+
+    def yaml(self, **kw):
+        '''
+        YAML ain't markup language dumper
+
+        http://en.wikipedia.org/wiki/YAML
+
+        http://pypi.python.org/pypi/PyYAML/
+        '''
+        try:
+            return self._process(
+                lambda x: imps.yaml.load(x, **kw), 'application/x-yaml',  # @UndefinedVariable @IgnorePep8
+            )
+        except AttributeError:
+            raise ImportError('requires PyYaml module')

callchain/chainlet/keys.py

+# -*- coding: utf-8 -*-
+'''callchain contrib keys'''
+
+from appspace import AppspaceKey, Attribute, AppLookupError
+
+from callchain.keys.mixin import KBranch
+
+
+class NoService(AppLookupError):
+
+    '''no service'''
+
+
+class KChainlet(KBranch):
+
+    '''service key'''
+
+    def back():  # @NoSelf
+        '''switch back to root chain'''
+
+
+class KLogger(KChainlet):
+
+    '''logging service key'''
+
+    logger = Attribute('the logger')
+
+    def debug(msg):  # @NoSelf
+        '''log debug message'''
+
+    def warning(msg):  # @NoSelf
+        '''log warning message'''
+
+    def info(msg):  # @NoSelf
+        '''log info message'''
+
+    def error(msg):  # @NoSelf
+        '''log error message'''
+
+    def critical(msg):  # @NoSelf
+        '''log critical message'''
+
+    def exception(msg):  # @NoSelf
+        '''log exception message'''
+
+
+class KQueue(AppspaceKey):
+
+    '''queue key'''
+
+
+class KPorting(AppspaceKey):
+
+    '''porting key'''
+
+
+class KIO(KChainlet):
+
+    def read(mode='rb', encoding=None, errors='strict', *paths):  # @NoSelf
+        '''
+        read incoming things from files
+
+        @param mode: mode to open files (default: 'r')
+        @param encoding: encoding for text data (default: `None`)
+        @param errors: error handling in encoding text data (default: 'strict')
+        @param *paths: sequence of filesystem paths
+        '''
+
+    def write(mode='rb', encoding=None, errors='strict', *paths):  # @NoSelf
+        '''
+        write outgoing things to files
+
+        @param mode: mode to open files (default: 'r')
+        @param encoding: encoding for text data (default: `None`)
+        @param errors: error handling in encoding text data (default: 'strict')
+        @param *paths: sequence of filesystem paths
+        '''
+
+
+class KDum