root/trac/hacks/marketplugin/0.9/tracmarket/ctl.py

Revision 117 (checked in by stevegt, 6 years ago)

checkpoint after mss tutorial, before moving order validity checks until after order entry into db

Line 
1 import os
2 import sys
3 import time
4 import types
5 import urllib
6
7 from trac.core import *
8
9 from tracmarket.api import *
10 from tracmarket.mq import *
11 from tracmarket.response import Response
12
13 SequenceType = (types.ListType, types.TupleType, types.GeneratorType)
14
15 # XXX deprecate this file, move Context to context.py
16
17 class Controller(Component):
18     implements(IMessageBusSubscriber, IMarketController)
19
20     interpreters = ExtensionPoint(ICommandInterpreter)
21     models = ExtensionPoint(IMessageBusSubscriber)
22     ledgers = ExtensionPoint(ILedger)
23
24     # IMessageBusSubscriber methods
25
26     def solicit(self, bus):
27         bus.subscribe('market.cmd', reader=self._route_cmd)
28
29     def _route_cmd(self, bus, group, msg):
30         '''route all incoming commands to a per-symbol group'''
31         cmd = msg.data
32         tokens = cmd.strip().split()
33         symbol = tokens.pop(0)
34         if tokens:
35             verb = tokens.pop(0)
36         else:
37             verb = 'show'
38         args = tokens
39         msg = Msg(cmd, verb=verb, args=args)
40         group = 'market.cmd.%s' % (symbol)
41         bus.send(group, msg)
42
43     # IMarketController methods  XXX these should probably just move
44     # to UI, deprecate IMarketController
45
46     def open(self, req=None, bus=None, db=None):
47         if not db:
48             db = self.env.get_db_cnx()
49         ledger = iter(self.ledgers).next()
50         ctx = Context(env=self.env, req=req, db=db, ledger=ledger)
51         if not bus:
52             bus = MemoryBus(subscribers=self.models, ctx=ctx)
53         # XXX circ ref bus <-> ctx
54         ctx.mkres(bus=bus)
55         return bus
56
57     def run(bus, cmds):
58         '''Return a generator which sends commands to bus and yields
59         the resulting message stream.  Cmds is a list of command
60         strings.'''
61
62         '''
63         # execute cmd
64         id = bus.subscribe(re.compile('.*'))
65         msg = Msg(cmd)
66         bus.send('market.cmd', msg)
67         while True:
68             msg = bus.recv(id)
69             if not msg:
70                 break
71             req.hdf[msg.group] = msg.data
72         '''
73
74     def commit(self, bus):
75         bus.ctx.db.commit()
76
77     def rollback(self, bus):
78         bus.ctx.db.rollback()
79
80     def run_cmd(self, req, cmd):
81         bus = self.open(req)
82         bus.subscribe('res.', reader=self._recv_res)
83         ctx = bus.ctx
84         '''
85         results = self.run(bus, [cmd])
86         for msg in results:
87             if not msg.group.startswith('message.'):
88                 # XXX let ctx.res accumulate for now
89                 continue
90             XXX
91         self.close(bus)
92         '''
93         db = ctx.db
94         try:
95             self.xeq(ctx, db, cmd)
96         except InsufficientFunds, e:
97             db.rollback()
98             ctx.res.error(str(e))
99         except:
100             db.rollback()
101             raise
102         else:
103             db.commit()
104         return ctx
105
106     # internal
107
108     def _recv_res(self, bus, group, msg):
109         pass
110
111     def xeq(self, ctx, db, cmd):
112         req = ctx.req
113         db = ctx.db
114         messages = None
115         hit = False
116         for interpreter in self.interpreters:
117             cmx = interpreter.parse_cmd(ctx, cmd)
118             if cmx:
119                 hit = True
120                 cmx()
121                 break
122         if not hit:
123             raise TracError, "Unrecognized command: %s" % cmd
124    
125
126 class Context(object):
127     '''A place to hold per-query context, since we shouldn't store
128     transients in the specialist Component instance.'''
129
130     def __init__(self, env, req, ledger, res=None, db=None):
131         self.env = env
132         self.req = req
133         self.ledger = ledger
134         self.res = res
135         self.db = db
136
137     def mkres(self, bus):
138         self.res = Response(bus=bus, path='')
139
140     def Mock(cls, **kwargs):
141         d = dict(
142                 env = None,
143                 req = None,
144                 ledger = None,
145             )
146         d.update(kwargs)
147         return cls(**d)
148     Mock = classmethod(Mock)
149    
Note: See TracBrowser for help on using the browser.