ct 0.10.8.114__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.
Files changed (55) hide show
  1. cantools/__init__.py +24 -0
  2. cantools/_db.py +142 -0
  3. cantools/_memcache.py +76 -0
  4. cantools/_pay.py +46 -0
  5. cantools/admin.py +31 -0
  6. cantools/cfg.py +347 -0
  7. cantools/config.py +131 -0
  8. cantools/db/__init__.py +18 -0
  9. cantools/db/admin.py +27 -0
  10. cantools/db/gae/__init__.py +0 -0
  11. cantools/db/gae/model.py +127 -0
  12. cantools/db/gae/properties.py +35 -0
  13. cantools/db/wp.py +99 -0
  14. cantools/geo.py +188 -0
  15. cantools/hooks.py +13 -0
  16. cantools/scripts/__init__.py +0 -0
  17. cantools/scripts/bench.py +167 -0
  18. cantools/scripts/builder.py +272 -0
  19. cantools/scripts/deploy.py +154 -0
  20. cantools/scripts/doc.py +239 -0
  21. cantools/scripts/index.py +226 -0
  22. cantools/scripts/init.py +345 -0
  23. cantools/scripts/migrate.py +593 -0
  24. cantools/scripts/pubsub/__init__.py +28 -0
  25. cantools/scripts/pubsub/actor.py +13 -0
  26. cantools/scripts/pubsub/bots.py +143 -0
  27. cantools/scripts/pubsub/channel.py +85 -0
  28. cantools/scripts/pubsub/ps.py +145 -0
  29. cantools/scripts/pubsub/user.py +51 -0
  30. cantools/scripts/start.py +53 -0
  31. cantools/scripts/util.py +24 -0
  32. cantools/util/__init__.py +78 -0
  33. cantools/util/admin.py +620 -0
  34. cantools/util/data.py +109 -0
  35. cantools/util/media.py +303 -0
  36. cantools/util/package.py +125 -0
  37. cantools/util/system.py +73 -0
  38. cantools/web/__init__.py +9 -0
  39. cantools/web/dez_server/__init__.py +1 -0
  40. cantools/web/dez_server/controller.py +129 -0
  41. cantools/web/dez_server/cron.py +115 -0
  42. cantools/web/dez_server/daemons.py +64 -0
  43. cantools/web/dez_server/mail.py +24 -0
  44. cantools/web/dez_server/response.py +63 -0
  45. cantools/web/dez_server/routes.py +21 -0
  46. cantools/web/dez_server/server.py +229 -0
  47. cantools/web/dez_server/sms.py +12 -0
  48. cantools/web/gae_server.py +68 -0
  49. cantools/web/util.py +552 -0
  50. ct-0.10.8.114.dist-info/LICENSE +9 -0
  51. ct-0.10.8.114.dist-info/METADATA +25 -0
  52. ct-0.10.8.114.dist-info/RECORD +55 -0
  53. ct-0.10.8.114.dist-info/WHEEL +5 -0
  54. ct-0.10.8.114.dist-info/entry_points.txt +10 -0
  55. ct-0.10.8.114.dist-info/top_level.txt +1 -0
@@ -0,0 +1,143 @@
1
+ import datetime, json, os
2
+ from cantools import config
3
+ from cantools.util import log, write
4
+ from cantools.web import fetch, send_mail
5
+ from .actor import Actor
6
+ try:
7
+ import psutil
8
+ except ImportError as e:
9
+ pass # google crap engine (get it if you need it!)
10
+ from six import with_metaclass
11
+
12
+ class BotMeta(type):
13
+ def __new__(cls, name, bases, attrs):
14
+ bc = type.__new__(cls, name, bases, attrs)
15
+ if name != "Bot":
16
+ name != "Monitor" and log("Initializing Bot Class: %s"%(name,), important=True)
17
+ config.pubsub.bots.update(name.lower(), bc)
18
+ return bc
19
+
20
+ class Bot(with_metaclass(BotMeta, Actor)):
21
+ num = 0
22
+ def __init__(self, server, channel, name=None):
23
+ Bot.num += 1
24
+ self.name = name or (self.__class__.__name__ + str(Bot.num))
25
+ self.server = server
26
+ self.channel = channel # often we only care about one channel
27
+ self.channels = set()
28
+ self._set_defaults()
29
+ log("Bot Spawned: '%s'"%(self.name,), 2)
30
+ channel.join(self)
31
+ self.server.bots[self.name] = self
32
+
33
+ def pub(self, message):
34
+ self.server.publish({
35
+ "message": message,
36
+ "channel": self.channel.name
37
+ }, self)
38
+
39
+ def write(self, obj): # receive message from channel
40
+ getattr(self, "on_%s"%(obj["action"],))(obj["data"])
41
+
42
+ def _default_handler(self, action):
43
+ def _h(*args):
44
+ log('Bot %s handling %s: "%s"'%(self.name, action, json.dumps(args)), 3)
45
+ return _h
46
+
47
+ def _set_defaults(self):
48
+ for action in ["channel", "publish", "subscribe", "unsubscribe", "pm", "error", "meta"]:
49
+ hname = "on_%s"%(action,)
50
+ if not hasattr(self, hname):
51
+ setattr(self, hname, self._default_handler(action))
52
+
53
+ class Monitor(Bot):
54
+ def __init__(self, server, channel, name="monitor"): # only one monitor
55
+ import event # here for google crap engine
56
+ self.current = {}
57
+ self.alert = {}
58
+ Bot.__init__(self, server, channel, name)
59
+ event.timeout(config.admin.monitor.interval, self._tick)
60
+
61
+ def _datedir(self):
62
+ n = datetime.datetime.now()
63
+ lp = os.path.join("logs", "monitor")
64
+ yp = os.path.join(lp, str(n.year))
65
+ mp = os.path.join(yp, str(n.month))
66
+ dp = os.path.join(mp, str(n.day))
67
+ if not os.path.isdir(lp):
68
+ os.mkdir(lp)
69
+ if not os.path.isdir(yp):
70
+ os.mkdir(yp)
71
+ if not os.path.isdir(mp):
72
+ os.mkdir(mp)
73
+ if not os.path.isdir(dp):
74
+ os.mkdir(dp)
75
+ return os.path.join(dp, str(n.hour))
76
+
77
+ def log(self, data):
78
+ self.pub(data)
79
+ if config.admin.monitor.log:
80
+ write(data, self._datedir(), True, append=True, newline=True)
81
+
82
+ def _cpu(self):
83
+ c = self.current["cpu"] = psutil.cpu_percent()
84
+ if self.alert.get("cpu"):
85
+ if c < config.admin.monitor.thresholds.cpu:
86
+ del self.alert["cpu"]
87
+ log("CPU calmed down")
88
+ send_mail(config.admin.contacts, subject="High CPU", body="just ended")
89
+ else:
90
+ if c >= config.admin.monitor.thresholds.cpu:
91
+ self.alert["cpu"] = True
92
+ log("CPU just started going crazy")
93
+ send_mail(config.admin.contacts, subject="High CPU", body="just started")
94
+
95
+ def _tick(self):
96
+ self._cpu()
97
+ dioc = psutil.disk_io_counters()
98
+ nioc = psutil.net_io_counters()
99
+ dmon = fetch(config.admin.host, "/_report",
100
+ config.admin.port, True, protocol=config.admin.protocol)
101
+ data = {
102
+ "gc": dmon["gc"],
103
+ "cpu": self.current["cpu"],
104
+ "read": dioc.read_time,
105
+ "write": dioc.write_time,
106
+ "sent": nioc.bytes_sent,
107
+ "recv": nioc.bytes_recv,
108
+ "process_memory": dmon["mem"],
109
+ "threads": dmon["threads"],
110
+ "stack_frames": dmon["stack_frames"],
111
+ "virtual_memory": psutil.virtual_memory().percent,
112
+ "swap_memory": psutil.swap_memory().percent,
113
+ "connections": len(psutil.net_connections()),
114
+ "web_connections": dmon["web"]["connections"],
115
+ "admin_connections": dmon["admin"]["connections"],
116
+ "web_requests": dmon["web"]["requests"],
117
+ "admin_requests": dmon["admin"]["requests"],
118
+ "totals": {
119
+ "web": {
120
+ "connections": dmon["web"]["total_connections"],
121
+ "requests": dmon["web"]["total_requests"],
122
+ "rolls": dmon["web"]["rolls"]
123
+ },
124
+ "admin": {
125
+ "connections": dmon["admin"]["total_connections"],
126
+ "requests": dmon["admin"]["total_requests"],
127
+ "rolls": dmon["admin"]["rolls"]
128
+ }
129
+ },
130
+ "devices": {
131
+ "web": dmon["web"]["devices"],
132
+ "admin": dmon["admin"]["devices"]
133
+ },
134
+ "ips": {
135
+ "web": dmon["web"]["ips"],
136
+ "admin": dmon["admin"]["ips"]
137
+ }
138
+ }
139
+ if config.admin.monitor.proxy:
140
+ data["ips"]["proxy"] = fetch(config.admin.host, "/_report",
141
+ config.admin.monitor.proxy, True)["ips"]
142
+ self.log(data)
143
+ return True
@@ -0,0 +1,85 @@
1
+ from cantools import config
2
+
3
+ def diffmerge(orig, diff): # move this somewhere else....
4
+ for k, v in diff.items():
5
+ if type(v) == dict:
6
+ if k not in orig:
7
+ orig[k] = {}
8
+ diffmerge(orig[k], v)
9
+ else:
10
+ orig[k] = v
11
+
12
+ class PubSubChannel(object):
13
+ def __init__(self, name, server):
14
+ self._log = server._log
15
+ self.server = server
16
+ self.name = name
17
+ self.users = set()
18
+ self.history = []
19
+ self.metadata = {}
20
+ self._log('NEW CHANNEL: "%s"'%(name,), 1, True)
21
+
22
+ def data(self):
23
+ return {
24
+ "name": self.name,
25
+ "users": [u.name for u in self.users]
26
+ }
27
+
28
+ def _broadcast(self, obj):
29
+ for user in self.users:
30
+ if config.pubsub.echo or user.name != obj["data"]["user"]:
31
+ user.write(obj)
32
+ for user in list(self.server.admins.values()):
33
+ user.write(obj)
34
+
35
+ def meta(self, subobj):
36
+ subobj["channel"] = self.name
37
+ self._broadcast({
38
+ "action": "meta",
39
+ "data": subobj
40
+ })
41
+
42
+ def chmeta(self, subobj):
43
+ subobj["channel"] = self.name # _usually_ unnecessary
44
+ diffmerge(self.metadata, subobj["meta"])
45
+ # self.metadata = subobj["meta"]
46
+ self._broadcast({
47
+ "action": "chmeta",
48
+ "data": subobj
49
+ })
50
+
51
+ def write(self, subobj):
52
+ subobj["channel"] = self.name
53
+ obj = {
54
+ "action": "publish",
55
+ "data": subobj
56
+ }
57
+ self._broadcast(obj)
58
+ self.history.append(subobj)
59
+ self.history = self.history[-config.pubsub.history:]
60
+
61
+ def leave(self, user):
62
+ if user in self.users:
63
+ self.users.remove(user)
64
+ user.leave(self)
65
+ self._broadcast({
66
+ "action": "unsubscribe",
67
+ "data": {
68
+ "user": user.name,
69
+ "channel": self.name
70
+ }
71
+ })
72
+
73
+ def join(self, user):
74
+ data = {
75
+ "user": user.name,
76
+ "channel": self.name
77
+ }
78
+ if config.pubsub.meta:
79
+ data["meta"] = user.meta
80
+ self._broadcast({
81
+ "action": "subscribe",
82
+ "data": data
83
+ })
84
+ self.users.add(user)
85
+ user.join(self)
@@ -0,0 +1,145 @@
1
+ import os, sys
2
+ from base64 import b64encode
3
+ from dez.network.websocket import WebSocketDaemon
4
+ from cantools import config
5
+ from cantools.util import log, set_log
6
+ from .user import PubSubUser
7
+ from .channel import PubSubChannel
8
+
9
+ class PubSub(WebSocketDaemon):
10
+ def __init__(self, *args, **kwargs):
11
+ if config.pubsub.log:
12
+ set_log(os.path.join("logs", config.pubsub.log))
13
+ kwargs["b64"] = config.pubsub.b64
14
+ kwargs["isJSON"] = True
15
+ kwargs["report_cb"] = self._log
16
+ kwargs["cb"] = self.connect
17
+ kwargs["certfile"] = config.ssl.pubsubcert or config.ssl.certfile
18
+ kwargs["keyfile"] = config.ssl.pubsubkey or config.ssl.keyfile
19
+ kwargs["cacerts"] = config.ssl.pubsubcacerts or config.ssl.cacerts
20
+ if "silent" in kwargs:
21
+ self.silent = kwargs["silent"]
22
+ del kwargs["silent"]
23
+ else:
24
+ self.silent = False
25
+ WebSocketDaemon.__init__(self, *args, **kwargs)
26
+ self.bots = {}
27
+ self.users = {}
28
+ self.admins = {}
29
+ self.channels = {}
30
+ self.loadBots()
31
+ config.admin.update("pw", config.cache("admin password? "))
32
+ self._log("Initialized PubSub Server @ %s:%s"%(self.hostname, self.port), important=True)
33
+
34
+ def loadBots(self):
35
+ self._log("Loading Bots: %s"%(config.pubsub.botnames,))
36
+ sys.path.insert(0, "bots") # for dynamically loading bot modules
37
+ for bname in config.pubsub.botnames:
38
+ self._log("Importing Bot: %s"%(bname,), 2)
39
+ __import__(bname) # config modified in pubsub.bots.BotMeta.__new__()
40
+
41
+ def newUser(self, u):
42
+ if not u.name: # on dc?
43
+ self._log("user disconnected without registering")
44
+ u.conn.close()
45
+ elif u.name.startswith("__admin__") and u.name.endswith(b64encode(config.admin.pw.encode()).decode()):
46
+ self.admins[u.name] = u
47
+ self.snapshot(u)
48
+ else:
49
+ self.users[u.name] = u
50
+
51
+ def client(self, name):
52
+ return self.users.get(name) or self.bots.get(name) or self.admins.get(name)
53
+
54
+ def snapshot(self, admin):
55
+ admin.write({
56
+ "action": "snapshot",
57
+ "data": {
58
+ "bots": [b.data() for b in list(self.bots.values())],
59
+ "users": [u.data() for u in list(self.users.values())],
60
+ "admins": [a.data() for a in list(self.admins.values())],
61
+ "channels": [c.data() for c in list(self.channels.values())]
62
+ }
63
+ })
64
+
65
+ def pm(self, data, user):
66
+ recipient = self.client(data["user"])
67
+ if not recipient:
68
+ return user._error("no such user!")
69
+ recipient.write({
70
+ "action": "pm",
71
+ "data": {
72
+ "user": user.name,
73
+ "message": data["message"]
74
+ }
75
+ })
76
+
77
+ def subscribe(self, channel, user):
78
+ self._check_channel(channel)
79
+ chan = self.channels[channel]
80
+ chan.join(user)
81
+ self._log('SUBSCRIBE: "%s" -> "%s"'%(user.name, channel), 2)
82
+ data = {
83
+ "channel": channel,
84
+ "presence": [u.name for u in chan.users],
85
+ "history": chan.history
86
+ }
87
+ if config.pubsub.meta:
88
+ data["meta"] = {
89
+ "channel": chan.metadata,
90
+ "users": [u.meta for u in chan.users]
91
+ }
92
+ user.write({
93
+ "action": "channel",
94
+ "data": data
95
+ })
96
+
97
+ def unsubscribe(self, channel, user):
98
+ if self._check_channel(channel, True) and user in self.channels[channel].users:
99
+ self.channels[channel].leave(user)
100
+ self._log('UNSUBSCRIBE: "%s" -> "%s"'%(user.name, channel), 2)
101
+ else:
102
+ self._log('FAILED UNSUBSCRIBE: "%s" -> "%s"'%(user.name, channel), 2)
103
+
104
+ def meta(self, data, user):
105
+ channel = data["channel"]
106
+ self._check_channel(channel)
107
+ user.meta = data["meta"]
108
+ self.channels[channel].meta({
109
+ "meta": user.meta,
110
+ "user": user.name
111
+ })
112
+
113
+ def chmeta(self, data, user):
114
+ channel = data["channel"]
115
+ self._check_channel(channel)
116
+ self.channels[channel].chmeta(data)
117
+
118
+ def publish(self, data, user):
119
+ channel = data["channel"]
120
+ self._check_channel(channel)
121
+ self.channels[channel].write({
122
+ "message": data["message"],
123
+ "user": user.name
124
+ })
125
+
126
+ def _new_channel(self, channel):
127
+ self.channels[channel] = PubSubChannel(channel, self)
128
+ # check for bots...
129
+ botname = channel.split("_")[0]
130
+ if botname in config.pubsub.bots:
131
+ self._log("Generating Bot '%s' for channel '%s'"%(botname, channel), 2)
132
+ config.pubsub.bots[botname](self, self.channels[channel])
133
+
134
+ def _check_channel(self, channel, justBool=False):
135
+ condition = channel in self.channels
136
+ if not condition and not justBool:
137
+ self._new_channel(channel)
138
+ return condition
139
+
140
+ def _log(self, data, level=0, important=False):
141
+ if not self.silent:
142
+ log(data, level=level, important=important)
143
+
144
+ def connect(self, conn):
145
+ PubSubUser(conn, self, self._log)
@@ -0,0 +1,51 @@
1
+ from datetime import datetime
2
+ from .actor import Actor
3
+
4
+ class PubSubUser(Actor):
5
+ id = 0
6
+ def __init__(self, conn, server, logger):
7
+ PubSubUser.id += 1
8
+ self.id = PubSubUser.id
9
+ self.conn = conn
10
+ self.server = server
11
+ self._log = logger
12
+ self.channels = set()
13
+ self.conn.set_cb(self._register)
14
+ self._log('NEW CONNECTION (%s)'%(self.id,), 1, True)
15
+
16
+ def write(self, data):
17
+ data["data"]["datetime"] = str(datetime.utcnow())
18
+ self.conn.write(data)
19
+
20
+ def _read(self, obj):
21
+ if obj["action"] == "close":
22
+ return self.conn.close()
23
+ getattr(self.server, obj["action"])(obj["data"], self)
24
+
25
+ def _close(self):
26
+ if self.name in self.server.users:
27
+ del self.server.users[self.name]
28
+ elif self.name in self.server.admins:
29
+ del self.server.admins[self.name]
30
+ for channel in list(self.channels):
31
+ channel.leave(self)
32
+
33
+ def _error(self, message):
34
+ self.write({
35
+ "action": "error",
36
+ "data": {
37
+ "message": message
38
+ }
39
+ })
40
+
41
+ def _register(self, obj):
42
+ name = obj.get("data")
43
+ if not name:
44
+ self._log("no name provided! assigning index (%s)."%(self.id,))
45
+ name = str(self.id)
46
+ self._log('REGISTER: "%s"'%(name,), 1, True)
47
+ self.name = name
48
+ self.meta = obj.get("meta")
49
+ self.server.newUser(self)
50
+ self.conn.set_cb(self._read)
51
+ self.conn.set_close_cb(self._close)
@@ -0,0 +1,53 @@
1
+ """
2
+ ### Usage: ctstart [--web_backend=BACKEND] [--port=PORT] [--datastore=DS_PATH]
3
+
4
+ ### Options:
5
+ -h, --help show this help message and exit
6
+ -w WEB_BACKEND, --web_backend=WEB_BACKEND
7
+ web backend. options: dez, gae. (default: dez)
8
+ -p PORT, --port=PORT select your port (default=8080)
9
+ -a ADMIN_PORT, --admin_port=ADMIN_PORT
10
+ select your port (default=8002)
11
+ -d DATASTORE, --datastore=DATASTORE
12
+ select your datastore file (default=sqlite:///data.db)
13
+ -o, --overwrite_password
14
+ overwrite admin password (default=False)
15
+ """
16
+
17
+ from optparse import OptionParser
18
+ from cantools import config
19
+ from cantools.util import error
20
+
21
+ def go():
22
+ parser = OptionParser("ctstart [--web_backend=BACKEND] [--port=PORT] [--datastore=DS_PATH]")
23
+ parser.add_option("-w", "--web_backend", dest="web_backend", default=config.web.server,
24
+ help="web backend. options: dez, gae. (default: %s)"%(config.web.server,))
25
+ parser.add_option("-p", "--port", dest="port", default=config.web.port,
26
+ help="select your port (default=%s)"%(config.web.port,))
27
+ parser.add_option("-a", "--admin_port", dest="admin_port", default=config.admin.port,
28
+ help="select your port (default=%s)"%(config.admin.port,))
29
+ parser.add_option("-d", "--datastore", dest="datastore", default=config.db.main,
30
+ help="select your datastore file (default=%s)"%(config.db.main,))
31
+ parser.add_option("-o", "--overwrite_password", action="store_true", dest="overwrite_password",
32
+ default=False, help="overwrite admin password (default=False)")
33
+ options, args = parser.parse_args()
34
+
35
+ config.web.update("port", int(options.port))
36
+ config.admin.update("port", int(options.admin_port))
37
+ if options.overwrite_password:
38
+ config.update("newpass", True)
39
+
40
+ if options.web_backend == "gae":
41
+ import subprocess
42
+ cmd = 'dev_appserver.py . --host=%s --port=%s --admin_port=%s --datastore_path=%s'%(config.web.host,
43
+ options.port, options.admin_port, options.datastore)
44
+ print(cmd)
45
+ subprocess.call(cmd, shell=True)
46
+ elif options.web_backend == "dez":
47
+ from cantools.web import run_dez_webserver
48
+ run_dez_webserver()
49
+ else:
50
+ error("invalid web_backend: %s"%(options.web_backend,))
51
+
52
+ if __name__ == "__main__":
53
+ go()
@@ -0,0 +1,24 @@
1
+ """
2
+ ### Usage: ctutil [module] [function] [..parameters]
3
+
4
+ ### Options:
5
+ -h, --help show this help message and exit
6
+ """
7
+
8
+ from optparse import OptionParser
9
+ from cantools import util
10
+ log = util.log
11
+ error = util.error
12
+
13
+ def run():
14
+ parser = OptionParser("ctutil [module] [function] [..parameters]")
15
+ args = parser.parse_args()[1]
16
+ args or error("what module?")
17
+ module = args.pop(0)
18
+ args or error("what function?")
19
+ function = args.pop(0)
20
+ #log("calling %s.%s(%s)"%(module, function, ", ".join(args)))
21
+ getattr(getattr(util, module), function)(*args)
22
+
23
+ if __name__ == "__main__":
24
+ run()
@@ -0,0 +1,78 @@
1
+ import os, sys
2
+ from fyg.util import read, write, writejson, confirm, batch, indir, rm # backwards compat
3
+ from fyg.util.reporting import set_log, close_log, log, set_error, error, start_timer, end_timer
4
+ from .system import cp, sym, mkdir, sed, py, pymod, cmd, output
5
+ from .data import getxls, gettsv, getcsv, getcsv_from_data, flatten, arr2csv, token
6
+ from .media import transcode, segment, hlsify, shouldMoveMoov, crop, resizep2, thumb, dlp, repitch
7
+ from .admin import certs, screener
8
+ from .apper import android
9
+ from .ai import tox, vox, tellme
10
+
11
+ def init_basic():
12
+ os.path.isdir("emails") and sys.path.append("emails")
13
+
14
+ def init_rel():
15
+ import rel
16
+ from rel.util import loudListen
17
+ from cantools import config
18
+ rcfg = config.rel
19
+ if rcfg.sleep:
20
+ rel.set_sleep(rcfg.sleep)
21
+ if rcfg.turbo:
22
+ rel.set_turbo(rcfg.turbo)
23
+ rel.set_verbose(rcfg.verbose)
24
+ loudListen(rcfg.loudlisten)
25
+
26
+ def init_gae():
27
+ try:
28
+ from google import appengine
29
+ except: # running outside of dev_appserver
30
+ gae_p = None
31
+ for p in os.environ["PATH"].split(":"):
32
+ if p.endswith("google_appengine"):
33
+ gae_p = p
34
+ break
35
+ if not gae_p:
36
+ from cantools import config
37
+ gae_p = config.cache("\n".join([
38
+ "can't find google - please enter the path to google_appengine",
39
+ " - if you DON'T have a copy, get one here:",
40
+ " https://cloud.google.com/appengine/downloads#Google_App_Engine_SDK_for_Python",
41
+ " - if you DO have a copy, enter the path to it below",
42
+ "so what's the path? "]), password=False)
43
+ if not gae_p:
44
+ error("can't find google_appengine in path! please add and retry.")
45
+ sys.path.append(gae_p)
46
+ if 'google' in sys.modules:
47
+ del sys.modules['google']
48
+ import dev_appserver
49
+ dev_appserver.fix_sys_path()
50
+ sys.path.insert(0, ".")
51
+
52
+ # accesses ct gae app running locally or elsewhere (other than app engine production, aka gcloud)
53
+ def init_ndb():
54
+ from cantools import config
55
+ from google.appengine.ext.remote_api import remote_api_stub
56
+ remote_api_stub.ConfigureRemoteDatastore("", "/remote_api",
57
+ lambda : ("user@email.com", "password"),
58
+ servername="%s:%s"%(config.web.host, config.web.port))
59
+
60
+ # these are essentially not recommended. google's
61
+ # rules for operating outside of their native environment
62
+ # are crappy and generally get worse with time. these
63
+ # _sort of_ work, but easily get messed up. it's whatever.
64
+ def init_ndb_cloud(url=None):
65
+ from cantools import config
66
+ from google.appengine.ext.remote_api import remote_api_stub
67
+ if not url:
68
+ app_id = read("app.yaml", True)[0].split(": ")[1].strip()
69
+ url = "%s.appspot.com"%(app_id,)
70
+ remote_api_stub.ConfigureRemoteApiForOAuth(url, "/_ah/remote_api")
71
+
72
+ def init_ndb_depped(datastore_file="/dev/null"):
73
+ from google.appengine.api import apiproxy_stub_map, datastore_file_stub
74
+ app_id = read("app.yaml", True)[0].split(": ")[1].strip()
75
+ os.environ['APPLICATION_ID'] = app_id
76
+ apiproxy_stub_map.apiproxy = apiproxy_stub_map.APIProxyStubMap()
77
+ stub = datastore_file_stub.DatastoreFileStub(app_id, datastore_file, '/')
78
+ apiproxy_stub_map.apiproxy.RegisterStub('datastore_v3', stub)