ct 0.10.8.115__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 CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.10.8.115"
1
+ __version__ = "0.10.8.116"
2
2
 
3
3
  from . import util, hooks
4
4
  from . import config as cfgmod
cantools/config.py CHANGED
@@ -40,6 +40,9 @@ gcpath = os.path.join(os.path.expanduser("~"), "ct.cfg")
40
40
  if os.path.isfile(gcpath):
41
41
  print("loading global configuration at: %s"%(gcpath,))
42
42
  lines = read(gcpath, True) + lines
43
+ if os.path.isfile("extra.cfg"):
44
+ print("loading extra configuration at: extra.cfg")
45
+ lines = lines + read("extra.cfg", True)
43
46
  for line in lines:
44
47
  if line.startswith("#"):
45
48
  continue
cantools/util/admin.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import os, sys, rel, time, datetime
2
+ from fyg.util import pcount, pcheck, pkill
2
3
  from cantools.util import cmd, output, error, log, set_log, close_log, read, write, confirm, rm
3
4
 
4
5
  coremods = ["screen", "ctstart", "ctpubsub", "ctutil", "ctinit", "dez_reverse_proxy", "dez_websocket_proxy"]
@@ -65,33 +66,6 @@ def certs(dpath="/root", sname=None):
65
66
  log("goodbye")
66
67
  close_log()
67
68
 
68
- def pcount(pname):
69
- log("checking count: %s"%(pname,), important=True)
70
- num = int(output("ps -ef | grep %s | egrep -v 'screener|pcount|grep' | wc -l"%(pname,)))
71
- log("%s count: %s"%(pname, num), 1)
72
- return num
73
-
74
- def pcheck(pname, target, starter):
75
- if target and pcount(pname) != target:
76
- log("not enough %s processes - restarting screen!"%(pname,), 1)
77
- log(output("screen -Q windows"), important=True)
78
- cmd("killall screen; %s"%(starter,))
79
- return True
80
-
81
- def pkill(pname, force=False):
82
- pblock = output("ps -ef | grep %s | egrep -v 'screener|pkill|grep'"%(pname,))
83
- if not pblock:
84
- log("no '%s' processes!"%(pname,))
85
- else:
86
- plines = pblock.split("\n")
87
- log("found %s '%s' processes"%(len(plines), pname), important=True)
88
- if plines:
89
- procs = [[w for w in line.split(" ") if w][1] for line in plines]
90
- if force or confirm("kill %s '%s' processes"%(len(procs), pname)):
91
- for proc in procs:
92
- cmd("kill -9 %s"%(proc,))
93
- log("goodbye")
94
-
95
69
  def binpath(bpath="/usr/bin/"):
96
70
  log("checking %s core modules"%(len(coremods),), important=True)
97
71
  missings = []
@@ -0,0 +1,8 @@
1
+ from .tox import tox, g4chat, g4image, fzn, duck, pb
2
+ from .vox import vox, kvoices
3
+
4
+ def tellme(prompt, voice="random", identity="gpt-4o-mini", filename="tts", unsaid=False, silent=False):
5
+ print("tellme(%s, %s, %s)"%(voice, identity, filename), prompt)
6
+ resp = tox(prompt, identity)
7
+ unsaid or vox(resp, voice, filename=filename, say=not silent)
8
+ return resp
@@ -0,0 +1,15 @@
1
+ from .duck import duck # not currently working :'(
2
+ from .g4free import g4chat, g4image, gchatters
3
+ from .fzn import fzn
4
+
5
+ # pb
6
+ def pb(question, botname, appid, userkey):
7
+ from pb_py import main as PB
8
+ resp = PB.talk(userkey, appid, "aiaas.pandorabots.com", botname, question)["response"]
9
+ return resp.split("[URL]")[0]
10
+
11
+ # wrapper
12
+ def tox(statement, identity="Anonymous", name=None, mood=None, asker=None, options=None):
13
+ if identity in gchatters:
14
+ return g4chat(statement, identity)
15
+ return fzn(statement, identity, name, mood, asker, options)
@@ -0,0 +1,80 @@
1
+ import random
2
+ from datetime import datetime
3
+
4
+ def nosay():
5
+ return random.choice([
6
+ "i'm confused",
7
+ "you broke me",
8
+ "you're killing me bro",
9
+ "that question ruined me",
10
+ "your words somehow fried my circuits",
11
+ "i literally don't know how to answer that"
12
+ ])
13
+
14
+ def notyet():
15
+ return random.choice([
16
+ "slow down",
17
+ "not so fast",
18
+ "wait a minute",
19
+ "take your time",
20
+ "slow your roll",
21
+ "i need a moment",
22
+ "hold your horses"
23
+ ])
24
+
25
+ # ddg
26
+ DDGAI = {
27
+ "bot": None,
28
+ "last": None
29
+ }
30
+ DUX = ["gpt-4o-mini", "llama-3.3-70b", "claude-3-haiku", "o3-mini", "mistral-small-3"]
31
+ OLDUX = ["o3-mini", "gpt-4o-mini", "claude-3-haiku", "llama-3.1-70b", "mixtral-8x7b"]
32
+ delimiases = {
33
+ "False": False,
34
+ True: "\n",
35
+ "True": "\n",
36
+ "LINE": "\n",
37
+ "PARAGRAPH": "\n",
38
+ "SENTENCE": ".",
39
+ "PHRASE": [".", "!", "?"]
40
+ }
41
+
42
+ def ddgai():
43
+ if not DDGAI["bot"]:
44
+ from duckai import DuckAI
45
+ DDGAI["bot"] = DuckAI()
46
+ return DDGAI["bot"]
47
+
48
+ def toosoon():
49
+ now = datetime.now()
50
+ if DDGAI["last"] and (now - DDGAI["last"]).seconds < 15:
51
+ return True
52
+ DDGAI["last"] = now
53
+
54
+ def duck(prompt, model="gpt-4o-mini", shorten=False, strip=False, timeout=30):
55
+ if toosoon():
56
+ return notyet()
57
+ try:
58
+ resp = ddgai().chat(prompt, model, int(timeout))
59
+ except:
60
+ resp = nosay()
61
+ print(resp)
62
+ if shorten in delimiases:
63
+ shorten = delimiases[shorten]
64
+ if shorten:
65
+ if type(shorten) is not list:
66
+ shorten = [shorten]
67
+ for sho in shorten:
68
+ resp = resp.split(sho).pop(0)
69
+ print("shortened to:")
70
+ print(resp)
71
+ if strip:
72
+ resp = resp.replace("\n", " ").replace(" & ", " and ")
73
+ while " <" in resp and "> " in resp:
74
+ resp = resp[:resp.index(" <") + 1] + resp[resp.index("> ") + 1:]
75
+ while "```" in resp:
76
+ start = resp.index("```") + 3
77
+ resp = resp[:start] + resp[resp.index("```", start) + 3:]
78
+ print("stripped to:")
79
+ print(resp)
80
+ return resp
@@ -0,0 +1,22 @@
1
+ # aiio
2
+ afcfg = {
3
+ "host": "ai.fzn.party",
4
+ "path": "_respond",
5
+ "proto": "https"
6
+ }
7
+
8
+ def fzn(statement, identity="Anonymous", name=None, mood=None, asker=None, options=None):
9
+ from cantools.web import post
10
+ params = {
11
+ "identity": identity,
12
+ "statement": statement,
13
+ "options": options,
14
+ "mood": mood,
15
+ "name": name,
16
+ "asker": asker
17
+ }
18
+ fu = "%s://%s/%s"%(afcfg["proto"], afcfg["host"], afcfg["path"])
19
+ print("fzn", fu, params)
20
+ resp = post(fu, data=params, ctjson=True)
21
+ print(resp)
22
+ return resp
@@ -0,0 +1,73 @@
1
+
2
+ class G4F(object):
3
+ def __init__(self, log=print):
4
+ self.logger = log
5
+ self.client = None
6
+
7
+ def log(self, *msg):
8
+ self.logger("G4F", *msg)
9
+
10
+ def getClient(self):
11
+ if not self.client:
12
+ self.log("setting up client")
13
+ from g4f.client import Client
14
+ self.client = Client()
15
+ return self.client
16
+
17
+ def chat(self, prompt, model="gpt-4o-mini", short=True):
18
+ self.log("chat(%s)"%(model,), prompt)
19
+ messages = [{ "role": "user", "content": prompt }]
20
+ short and messages.insert(0, {
21
+ "role": "user",
22
+ "content": "one sentence responses please"
23
+ })
24
+ return self.getClient().chat.completions.create(
25
+ model=model,
26
+ messages=messages
27
+ ).choices[0].message.content
28
+
29
+ def image(self, prompt, model="flux"):
30
+ self.log("image(%s)"%(model,), prompt)
31
+ return self.getClient().images.generate(
32
+ model=model,
33
+ prompt=prompt,
34
+ response_format="url"
35
+ ).data[0].url
36
+
37
+ def __call__(self, action, prompt, model):
38
+ self.log("calling", action, "with", model, ":", prompt)
39
+ resp = getattr(self, action)(prompt, model)
40
+ self.log("got", resp)
41
+ return resp
42
+
43
+ gchatters = ["gpt-4o-mini", "gpt-4o", "gpt-4.1", "deepseek-v3"]
44
+ gimagers = ["flux", "dalle-3", "gpt-image"]
45
+ VAGENT = None
46
+ g4fer = G4F()
47
+
48
+ def vagent():
49
+ global VAGENT
50
+ if not VAGENT:
51
+ from venvr import getagent
52
+ VAGENT = getagent("g4f", [{
53
+ "requirements": "requirements-slim.txt",
54
+ "git": "xtekky/gpt4free",
55
+ "sym": "g4f"
56
+ }])
57
+ VAGENT.register(G4F)
58
+ return VAGENT
59
+
60
+ def g4do(action, prompt, model):
61
+ try:
62
+ import g4f
63
+ print("found g4f")
64
+ return g4fer(action, prompt, model)
65
+ except:
66
+ print("no g4f - using venvr")
67
+ return vagent().run("G4F", action, prompt, model)
68
+
69
+ def g4image(prompt, model="flux"):
70
+ return g4do("image", prompt, model)
71
+
72
+ def g4chat(prompt, model="gpt-4o-mini"):
73
+ return g4do("chat", prompt, model)
@@ -0,0 +1,84 @@
1
+ import random
2
+ from ..system import cmd
3
+
4
+ class Kvox(object):
5
+ def __init__(self, log=print):
6
+ self.logger = log
7
+ self.kpipes = {}
8
+
9
+ def log(self, *msg):
10
+ self.logger("Kvox", *msg)
11
+
12
+ def getpipe(self, lang_code):
13
+ from kokoro import KPipeline
14
+ if lang_code not in self.kpipes:
15
+ self.kpipes[lang_code] = KPipeline(lang_code=lang_code)
16
+ return self.kpipes[lang_code]
17
+
18
+ def vi(self, t, v):
19
+ t = round(t)
20
+ self.log("viseme with time", t, "and value", v)
21
+ return { "time": t, "value": v }
22
+
23
+ def token2visemes(self, token, visemes):
24
+ self.log("token2visemes", token.text, token.phonemes, token.start_ts, token.end_ts)
25
+ phos = token.text # phonemes are full of unicode....
26
+ step = 1000 * (token.end_ts - token.start_ts) / len(phos)
27
+ t = 1000 * token.start_ts
28
+ for pho in phos:
29
+ visemes.append(self.vi(t, pho))
30
+ t += step
31
+ return t
32
+
33
+ def tokens2visemes(self, tokens):
34
+ self.log("tokens2visemes")
35
+ t = 0
36
+ visemes = []
37
+ for token in tokens:
38
+ t = self.token2visemes(token, visemes)
39
+ visemes.append(self.vi(t, "sil"))
40
+ return visemes
41
+
42
+ def __call__(self, text, voice="af_heart", speed=1, lang_code='a', filename="tts"):
43
+ import json, soundfile
44
+ pipeline = self.getpipe(lang_code)
45
+ nothing, tokens = pipeline.g2p(text)
46
+ for result in pipeline.generate_from_tokens(tokens=tokens, voice=voice, speed=float(speed)):
47
+ self.log(result.phonemes)
48
+ vz = self.tokens2visemes(result.tokens)
49
+ vname = "%s.json"%(filename,)
50
+ aname = "%s.mp3"%(filename,)
51
+ self.log("writing", vname)
52
+ with open(vname, "w") as f:
53
+ f.write("%s\n"%("\n".join([json.dumps(v) for v in vz]),))
54
+ self.log("writing", aname)
55
+ soundfile.write(aname, result.audio, 24000)
56
+
57
+ VAGENT = None
58
+ kvox = Kvox()
59
+ kvoices = [
60
+ "af_heart", "af_bella", "af_nicole", "af_aoede", "af_kore", "af_sarah", "af_nova",
61
+ "af_sky", "af_alloy", "af_jessica", "af_river", "am_michael", "am_fenrir", "am_puck",
62
+ "am_echo", "am_eric", "am_liam", "am_onyx", "am_santa", "am_adam", "bf_emma",
63
+ "bf_isabella", "bf_alice", "bf_lily", "bm_george", "bm_fable", "bm_lewis", "bm_daniel"
64
+ ]
65
+
66
+ def vagent():
67
+ global VAGENT
68
+ if not VAGENT:
69
+ from venvr import getagent
70
+ VAGENT = getagent("kovo", ["kokoro", "soundfile"])
71
+ VAGENT.register(Kvox)
72
+ return VAGENT
73
+
74
+ def vox(text, voice="af_heart", speed=1, lang_code='a', filename="tts", say=False):
75
+ if voice == "random":
76
+ voice = random.choice(kvoices)
77
+ try:
78
+ import kokoro
79
+ print("found kokoro")
80
+ kvox(text, voice, speed, lang_code, filename)
81
+ except:
82
+ print("no kokoro - using venvr")
83
+ vagent().run("Kvox", text, voice, speed, lang_code, filename)
84
+ say and cmd("mplayer %s.mp3"%(filename,))
@@ -0,0 +1 @@
1
+ from .ander import android
@@ -0,0 +1,101 @@
1
+ import os
2
+ from fyg.util import log, ask, confirm, selnum
3
+ from cantools.util import cmd, output, mkdir, cp
4
+ from cantools.util.system import envget, envset
5
+ from cantools.util.admin import _which, javaver
6
+ from .data import TEMPLATES
7
+
8
+ class Android(object):
9
+ def __init__(self, url, name=None, package=None, auto=False):
10
+ self.setVars(url, name, package, auto)
11
+ self.setMode()
12
+ self.dirs()
13
+ self.files()
14
+ self.icons()
15
+ os.chdir(self.name)
16
+ self.apk()
17
+ self.install()
18
+ log("goodbye")
19
+
20
+ def setVars(self, url, name=None, package=None, auto=False):
21
+ if "://" not in url:
22
+ url = "https://%s"%(url,)
23
+ parts = url.split("://").pop().split("/").pop(0).split(".")
24
+ self.url = url
25
+ self.auto = auto
26
+ self.name = name or self.ask("name", parts[0])
27
+ parts.reverse()
28
+ self.package = package or self.ask("package name", ".".join(parts))
29
+ self.dir = self.package.replace(".", "/")
30
+ self.tmps = TEMPLATES["android"]
31
+
32
+ def ask(self, question, default=None):
33
+ if default and self.auto:
34
+ log("question '%s' -> choosing '%s'"%(question, default), important=True)
35
+ return default
36
+ return ask(question, default)
37
+
38
+ def conf(self, condition, default=False):
39
+ if self.auto:
40
+ log("confirmation '%s' -> deciding '%s'"%(condition, default), important=True)
41
+ return default
42
+ return confirm(condition, default)
43
+
44
+ def setMode(self, mode="debug"):
45
+ self.mode = mode
46
+ self.debug = mode == "debug"
47
+
48
+ def dirs(self):
49
+ if not self.conf("assemble directory hierarchy", True): return
50
+ mkdir("%s/src/main/java/%s"%(self.name, self.dir), True)
51
+ mkdir("%s/src/main/res"%(self.name,))
52
+
53
+ def files(self):
54
+ if not self.conf("create project files", True): return
55
+ self.jv = javaver()
56
+ cp(self.tmps["manifest"]%(self.name, self.package, self.name),
57
+ "%s/src/main/AndroidManifest.xml"%(self.name))
58
+ cp(self.tmps["activity"]%(self.package, self.url),
59
+ "%s/src/main/java/%s/MainActivity.java"%(self.name, self.dir))
60
+ cp(self.tmps["gradle"]%(self.package, self.jv, self.jv),
61
+ "%s/build.gradle"%(self.name,))
62
+ cp(self.tmps["properties"], "%s/gradle.properties"%(self.name,))
63
+
64
+ def icons(self):
65
+ if not self.conf("generate icons", True): return
66
+ ipath = self.ask("image path", "icon.png")
67
+ for k, v in self.tmps["isizes"].items():
68
+ wpath = "%s/src/main/res/drawable-%s"%(self.name, k)
69
+ mkdir(wpath)
70
+ cmd(self.tmps["icons"]%(ipath, v, wpath))
71
+
72
+ def chenv(self):
73
+ for name, cfg in self.tmps["env"].items():
74
+ if not envget(name):
75
+ log("%s not set!"%(name,))
76
+ envset(name, self.ask("%s location"%(name,),
77
+ output("locate %s"%(cfg["locater"].replace("_JV_",
78
+ self.jv),)).split(cfg["splitter"]).pop(0)))
79
+
80
+ def apk(self):
81
+ if not self.conf("build apk", True): return
82
+ self.chenv()
83
+ self.setMode(selnum(["debug", "release"]))
84
+ gcmd = self.debug and "assembleDebug" or "assemble"
85
+ if self.conf("add stacktrace flag"):
86
+ gcmd = "%s --stacktrace"%(gcmd,)
87
+ if self.conf("specify trustStore cacerts", True):
88
+ tsca = selnum(output("locate cacerts | grep java").split("\n"))
89
+ tspw = self.ask("trustStore password", "changeit")
90
+ gcmd = self.tmps["tstore"]%(gcmd, tsca, tspw)
91
+ cmd("gradle %s"%(gcmd,))
92
+
93
+ def install(self):
94
+ if not self.conf("install on device", True): return
95
+ aname = self.debug and "%s-debug"%(self.name,) or self.name
96
+ cmd("adb install build/outputs/apk/%s/%s.apk"%(self.mode, aname))
97
+
98
+ def android(url=None, auto=False):
99
+ if not _which("java", "gradle", "adb", "convert"):
100
+ return log("build aborted!")
101
+ Android(url or ask("url", "http://ct.mkult.co"), auto=auto)
@@ -0,0 +1,167 @@
1
+ # reference:
2
+ # - https://github.com/raelmax/android-webview
3
+ # - https://czak.pl/posts/minimal-android-project
4
+
5
+ AMAN = """<?xml version="1.0" encoding="utf-8"?>
6
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
7
+ android:versionCode="1"
8
+ android:versionName="1.0" >
9
+
10
+ <uses-sdk />
11
+
12
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
13
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
14
+ <uses-permission android:name="android.permission.INTERNET" />
15
+ <uses-permission android:name="android.permission.CAMERA" />
16
+
17
+ <application
18
+ android:allowBackup="true"
19
+ android:icon="@drawable/ic_launcher"
20
+ android:label="%s"
21
+ android:theme="@android:style/Theme.NoTitleBar" >
22
+ <activity
23
+ android:name="%s.MainActivity"
24
+ android:configChanges="orientation|screenSize"
25
+ android:label="%s"
26
+ android:exported="true" >
27
+ <intent-filter>
28
+ <action android:name="android.intent.action.MAIN" />
29
+ <category android:name="android.intent.category.LAUNCHER" />
30
+ </intent-filter>
31
+ </activity>
32
+ </application>
33
+ </manifest>
34
+ """
35
+
36
+ AMAC = """package %s;
37
+ import android.Manifest;
38
+ import android.app.Activity;
39
+ import android.os.Bundle;
40
+ import android.view.KeyEvent;
41
+ import android.view.Window;
42
+ import android.webkit.WebView;
43
+ import android.webkit.WebViewClient;
44
+ import android.webkit.WebChromeClient;
45
+ import android.webkit.PermissionRequest;
46
+ import android.content.pm.PackageManager;
47
+ import androidx.core.content.ContextCompat;
48
+
49
+ public class MainActivity extends Activity {
50
+ private WebView mWebView;
51
+
52
+ @Override
53
+ public void onCreate(Bundle savedInstanceState) {
54
+ super.onCreate(savedInstanceState);
55
+ MainActivity thaz = this;
56
+ getWindow().requestFeature(Window.FEATURE_NO_TITLE);
57
+ mWebView = new WebView(this);
58
+ mWebView.getSettings().setMediaPlaybackRequiresUserGesture(false);
59
+ mWebView.getSettings().setJavaScriptEnabled(true);
60
+ mWebView.getSettings().setDomStorageEnabled(true);
61
+ mWebView.getSettings().setUseWideViewPort(true);
62
+ mWebView.loadUrl("%s");
63
+ mWebView.setWebViewClient(new WebViewClient() {
64
+ @Override
65
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
66
+ view.loadUrl(url);
67
+ return true;
68
+ }
69
+ });
70
+ mWebView.setWebChromeClient(new WebChromeClient(){
71
+ // Need to accept permissions to use the camera
72
+ @Override
73
+ public void onPermissionRequest(final PermissionRequest request) {
74
+ // grants permission for app. video not showing
75
+ if (ContextCompat.checkSelfPermission(thaz, Manifest.permission.CAMERA)
76
+ != PackageManager.PERMISSION_GRANTED
77
+ ) {
78
+ requestPermissions(new String[]{Manifest.permission.CAMERA}, 1010);
79
+ }
80
+
81
+ if (ContextCompat.checkSelfPermission(thaz, Manifest.permission.RECORD_AUDIO)
82
+ != PackageManager.PERMISSION_GRANTED
83
+ ) {
84
+ requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 1010);
85
+ }
86
+
87
+ request.grant(request.getResources()); // is this right?
88
+ }
89
+ });
90
+ this.setContentView(mWebView);
91
+ }
92
+
93
+ @Override
94
+ public boolean onKeyDown(final int keyCode, final KeyEvent event) {
95
+ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
96
+ mWebView.goBack();
97
+ return true;
98
+ }
99
+ return super.onKeyDown(keyCode, event);
100
+ }
101
+ }"""
102
+
103
+ ABG = """buildscript {
104
+ repositories {
105
+ google()
106
+ mavenCentral()
107
+ }
108
+ dependencies {
109
+ classpath 'com.android.tools.build:gradle:8.5.2'
110
+ }
111
+ }
112
+
113
+ repositories {
114
+ google()
115
+ }
116
+
117
+ apply plugin: 'com.android.application'
118
+
119
+ dependencies {
120
+ implementation 'androidx.appcompat:appcompat:1.1.0'
121
+ }
122
+
123
+ android {
124
+ namespace = "%s"
125
+
126
+ compileSdkVersion 34
127
+
128
+ defaultConfig {
129
+ targetSdk = 34
130
+ minSdkVersion = 14
131
+ }
132
+
133
+ compileOptions {
134
+ sourceCompatibility JavaVersion.VERSION_%s
135
+ targetCompatibility JavaVersion.VERSION_%s
136
+ }
137
+ }"""
138
+
139
+ AGP = """android.useAndroidX=true
140
+ android.enableJetifier=true"""
141
+
142
+ TEMPLATES = {
143
+ "android": {
144
+ "manifest": AMAN,
145
+ "activity": AMAC,
146
+ "gradle": ABG,
147
+ "properties": AGP,
148
+ "icons": "convert -background none %s -resize %s %s/ic_launcher.png",
149
+ "tstore": "%s -Djavax.net.ssl.trustStore=%s -Djavax.net.ssl.trustStorePassword=%s",
150
+ "isizes": {
151
+ 'ldpi': '36x36',
152
+ 'mdpi': '48x48',
153
+ 'hdpi': '72x72',
154
+ 'xhdpi': '96x96'
155
+ },
156
+ "env": {
157
+ "JAVA_HOME": {
158
+ "locater": "cacerts|grep jvm/java-_JV_-",
159
+ "splitter": "/lib/security"
160
+ },
161
+ "ANDROID_HOME": {
162
+ "locater": "/lib/android-sdk",
163
+ "splitter": "\n"
164
+ }
165
+ }
166
+ }
167
+ }
cantools/util/system.py CHANGED
@@ -1,9 +1,5 @@
1
- import os, sys, subprocess, platform
2
- try:
3
- from commands import getoutput # py2
4
- except:
5
- from subprocess import getoutput # py3
6
- from fyg.util import log, read, write, rm
1
+ import os, sys
2
+ from fyg.util import log, read, write, rm, sudoed, cmd, output
7
3
 
8
4
  def cp(content, fname): # more write than copy, buuuut...
9
5
  log("writing %s"%(fname,), 2)
@@ -40,23 +36,6 @@ def mkdir(pname, recursive=False):
40
36
  def sed(fname, flag, replacement, target=None):
41
37
  write(read(fname).replace(flag, replacement), target or fname)
42
38
 
43
- def sudoed(cline, sudo=False):
44
- if sudo and platform.system() != "Windows" and os.geteuid(): # !root
45
- cline = "sudo %s"%(cline,)
46
- return cline
47
-
48
- def cmd(cline, sudo=False, silent=False):
49
- cline = sudoed(cline, sudo)
50
- silent or log('issuing command: "%s"'%(cline,), 2)
51
- subprocess.call(cline, shell=True)
52
-
53
- def output(cline, sudo=False, silent=False, loud=False):
54
- cline = sudoed(cline, sudo)
55
- silent or log('getting output for: "%s"'%(cline,), 2)
56
- output = getoutput(cline)
57
- loud and log(output)
58
- return output
59
-
60
39
  def envget(name):
61
40
  return output("echo $%s"%(name,))
62
41
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ct
3
- Version: 0.10.8.115
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
@@ -17,7 +17,7 @@ Requires-Dist: babyweb >=0.1.2
17
17
  Requires-Dist: catmail >=0.1.9.1
18
18
  Requires-Dist: databae >=0.1.5.1
19
19
  Requires-Dist: dez >=0.10.10.45
20
- Requires-Dist: fyg >=0.1.7.8
20
+ Requires-Dist: fyg >=0.1.7.9
21
21
  Requires-Dist: rel >=0.4.9.23
22
22
  Requires-Dist: venvr >=0.1.5.8
23
23
 
@@ -1,10 +1,10 @@
1
- cantools/__init__.py,sha256=ex9aLaH_c4us-uSjnvbJ9KFypAcsyPTdldrPVvkYtGE,824
1
+ cantools/__init__.py,sha256=pYszyy7Gwi8eK0nDPsJq5aIok5xQnYLERkM74roIzFE,824
2
2
  cantools/_db.py,sha256=g-kXshJpjfLiYPg8GtTrae1bD0uZ8eWbYi8ORKaXGNs,5075
3
3
  cantools/_memcache.py,sha256=xv_rumi1mrr6Br4ofZXTA6deNOEyZg6nwFW6QEcUVZ4,2154
4
4
  cantools/_pay.py,sha256=hvu8SiFVUySVIu5W1SZuD_6DHaUWnmy0XOITPlt1C3M,1292
5
5
  cantools/admin.py,sha256=MuRKvFQ_LhGqRro6cY6e6PGOBjLXGwKKcTJ1GuAa3K0,1182
6
6
  cantools/cfg.py,sha256=N1hBT_MwuHIYAtZ0vczjnE9B_cvwq_IcgTWRvoBUGZI,8920
7
- cantools/config.py,sha256=Lx_qk20aHxzEi-rx1ztZi3gSGj_mf2kwvqUyMnxTgr4,5057
7
+ cantools/config.py,sha256=FA9VmBhYhSIshizUjA7zrGNmgjYgoItrRGac-mKhp0o,5182
8
8
  cantools/geo.py,sha256=WQMWp142niNzRf4WXRurzGPiFaZ3orbDpBwQC2gZXn0,5422
9
9
  cantools/hooks.py,sha256=kEnYBt8Fl6EFJz_u-jPQjGQTXa9TxACZxPMbgUW3cHc,219
10
10
  cantools/db/__init__.py,sha256=slJyO03jrCTEqDWzXUkrsmolGoJTO42FPJSLCE87RSM,614
@@ -30,18 +30,27 @@ cantools/scripts/pubsub/channel.py,sha256=racPeZThUoKJK2TYFfNtwKkxjP5jLUwTWozoZz
30
30
  cantools/scripts/pubsub/ps.py,sha256=enpSroRCKdJ4GS7M7mpv5mh0z6_rtv_JLpri2NvyJQ0,5216
31
31
  cantools/scripts/pubsub/user.py,sha256=B1LdCmmwxgtTNgWGmtxDVzPruYjgw5J-vIjmcB0kbck,1554
32
32
  cantools/util/__init__.py,sha256=zZ_0RSbOyChUvp4PBfuzKNy4KRQHJXv8abv-LO2T06I,3444
33
- cantools/util/admin.py,sha256=cd1-lG6cfIbFF-dz3uZEnHv8bxJHP-S7X8Q6mmRHO-k,19377
33
+ cantools/util/admin.py,sha256=b5lb4X1N7VfeL0MutMT_cWIpTMz3ehL900YkCN9DLPE,18469
34
34
  cantools/util/data.py,sha256=RrvVmgQkelSCXHj0oqRkg_aifX6qI7IsrBAJr0wvq8s,2911
35
35
  cantools/util/media.py,sha256=-znYq87blesL_rMc2OfYmum69z1uiyMe0XmGL--bS2g,8585
36
36
  cantools/util/package.py,sha256=cKJwC7OoLRmQ2dzYtjZjpQoW09ojZ_nTTqgx0fCimHI,3998
37
- cantools/util/system.py,sha256=vBDxcX3EAAjaaOcPzxo1AoESbq7kWYX7Zs1iXfHZKHg,1906
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
38
47
  cantools/web/__init__.py,sha256=nJOA_sNuT31LgFauWGUjznjhWoubjb1JqGVg2XWXjhM,407
39
48
  cantools/web/bw.py,sha256=N-cimUHYyDuHv8v2Ut0twsi8yBDMb3alw1m9EpCYDEs,2704
40
49
  cantools/web/gae_server.py,sha256=dPLkEsvzOb-wEFCSMleCvIElNnJoLRMdAGw5DYytwGU,2007
41
50
  cantools/web/util.py,sha256=ovacYpR6VtJVw9MvL9jJuXdkMKKv8A5GxjWE-KlYe70,4367
42
- ct-0.10.8.115.dist-info/LICENSE,sha256=lUkxqJkYxLYhvL52PQdG8L3aqmG241XXmThs30isJTU,1078
43
- ct-0.10.8.115.dist-info/METADATA,sha256=QL_l91VqDZvV5OlBQKeGuxBZ9grfPJsy0PUPITuxRCE,1175
44
- ct-0.10.8.115.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
45
- ct-0.10.8.115.dist-info/entry_points.txt,sha256=Gd3wUZp5AMeazvq2oIOh4qn57T2joZ8NeHenLhXG4Hw,261
46
- ct-0.10.8.115.dist-info/top_level.txt,sha256=Tl_rJpBXgVrhgmBrKozbrcQrKnOIX89JqFF7aF_4EbA,9
47
- ct-0.10.8.115.dist-info/RECORD,,
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,,