ct 0.10.8.114__py3-none-any.whl → 0.10.8.116__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cantools/__init__.py +38 -13
- cantools/_db.py +1 -1
- cantools/cfg.py +13 -0
- cantools/config.py +12 -4
- cantools/db/__init__.py +3 -0
- cantools/db/gae/model.py +1 -2
- cantools/db/wp.py +1 -1
- cantools/scripts/index.py +2 -8
- cantools/scripts/init.py +1 -1
- cantools/scripts/pubsub/actor.py +3 -1
- cantools/scripts/pubsub/bots.py +11 -13
- cantools/scripts/start.py +2 -2
- cantools/util/__init__.py +2 -0
- cantools/util/admin.py +10 -18
- cantools/util/ai/__init__.py +8 -0
- cantools/util/ai/tox/__init__.py +15 -0
- cantools/util/ai/tox/duck.py +80 -0
- cantools/util/ai/tox/fzn.py +22 -0
- cantools/util/ai/tox/g4free.py +73 -0
- cantools/util/ai/vox.py +84 -0
- cantools/util/apper/__init__.py +1 -0
- cantools/util/apper/ander.py +101 -0
- cantools/util/apper/data.py +167 -0
- cantools/util/system.py +2 -23
- cantools/web/__init__.py +6 -2
- cantools/web/bw.py +70 -0
- cantools/web/gae_server.py +1 -6
- cantools/web/util.py +6 -409
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/METADATA +7 -8
- ct-0.10.8.116.dist-info/RECORD +56 -0
- cantools/web/dez_server/__init__.py +0 -1
- cantools/web/dez_server/controller.py +0 -129
- cantools/web/dez_server/cron.py +0 -115
- cantools/web/dez_server/daemons.py +0 -64
- cantools/web/dez_server/mail.py +0 -24
- cantools/web/dez_server/response.py +0 -63
- cantools/web/dez_server/routes.py +0 -21
- cantools/web/dez_server/server.py +0 -229
- cantools/web/dez_server/sms.py +0 -12
- ct-0.10.8.114.dist-info/RECORD +0 -55
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/LICENSE +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/WHEEL +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/entry_points.txt +0 -0
- {ct-0.10.8.114.dist-info → ct-0.10.8.116.dist-info}/top_level.txt +0 -0
cantools/web/util.py
CHANGED
|
@@ -1,87 +1,10 @@
|
|
|
1
|
-
import re, os, sys, ast, json, time
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
from urllib.request import urlopen, Request
|
|
5
|
-
except:
|
|
6
|
-
from urllib import quote, unquote, urlencode # py2.7
|
|
7
|
-
from urllib2 import urlopen, Request
|
|
8
|
-
from base64 import b64encode, b64decode
|
|
1
|
+
import re, os, sys, ast, json, time
|
|
2
|
+
from urllib.parse import urlencode
|
|
3
|
+
from urllib.request import urlopen, Request
|
|
9
4
|
from dez.http.static import StaticStore
|
|
5
|
+
from babyweb.util import local, send_file
|
|
6
|
+
from babyweb.config import config as tinyfyg
|
|
10
7
|
from cantools import config
|
|
11
|
-
from six import string_types
|
|
12
|
-
|
|
13
|
-
DEBUG = True
|
|
14
|
-
|
|
15
|
-
# memcache stuff -- overwrite with setters
|
|
16
|
-
def getmem(key, tojson=True):
|
|
17
|
-
log("memcache getting: %s"%(key,))
|
|
18
|
-
|
|
19
|
-
def setmem(key, val, fromjson=True):
|
|
20
|
-
log("memcache setting: %s -> %s"%(key, val))
|
|
21
|
-
|
|
22
|
-
def delmem(key):
|
|
23
|
-
log("memcache deleting: %s"%(key,))
|
|
24
|
-
|
|
25
|
-
def clearmem():
|
|
26
|
-
log("memcache clearing")
|
|
27
|
-
|
|
28
|
-
def set_getmem(f):
|
|
29
|
-
global getmem
|
|
30
|
-
getmem = f
|
|
31
|
-
|
|
32
|
-
def set_setmem(f):
|
|
33
|
-
global setmem
|
|
34
|
-
setmem = f
|
|
35
|
-
|
|
36
|
-
def set_delmem(f):
|
|
37
|
-
global delmem
|
|
38
|
-
delmem = f
|
|
39
|
-
|
|
40
|
-
def set_clearmem(f):
|
|
41
|
-
global clearmem
|
|
42
|
-
clearmem = f
|
|
43
|
-
|
|
44
|
-
# logging -- overwrite with setlog if ya want
|
|
45
|
-
def log(*args, **kwargs):
|
|
46
|
-
print(args, kwargs)
|
|
47
|
-
|
|
48
|
-
# encoding, decoding -- may overwrite with setenc/setdec, but not _that_ necessary
|
|
49
|
-
_c = config.scrambler
|
|
50
|
-
_cl = len(_c)
|
|
51
|
-
_chl = int(_cl / 2)
|
|
52
|
-
|
|
53
|
-
def flip(c):
|
|
54
|
-
i = _c.find(c)
|
|
55
|
-
if i == -1:
|
|
56
|
-
return c
|
|
57
|
-
return _c[(i + _chl) % _cl]
|
|
58
|
-
|
|
59
|
-
def scramble(s):
|
|
60
|
-
return "".join([flip(c) for c in s])
|
|
61
|
-
|
|
62
|
-
def enc(data):
|
|
63
|
-
return scramble(b64encode(hasattr(data, "encode") and data.encode() or data).decode())
|
|
64
|
-
|
|
65
|
-
def dec(data):
|
|
66
|
-
return data.startswith("{") and data or b64decode(scramble(data)).decode()
|
|
67
|
-
|
|
68
|
-
# setters (see above)
|
|
69
|
-
def setlog(f):
|
|
70
|
-
global log
|
|
71
|
-
log = f
|
|
72
|
-
|
|
73
|
-
def setenc(f):
|
|
74
|
-
global enc
|
|
75
|
-
enc = f
|
|
76
|
-
|
|
77
|
-
def setdec(f):
|
|
78
|
-
global dec
|
|
79
|
-
dec = f
|
|
80
|
-
|
|
81
|
-
# threading
|
|
82
|
-
localvars = threading.local()
|
|
83
|
-
def local(key, fallback=None):
|
|
84
|
-
return getattr(localvars, key, fallback)
|
|
85
8
|
|
|
86
9
|
# request functions
|
|
87
10
|
def deUnicodeDict(d):
|
|
@@ -92,335 +15,9 @@ def deUnicodeDict(d):
|
|
|
92
15
|
n[str(v)] = deUnicodeDict(d[v])
|
|
93
16
|
return n
|
|
94
17
|
|
|
95
|
-
def cgi_dump():
|
|
96
|
-
return local("request_string")
|
|
97
|
-
|
|
98
|
-
def cgi_read():
|
|
99
|
-
return local("read", sys.stdin.read)()
|
|
100
|
-
|
|
101
|
-
def set_read(f):
|
|
102
|
-
localvars.read = f
|
|
103
|
-
|
|
104
|
-
def set_redir(f):
|
|
105
|
-
localvars.redir = f
|
|
106
|
-
|
|
107
|
-
def rdec(data):
|
|
108
|
-
bdata = b64decode(data.encode())
|
|
109
|
-
try: # py2
|
|
110
|
-
return unquote(bdata).decode()
|
|
111
|
-
except: #py3
|
|
112
|
-
return unquote(bdata.decode())
|
|
113
|
-
|
|
114
|
-
def renc(data):
|
|
115
|
-
try: # py2
|
|
116
|
-
return b64encode(quote(data).encode()).decode()
|
|
117
|
-
except: #py3
|
|
118
|
-
return b64encode(quote(data.encode())).decode()
|
|
119
|
-
|
|
120
|
-
def rb64(data, de=False): # depped
|
|
121
|
-
log("[DEPRECATION WARNING] Something just called rb64(), which is depped -- use rec_conv()")
|
|
122
|
-
return rec_conv(data, de)
|
|
123
|
-
|
|
124
|
-
def rec_conv(data, de=False):
|
|
125
|
-
if isinstance(data, bytes):
|
|
126
|
-
try:
|
|
127
|
-
data = data.decode()
|
|
128
|
-
except:
|
|
129
|
-
pass
|
|
130
|
-
if isinstance(data, string_types):
|
|
131
|
-
return (de and rdec or renc)(data)
|
|
132
|
-
elif isinstance(data, dict):
|
|
133
|
-
for k, v in list(data.items()):
|
|
134
|
-
data[k] = rec_conv(v, de)
|
|
135
|
-
elif isinstance(data, list):
|
|
136
|
-
return [rec_conv(d, de) for d in data]
|
|
137
|
-
return data
|
|
138
|
-
|
|
139
|
-
def qs_get(x, y):
|
|
140
|
-
val = localvars.request.getvalue(x, y)
|
|
141
|
-
if val:
|
|
142
|
-
val = unquote(val)
|
|
143
|
-
return val
|
|
144
|
-
|
|
145
|
-
def cgi_load(force=False):
|
|
146
|
-
localvars.request_string = cgi_read()
|
|
147
|
-
data = config.encode and dec(localvars.request_string) or localvars.request_string
|
|
148
|
-
try:
|
|
149
|
-
try:
|
|
150
|
-
jdata = json.loads(data)
|
|
151
|
-
except:
|
|
152
|
-
jdata = ast.literal_eval(data)
|
|
153
|
-
try:
|
|
154
|
-
localvars.request = rec_conv(jdata, True)
|
|
155
|
-
except:
|
|
156
|
-
localvars.request = jdata
|
|
157
|
-
except:
|
|
158
|
-
import cgi
|
|
159
|
-
localvars.request = cgi.FieldStorage()
|
|
160
|
-
setattr(localvars.request, "get", qs_get)
|
|
161
|
-
if not localvars.request:
|
|
162
|
-
if force or config.web.server == "dez":
|
|
163
|
-
localvars.request = {}
|
|
164
|
-
else:
|
|
165
|
-
fail('no request data!')
|
|
166
|
-
|
|
167
|
-
def cgi_get(key, choices=None, required=True, default=None, shield=False, decode=False, base64=False):
|
|
168
|
-
request = local("request")
|
|
169
|
-
val = request.get(key, default)
|
|
170
|
-
if val is None:
|
|
171
|
-
required and fail('no value submitted for required field: "%s" [%s]'%(key, request))
|
|
172
|
-
elif shield:
|
|
173
|
-
ip = local("ip")
|
|
174
|
-
shield = config.web.shield
|
|
175
|
-
if shield(val, ip, fspath=True, count=False):
|
|
176
|
-
log('cgi_get() shield bounced "%s" for "%s"'%(ip, shield.ip(ip)["message"]))
|
|
177
|
-
fail()
|
|
178
|
-
if choices and val not in choices:
|
|
179
|
-
fail('invalid value for "%s": "%s"'%(key, val))
|
|
180
|
-
if base64 and val:
|
|
181
|
-
val = b64decode(unquote(val))
|
|
182
|
-
if decode and val:
|
|
183
|
-
val = unquote(val)
|
|
184
|
-
return val
|
|
185
|
-
|
|
186
|
-
# response functions
|
|
187
|
-
def _send(data):
|
|
188
|
-
send = local("send")
|
|
189
|
-
if send:
|
|
190
|
-
send(data)
|
|
191
|
-
else:
|
|
192
|
-
print(data)
|
|
193
|
-
|
|
194
|
-
def set_send(f):
|
|
195
|
-
localvars.send = f
|
|
196
|
-
|
|
197
|
-
def _close():
|
|
198
|
-
local("close", sys.exit)()
|
|
199
|
-
|
|
200
|
-
def set_close(f):
|
|
201
|
-
localvars.close = f
|
|
202
|
-
|
|
203
|
-
def _pre_close():
|
|
204
|
-
pass
|
|
205
|
-
|
|
206
|
-
def set_pre_close(f):
|
|
207
|
-
global _pre_close
|
|
208
|
-
_pre_close = f
|
|
209
|
-
|
|
210
|
-
def _header(hkey, hval):
|
|
211
|
-
header = local("header")
|
|
212
|
-
if header:
|
|
213
|
-
header(hkey, hval)
|
|
214
|
-
else:
|
|
215
|
-
_send("%s: %s"%(hkey, hval))
|
|
216
|
-
|
|
217
|
-
def set_header(f):
|
|
218
|
-
localvars.header = f
|
|
219
|
-
|
|
220
|
-
def _write(data, exit=True, savename=None):
|
|
221
|
-
if savename:
|
|
222
|
-
setmem(savename, data, False)
|
|
223
|
-
# try:
|
|
224
|
-
# data = data.decode('ascii', 'replace').encode('utf-8')
|
|
225
|
-
# except Exception as e:
|
|
226
|
-
# data = data.encode('utf-8')
|
|
227
|
-
_send(data)
|
|
228
|
-
if exit:
|
|
229
|
-
_pre_close()
|
|
230
|
-
_close()
|
|
231
|
-
|
|
232
|
-
def trysavedresponse(key=None):
|
|
233
|
-
key = key or local("request_string")
|
|
234
|
-
response = getmem(key, False)
|
|
235
|
-
response and _write(response, exit=True)
|
|
236
|
-
|
|
237
|
-
def dez_wrap(resp, failure):
|
|
238
|
-
from cantools.db import seshman
|
|
239
|
-
from rel.errors import AbortBranch
|
|
240
|
-
def f():
|
|
241
|
-
try:
|
|
242
|
-
resp()
|
|
243
|
-
except AbortBranch as e:
|
|
244
|
-
seshman.close()
|
|
245
|
-
raise AbortBranch() # handled in rel
|
|
246
|
-
except SystemExit:
|
|
247
|
-
pass
|
|
248
|
-
except Exception as e:
|
|
249
|
-
failure(e)
|
|
250
|
-
return f
|
|
251
|
-
|
|
252
|
-
def gae_wrap(resp, failure):
|
|
253
|
-
def f():
|
|
254
|
-
try:
|
|
255
|
-
resp()
|
|
256
|
-
except SystemExit:
|
|
257
|
-
pass
|
|
258
|
-
except Exception as e:
|
|
259
|
-
failure(e)
|
|
260
|
-
return f
|
|
261
|
-
|
|
262
|
-
resp_wrap = { "dez": dez_wrap, "gae": gae_wrap }
|
|
263
|
-
|
|
264
|
-
def do_respond(responseFunc, failMsg="failed", failHtml=False, failNoEnc=False, noLoad=False, threaded=False, response=None, autowin=True):
|
|
265
|
-
def resp():
|
|
266
|
-
response and response.set_cbs()
|
|
267
|
-
noLoad or cgi_load()
|
|
268
|
-
responseFunc()
|
|
269
|
-
autowin and succeed()
|
|
270
|
-
|
|
271
|
-
def failure(e):
|
|
272
|
-
fail(data=failMsg, html=failHtml, err=e, noenc=failNoEnc)
|
|
273
|
-
|
|
274
|
-
wrapped_response = resp_wrap[config.web.server](resp, failure)
|
|
275
|
-
if threaded: # dez only!!!
|
|
276
|
-
from rel import thread
|
|
277
|
-
thread(wrapped_response)
|
|
278
|
-
else:
|
|
279
|
-
wrapped_response()
|
|
280
|
-
|
|
281
|
-
def redirect(addr, msg="", noscript=False, exit=True, metas=None):
|
|
282
|
-
a = "<script>"
|
|
283
|
-
if msg:
|
|
284
|
-
a += 'alert("%s"); '%(msg,)
|
|
285
|
-
a += "document.location = '%s';</script>"%(addr,)
|
|
286
|
-
if noscript:
|
|
287
|
-
a += '<noscript>This site requires Javascript to function properly. To enable Javascript in your browser, please follow <a href="http://www.google.com/support/bin/answer.py?answer=23852">these instructions</a>. Thank you, and have a nice day.</noscript>'
|
|
288
|
-
if metas:
|
|
289
|
-
a = "<html><head>%s%s</head><body></body></html>"%(metas, a)
|
|
290
|
-
_header("Content-Type", "text/html")
|
|
291
|
-
_write(_env(True)%(a,), exit)
|
|
292
|
-
|
|
293
18
|
def setcachedefault(shouldCache=True):
|
|
294
|
-
# deprecated -- should set via config.memcache.update("requst", [bool])
|
|
295
19
|
config.memcache.update("request", shouldCache)
|
|
296
|
-
|
|
297
|
-
def _env(html):
|
|
298
|
-
return "%s"
|
|
299
|
-
|
|
300
|
-
def set_env(f):
|
|
301
|
-
global _env
|
|
302
|
-
_env = f
|
|
303
|
-
|
|
304
|
-
def processResponse(data, code):
|
|
305
|
-
if code == "1":
|
|
306
|
-
try:
|
|
307
|
-
data = json.dumps(data)
|
|
308
|
-
except:
|
|
309
|
-
data = json.dumps(rec_conv(data))
|
|
310
|
-
code = "3"
|
|
311
|
-
elif code == "0":
|
|
312
|
-
try:
|
|
313
|
-
json.dumps(data)
|
|
314
|
-
except:
|
|
315
|
-
data = rec_conv(data)
|
|
316
|
-
code = "2"
|
|
317
|
-
return "%s%s"%(code, data)
|
|
318
|
-
|
|
319
|
-
def succeed_sync(func, cb):
|
|
320
|
-
d = {}
|
|
321
|
-
def handle(*a, **k):
|
|
322
|
-
d["a"] = a
|
|
323
|
-
d["k"] = k
|
|
324
|
-
func(handle)
|
|
325
|
-
while True:
|
|
326
|
-
time.sleep(0.01)
|
|
327
|
-
if d["a"] or d["k"]:
|
|
328
|
-
succeed(cb(*d["a"], **d["k"]))
|
|
329
|
-
|
|
330
|
-
def succeed(data="", html=False, noenc=False, savename=None, cache=False):
|
|
331
|
-
if cache or config.memcache.request:
|
|
332
|
-
savename = local("request_string")
|
|
333
|
-
_header("Content-Type", "text/%s"%(html and "html" or "plain"))
|
|
334
|
-
draw = processResponse(data, "1")
|
|
335
|
-
dstring = (config.encode and not noenc) and enc(draw) or draw
|
|
336
|
-
_write(_env(html)%(dstring,), savename=savename)
|
|
337
|
-
|
|
338
|
-
def fail(data="failed", html=False, err=None, noenc=False, exit=True):
|
|
339
|
-
if err:
|
|
340
|
-
# log it
|
|
341
|
-
import traceback
|
|
342
|
-
logdata = "%s --- %s --> %s"%(data, repr(err), traceback.format_exc())
|
|
343
|
-
log(logdata, "error")
|
|
344
|
-
if DEBUG:
|
|
345
|
-
# write it
|
|
346
|
-
data = logdata
|
|
347
|
-
resp = local("response")
|
|
348
|
-
reqstring = local("request_string")
|
|
349
|
-
path = resp and resp.request.url or "can't find path!"
|
|
350
|
-
ip = local("ip") or (resp and resp.ip or "can't find ip!")
|
|
351
|
-
edump = "%s\n\n%s\n\n%s\n\n%s"%(path, ip, reqstring, logdata)
|
|
352
|
-
shield = config.web.shield
|
|
353
|
-
if reqstring and shield(reqstring, ip):
|
|
354
|
-
data = "nabra"
|
|
355
|
-
reason = shield.ip(ip)["message"]
|
|
356
|
-
logline = "%s - IP (%s) banned!"%(reason, ip)
|
|
357
|
-
edump = "%s\n\n%s"%(logline, edump)
|
|
358
|
-
log(logline)
|
|
359
|
-
elif config.web.eflags:
|
|
360
|
-
samples = {
|
|
361
|
-
"traceback": logdata
|
|
362
|
-
}
|
|
363
|
-
if reqstring:
|
|
364
|
-
samples["request"] = reqstring
|
|
365
|
-
for sample in samples:
|
|
366
|
-
for ef in config.web.eflags:
|
|
367
|
-
if ef in samples[sample]:
|
|
368
|
-
reason = '"%s" in %s'%(ef, sample)
|
|
369
|
-
logline = "%s - IP (%s) banned!"%(reason, ip)
|
|
370
|
-
edump = "%s\n\n%s"%(logline, edump)
|
|
371
|
-
shield.suss(ip, reason)
|
|
372
|
-
log(logline)
|
|
373
|
-
if config.web.report:
|
|
374
|
-
from cantools.web import email_admins
|
|
375
|
-
email_admins("error encountered", edump)
|
|
376
|
-
_header("Content-Type", "text/%s"%(html and "html" or "plain"))
|
|
377
|
-
draw = processResponse(data, "0")
|
|
378
|
-
dstring = (config.encode and not noenc) and enc(draw) or draw
|
|
379
|
-
_write(_env(html)%(dstring,), exit)
|
|
380
|
-
|
|
381
|
-
def _headers(headers):
|
|
382
|
-
for k, v in list(headers.items()):
|
|
383
|
-
_header(k, v)
|
|
384
|
-
if config.web.server == "gae":
|
|
385
|
-
_send("")
|
|
386
|
-
|
|
387
|
-
def send_pdf(data, title=None):
|
|
388
|
-
if title:
|
|
389
|
-
_headers({
|
|
390
|
-
"Content-Type": 'application/pdf; name="%s.pdf"'%(title,),
|
|
391
|
-
"Content-Disposition": 'attachment; filename="%s.pdf"'%(title,)
|
|
392
|
-
})
|
|
393
|
-
else:
|
|
394
|
-
_headers({"Content-Type": "application/pdf"})
|
|
395
|
-
_send(data)
|
|
396
|
-
_close()
|
|
397
|
-
|
|
398
|
-
def send_image(data):
|
|
399
|
-
_headers({"Content-Type": "image/png"})
|
|
400
|
-
_send(data)
|
|
401
|
-
_close()
|
|
402
|
-
|
|
403
|
-
FILETYPES = {"pdf": "application/pdf", "img": "image/png", "ico": "image/ico", "html": "text/html"}
|
|
404
|
-
|
|
405
|
-
def send_file(data, file_type=None, detect=False, headers={}):
|
|
406
|
-
if detect:
|
|
407
|
-
import magic
|
|
408
|
-
file_type = data and magic.from_buffer(data, True)
|
|
409
|
-
if file_type:
|
|
410
|
-
headers["Content-Type"] = FILETYPES.get(file_type, file_type)
|
|
411
|
-
_headers(headers)
|
|
412
|
-
_send(data)
|
|
413
|
-
_close()
|
|
414
|
-
|
|
415
|
-
def send_text(data, dtype="html", fname=None, exit=True, headers={}):
|
|
416
|
-
headers["Content-Type"] = "text/%s"%(dtype,)
|
|
417
|
-
if fname:
|
|
418
|
-
headers['Content-Disposition'] = 'attachment; filename="%s.%s"'%(fname, dtype)
|
|
419
|
-
_headers(headers)
|
|
420
|
-
_write(data, exit)
|
|
421
|
-
|
|
422
|
-
def send_xml(data):
|
|
423
|
-
send_text(data, "xml")
|
|
20
|
+
tinyfyg.update("memcache", shouldCache)
|
|
424
21
|
|
|
425
22
|
# misc
|
|
426
23
|
def verify_recaptcha(cresponse, pkey):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ct
|
|
3
|
-
Version: 0.10.8.
|
|
3
|
+
Version: 0.10.8.116
|
|
4
4
|
Summary: Modern minimal web framework
|
|
5
5
|
Author: Mario Balibrera
|
|
6
6
|
Author-email: mario.balibrera@gmail.com
|
|
@@ -13,13 +13,12 @@ Classifier: Operating System :: OS Independent
|
|
|
13
13
|
Classifier: Programming Language :: Python
|
|
14
14
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
15
|
License-File: LICENSE
|
|
16
|
+
Requires-Dist: babyweb >=0.1.2
|
|
16
17
|
Requires-Dist: catmail >=0.1.9.1
|
|
17
|
-
Requires-Dist: databae >=0.1.
|
|
18
|
-
Requires-Dist: dez >=0.10.10.
|
|
19
|
-
Requires-Dist: fyg >=0.1.7.
|
|
20
|
-
Requires-Dist: rel >=0.4.9.
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist: six >=1.12.0
|
|
23
|
-
Requires-Dist: venvr >=0.1.5.3
|
|
18
|
+
Requires-Dist: databae >=0.1.5.1
|
|
19
|
+
Requires-Dist: dez >=0.10.10.45
|
|
20
|
+
Requires-Dist: fyg >=0.1.7.9
|
|
21
|
+
Requires-Dist: rel >=0.4.9.23
|
|
22
|
+
Requires-Dist: venvr >=0.1.5.8
|
|
24
23
|
|
|
25
24
|
This portable modern web framework is the application-neutral backbone of Civil Action Network. It includes: a pubsub WebSocket server and bot platform; swappable web backends capable of targeting high-concurrency standalone or cloud platforms; a variable-mode application compiler; a broad-spectrum ORM and database migration tools; a built in administrative interface; and a rich modular JavaScript library.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
cantools/__init__.py,sha256=pYszyy7Gwi8eK0nDPsJq5aIok5xQnYLERkM74roIzFE,824
|
|
2
|
+
cantools/_db.py,sha256=g-kXshJpjfLiYPg8GtTrae1bD0uZ8eWbYi8ORKaXGNs,5075
|
|
3
|
+
cantools/_memcache.py,sha256=xv_rumi1mrr6Br4ofZXTA6deNOEyZg6nwFW6QEcUVZ4,2154
|
|
4
|
+
cantools/_pay.py,sha256=hvu8SiFVUySVIu5W1SZuD_6DHaUWnmy0XOITPlt1C3M,1292
|
|
5
|
+
cantools/admin.py,sha256=MuRKvFQ_LhGqRro6cY6e6PGOBjLXGwKKcTJ1GuAa3K0,1182
|
|
6
|
+
cantools/cfg.py,sha256=N1hBT_MwuHIYAtZ0vczjnE9B_cvwq_IcgTWRvoBUGZI,8920
|
|
7
|
+
cantools/config.py,sha256=FA9VmBhYhSIshizUjA7zrGNmgjYgoItrRGac-mKhp0o,5182
|
|
8
|
+
cantools/geo.py,sha256=WQMWp142niNzRf4WXRurzGPiFaZ3orbDpBwQC2gZXn0,5422
|
|
9
|
+
cantools/hooks.py,sha256=kEnYBt8Fl6EFJz_u-jPQjGQTXa9TxACZxPMbgUW3cHc,219
|
|
10
|
+
cantools/db/__init__.py,sha256=slJyO03jrCTEqDWzXUkrsmolGoJTO42FPJSLCE87RSM,614
|
|
11
|
+
cantools/db/admin.py,sha256=czWPFWaCb0qlJV3Smq2FsInp2xp6DUYZ08UhtRfDl7A,849
|
|
12
|
+
cantools/db/wp.py,sha256=YgUmeHk5WwvTjYxYeFbNr0gpgJBgZ9OsiRKx0jkxA9o,2801
|
|
13
|
+
cantools/db/gae/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
cantools/db/gae/model.py,sha256=2FO8XyhexspGCuguzECfAnQAbtn1OTVQUIUr7JDrEP8,4567
|
|
15
|
+
cantools/db/gae/properties.py,sha256=hhmW_S6ratX0kKu7ZPf59Z8ovh-3oWZ9GyfnppeeaDw,773
|
|
16
|
+
cantools/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
cantools/scripts/bench.py,sha256=3fwR3R4tewBFiRk_X-G75Kau8ZaZRr1-ztlH9AEbN6M,6480
|
|
18
|
+
cantools/scripts/builder.py,sha256=7zx79yNlm7klMA-pGWN4zuluEQ33T87rOFFd7qfJwEA,10942
|
|
19
|
+
cantools/scripts/deploy.py,sha256=1qubH9OQop9C4Px7c2VEJrcVBD8-0qMj86WxKuDxv44,5802
|
|
20
|
+
cantools/scripts/doc.py,sha256=2FdYNifZ3H5fCbJ-M4fPGNDpy4FIvPY2Uon8hIkP-fA,7957
|
|
21
|
+
cantools/scripts/index.py,sha256=8RAx0Ixtv8eYPU_CMsCVFFuZ4khcHMubdnXxzBm8Ctw,8545
|
|
22
|
+
cantools/scripts/init.py,sha256=DXc-rdjud5hrxdxIECrZaWTQ4xKKJTm4GY8D21FWm7s,14515
|
|
23
|
+
cantools/scripts/migrate.py,sha256=LgS1A6M-XFyXkXICFxbrQ9htcHMtS1L8o1dgRvj1cN0,18718
|
|
24
|
+
cantools/scripts/start.py,sha256=eU6DlHcINlfr_CS5rYEHSSi83V38JYDN98xuiXxTpNE,2257
|
|
25
|
+
cantools/scripts/util.py,sha256=44Q08c8CuEVxC3NlkUPyS5w1X8SQp6F6CdjMvddrL0M,595
|
|
26
|
+
cantools/scripts/pubsub/__init__.py,sha256=mSwkEEsjzPGwhxViS747ESZpqOnk1eH1RFOekNPgHc4,1025
|
|
27
|
+
cantools/scripts/pubsub/actor.py,sha256=8Lb5zTaLs1iIucKJLSIgtQF9znMVM0wbhiffi8QTDcI,356
|
|
28
|
+
cantools/scripts/pubsub/bots.py,sha256=D_A6-TlCTtgC3-v8q-aJ3X4taMqtHKWa2kpHNATIU0Y,4302
|
|
29
|
+
cantools/scripts/pubsub/channel.py,sha256=racPeZThUoKJK2TYFfNtwKkxjP5jLUwTWozoZzQb3t8,2333
|
|
30
|
+
cantools/scripts/pubsub/ps.py,sha256=enpSroRCKdJ4GS7M7mpv5mh0z6_rtv_JLpri2NvyJQ0,5216
|
|
31
|
+
cantools/scripts/pubsub/user.py,sha256=B1LdCmmwxgtTNgWGmtxDVzPruYjgw5J-vIjmcB0kbck,1554
|
|
32
|
+
cantools/util/__init__.py,sha256=zZ_0RSbOyChUvp4PBfuzKNy4KRQHJXv8abv-LO2T06I,3444
|
|
33
|
+
cantools/util/admin.py,sha256=b5lb4X1N7VfeL0MutMT_cWIpTMz3ehL900YkCN9DLPE,18469
|
|
34
|
+
cantools/util/data.py,sha256=RrvVmgQkelSCXHj0oqRkg_aifX6qI7IsrBAJr0wvq8s,2911
|
|
35
|
+
cantools/util/media.py,sha256=-znYq87blesL_rMc2OfYmum69z1uiyMe0XmGL--bS2g,8585
|
|
36
|
+
cantools/util/package.py,sha256=cKJwC7OoLRmQ2dzYtjZjpQoW09ojZ_nTTqgx0fCimHI,3998
|
|
37
|
+
cantools/util/system.py,sha256=DqwxuQWX1f60N7-fdfazc5vfhB_k1LgzqED3xpjgXyw,1301
|
|
38
|
+
cantools/util/ai/__init__.py,sha256=MXVRzXC8IGGKMxyhBYma-UzRi0EY4tdDe2to77zhp14,358
|
|
39
|
+
cantools/util/ai/vox.py,sha256=aoEhO3nwo1ITi9ONSfuNviSWFqWmUCvtJhD0AlNcN1g,2601
|
|
40
|
+
cantools/util/ai/tox/__init__.py,sha256=Gd8XKP_201ZjiovuO7t0dIueGYQxRTKPQ3vx6ALdgx0,542
|
|
41
|
+
cantools/util/ai/tox/duck.py,sha256=rH8trJg8JygAmHzdTOeyaR27wgS3bjEtRdSBYTwYcvg,1818
|
|
42
|
+
cantools/util/ai/tox/fzn.py,sha256=u0LWvJb8T_xkhQidRNuAbVVQybMt2zI9_D-O2lgrFwE,501
|
|
43
|
+
cantools/util/ai/tox/g4free.py,sha256=9mxrNGmB_5C5Yv9g452EQpkt5a-Wua5iTgIE3iBYl4E,1792
|
|
44
|
+
cantools/util/apper/__init__.py,sha256=SZdGKLZfPtwxhLjLmdihWERD09cGNJBwnvu8cTPStis,26
|
|
45
|
+
cantools/util/apper/ander.py,sha256=gnvwMqtSLgQDjYIbHCbI9PAOU-ToV_A2rYpc-JI_OrY,3504
|
|
46
|
+
cantools/util/apper/data.py,sha256=HSk_LRBnuCAzorK8Waw5yDFoyBZoTvAd46pPQYlE51E,5146
|
|
47
|
+
cantools/web/__init__.py,sha256=nJOA_sNuT31LgFauWGUjznjhWoubjb1JqGVg2XWXjhM,407
|
|
48
|
+
cantools/web/bw.py,sha256=N-cimUHYyDuHv8v2Ut0twsi8yBDMb3alw1m9EpCYDEs,2704
|
|
49
|
+
cantools/web/gae_server.py,sha256=dPLkEsvzOb-wEFCSMleCvIElNnJoLRMdAGw5DYytwGU,2007
|
|
50
|
+
cantools/web/util.py,sha256=ovacYpR6VtJVw9MvL9jJuXdkMKKv8A5GxjWE-KlYe70,4367
|
|
51
|
+
ct-0.10.8.116.dist-info/LICENSE,sha256=lUkxqJkYxLYhvL52PQdG8L3aqmG241XXmThs30isJTU,1078
|
|
52
|
+
ct-0.10.8.116.dist-info/METADATA,sha256=0yjaCxOawMmRBy0WNIgVMrSCF7im9xnsQ3Ls5fkJyPE,1175
|
|
53
|
+
ct-0.10.8.116.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
|
54
|
+
ct-0.10.8.116.dist-info/entry_points.txt,sha256=Gd3wUZp5AMeazvq2oIOh4qn57T2joZ8NeHenLhXG4Hw,261
|
|
55
|
+
ct-0.10.8.116.dist-info/top_level.txt,sha256=Tl_rJpBXgVrhgmBrKozbrcQrKnOIX89JqFF7aF_4EbA,9
|
|
56
|
+
ct-0.10.8.116.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .server import *
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import os, sys, platform
|
|
2
|
-
from dez.network import SocketController, daemon_wrapper
|
|
3
|
-
from dez.http.server.shield import Shield
|
|
4
|
-
from dez.logging import get_logger_getter
|
|
5
|
-
from cantools import config
|
|
6
|
-
from .daemons import Web, Admin
|
|
7
|
-
from .response import Response
|
|
8
|
-
from .cron import Cron
|
|
9
|
-
from cantools import config, __version__
|
|
10
|
-
from ..util import *
|
|
11
|
-
from ...util import read, write, log as syslog
|
|
12
|
-
|
|
13
|
-
logger_getter = get_logger_getter("httpd", syslog, config.log.allow)
|
|
14
|
-
CTR = None
|
|
15
|
-
|
|
16
|
-
class DController(SocketController):
|
|
17
|
-
def __init__(self, *args, **kwargs):
|
|
18
|
-
self.logger = logger_getter("Controller")
|
|
19
|
-
SocketController.__init__(self, *args, **kwargs)
|
|
20
|
-
self.handlers = {}
|
|
21
|
-
self.modules = {}
|
|
22
|
-
self.blcount = 0
|
|
23
|
-
self.blchunk = getattr(config.web.shield, "chunk", 5)
|
|
24
|
-
self.logger.info("cantools: %s"%(__version__,))
|
|
25
|
-
self.logger.info("Python: %s"%(sys.version.split(' ')[0],))
|
|
26
|
-
self.logger.info("System: " + " > ".join([part for part in platform.uname() if part]))
|
|
27
|
-
|
|
28
|
-
def _respond(self, resp, *args, **kwargs):
|
|
29
|
-
if resp == "nothread": # "on start nothread" cron
|
|
30
|
-
kwargs["noLoad"] = True
|
|
31
|
-
elif resp: # regular request
|
|
32
|
-
kwargs["response"] = resp
|
|
33
|
-
localvars.response = resp
|
|
34
|
-
else: # regular cron
|
|
35
|
-
kwargs["noLoad"] = True
|
|
36
|
-
kwargs["threaded"] = True
|
|
37
|
-
do_respond(*args, **kwargs)
|
|
38
|
-
|
|
39
|
-
def register_handler(self, args, kwargs):
|
|
40
|
-
self.logger.info("register handler: %s"%(self.curpath,))
|
|
41
|
-
self.handlers[self.curpath] = lambda resp : self._respond(resp, *args, **kwargs)
|
|
42
|
-
|
|
43
|
-
def trigger_handler(self, rule, target, req=None, option=None):
|
|
44
|
-
self.curpath = rule
|
|
45
|
-
if rule not in self.handlers:
|
|
46
|
-
if target in self.modules:
|
|
47
|
-
self.logger.info("linking module: %s"%(target,))
|
|
48
|
-
self.handlers[rule] = self.modules[target]
|
|
49
|
-
else:
|
|
50
|
-
self.logger.info("importing module: %s"%(target,))
|
|
51
|
-
__import__(target)
|
|
52
|
-
self.modules[target] = self.handlers[rule]
|
|
53
|
-
self.handlers[rule](req and Response(req) or option)
|
|
54
|
-
|
|
55
|
-
def blup(self):
|
|
56
|
-
wcfg = config.web
|
|
57
|
-
bl = wcfg.blacklist.obj()
|
|
58
|
-
blen = len(bl.keys())
|
|
59
|
-
self.logger.warn("saving %s IPs in black.list"%(blen,))
|
|
60
|
-
write(bl, "black.list", isjson=True)
|
|
61
|
-
if wcfg.report and self.blcount != blen:
|
|
62
|
-
self.blcount = blen
|
|
63
|
-
if not blen % self.blchunk:
|
|
64
|
-
from cantools.web import email_admins
|
|
65
|
-
email_admins("sketch IPs blacklisted", "sketch count: %s"%(blen,))
|
|
66
|
-
wcfg.blacklister and wcfg.blacklister.update(bl)
|
|
67
|
-
|
|
68
|
-
class PaperShield(object):
|
|
69
|
-
def __init__(self):
|
|
70
|
-
self.logger = logger_getter("PaperShield")
|
|
71
|
-
self.default = { "reason": "I'm just a paper shield!" }
|
|
72
|
-
self.ips = {}
|
|
73
|
-
|
|
74
|
-
def __call__(self, path, ip, fspath=False, count=True):
|
|
75
|
-
self.logger.access('NOOP > paperShield("%s", "%s", fspath=%s, count=%s)'%(path, ip, fspath, count))
|
|
76
|
-
|
|
77
|
-
def suss(self, ip, reason):
|
|
78
|
-
self.logger.access("suss(%s) -> %s"%(ip, reason))
|
|
79
|
-
self.ips[ip] = { "reason": reason }
|
|
80
|
-
|
|
81
|
-
def ip(self, ip):
|
|
82
|
-
return self.ips.get(ip, self.default)
|
|
83
|
-
|
|
84
|
-
def setBlacklist():
|
|
85
|
-
bl = {}
|
|
86
|
-
for preban in config.web.blacklist:
|
|
87
|
-
bl[preban] = "config ban"
|
|
88
|
-
if os.path.isfile("black.list"):
|
|
89
|
-
try:
|
|
90
|
-
bsaved = read("black.list", isjson=True)
|
|
91
|
-
except: # old style
|
|
92
|
-
bsaved = {}
|
|
93
|
-
for line in read("black.list", lines=True):
|
|
94
|
-
bsaved[line.strip()] = "legacy ban"
|
|
95
|
-
bsaved and bl.update(bsaved)
|
|
96
|
-
config.web.update("blacklist", bl)
|
|
97
|
-
|
|
98
|
-
def getController():
|
|
99
|
-
global CTR
|
|
100
|
-
if not CTR:
|
|
101
|
-
# controller
|
|
102
|
-
CTR = DController()
|
|
103
|
-
|
|
104
|
-
shield = None
|
|
105
|
-
shfg = config.web.shield
|
|
106
|
-
if shfg: # web/admin share shield and blacklist
|
|
107
|
-
setBlacklist()
|
|
108
|
-
shield = Shield(config.web.blacklist, logger_getter, CTR.blup,
|
|
109
|
-
getattr(shfg, "limit", 400),
|
|
110
|
-
getattr(shfg, "interval", 2))
|
|
111
|
-
config.web.update("shield", shield or PaperShield())
|
|
112
|
-
mempad = config.mempad
|
|
113
|
-
|
|
114
|
-
# web
|
|
115
|
-
CTR.web = CTR.register_address(config.web.host,
|
|
116
|
-
config.web.port, dclass=daemon_wrapper(Web, logger_getter, shield, mempad))
|
|
117
|
-
CTR.web.controller = CTR
|
|
118
|
-
|
|
119
|
-
# admin
|
|
120
|
-
config.admin.update("pw",
|
|
121
|
-
config.cache("admin password? ", overwrite=config.newpass))
|
|
122
|
-
CTR.admin = CTR.register_address(config.admin.host,
|
|
123
|
-
config.admin.port, dclass=daemon_wrapper(Admin, logger_getter, shield, mempad))
|
|
124
|
-
CTR.admin.controller = CTR
|
|
125
|
-
|
|
126
|
-
# cron
|
|
127
|
-
Cron(CTR, logger_getter)
|
|
128
|
-
|
|
129
|
-
return CTR
|