bigtalk 1__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.
- bigtalk/brokers.py +36 -0
- bigtalk/clients.py +87 -0
- bigtalk/command.py +49 -0
- bigtalk/handler.py +54 -0
- bigtalk/kernels.py +69 -0
- bigtalk/locater.py +86 -0
- bigtalk/loggers.py +37 -0
- bigtalk/message.py +46 -0
- bigtalk/methods.py +139 -0
- bigtalk/objects.py +99 -0
- bigtalk/package.py +79 -0
- bigtalk/persist.py +69 -0
- bigtalk/repeats.py +63 -0
- bigtalk/serials.py +53 -0
- bigtalk/statics.py +52 -0
- bigtalk/threads.py +92 -0
- bigtalk/utility.py +245 -0
- bigtalk/workdir.py +67 -0
- bigtalk-1.dist-info/METADATA +70 -0
- bigtalk-1.dist-info/RECORD +22 -0
- bigtalk-1.dist-info/WHEEL +5 -0
- bigtalk-1.dist-info/top_level.txt +1 -0
bigtalk/brokers.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"an object for a string"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Broker:
|
|
8
|
+
|
|
9
|
+
objects = {}
|
|
10
|
+
|
|
11
|
+
@staticmethod
|
|
12
|
+
def add(obj):
|
|
13
|
+
Broker.objects[repr(obj)] = obj
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def all(attr):
|
|
17
|
+
for obj in Broker.objects.values():
|
|
18
|
+
if attr in dir(obj):
|
|
19
|
+
yield obj
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def get(origin):
|
|
23
|
+
return Broker.objects.get(origin)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@staticmethod
|
|
27
|
+
def like(txt):
|
|
28
|
+
for orig in Broker.objects:
|
|
29
|
+
if orig.split()[0] in orig.split()[0]:
|
|
30
|
+
yield orig
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def __dir__():
|
|
34
|
+
return (
|
|
35
|
+
'Broker',
|
|
36
|
+
)
|
bigtalk/clients.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"client-side event handling"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import queue
|
|
9
|
+
import threading
|
|
10
|
+
import _thread
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
from .brokers import Broker
|
|
14
|
+
from .command import Commands
|
|
15
|
+
from .handler import Handler
|
|
16
|
+
from .threads import Threads
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Client(Handler):
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
super().__init__()
|
|
23
|
+
self.olock = threading.RLock()
|
|
24
|
+
self.oqueue = queue.Queue()
|
|
25
|
+
self.silent = True
|
|
26
|
+
Broker.add(self)
|
|
27
|
+
|
|
28
|
+
def announce(self, text):
|
|
29
|
+
if not self.silent:
|
|
30
|
+
self.raw(text)
|
|
31
|
+
|
|
32
|
+
def display(self, event):
|
|
33
|
+
with self.olock:
|
|
34
|
+
for tme in event.result:
|
|
35
|
+
txt = event.result.get(tme)
|
|
36
|
+
self.dosay(event.channel, txt)
|
|
37
|
+
|
|
38
|
+
def dosay(self, channel, text):
|
|
39
|
+
self.say(channel, text)
|
|
40
|
+
|
|
41
|
+
def raw(self, text):
|
|
42
|
+
raise NotImplementedError("raw")
|
|
43
|
+
|
|
44
|
+
def say(self, channel, text):
|
|
45
|
+
self.raw(text)
|
|
46
|
+
|
|
47
|
+
def wait(self):
|
|
48
|
+
try:
|
|
49
|
+
self.oqueue.join()
|
|
50
|
+
except Exception as ex:
|
|
51
|
+
logging.exception(ex)
|
|
52
|
+
_thread.interrupt_main()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class CLI(Client):
|
|
56
|
+
|
|
57
|
+
def __init__(self):
|
|
58
|
+
super().__init__()
|
|
59
|
+
self.register("command", Commands.command)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class Output(Client):
|
|
63
|
+
|
|
64
|
+
def output(self):
|
|
65
|
+
while True:
|
|
66
|
+
event = self.oqueue.get()
|
|
67
|
+
if event is None:
|
|
68
|
+
self.oqueue.task_done()
|
|
69
|
+
break
|
|
70
|
+
self.display(event)
|
|
71
|
+
self.oqueue.task_done()
|
|
72
|
+
|
|
73
|
+
def start(self):
|
|
74
|
+
Threads.launch(self.output)
|
|
75
|
+
super().start()
|
|
76
|
+
|
|
77
|
+
def stop(self):
|
|
78
|
+
self.oqueue.put(None)
|
|
79
|
+
super().stop()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def __dir__():
|
|
83
|
+
return (
|
|
84
|
+
'Client',
|
|
85
|
+
'CLI',
|
|
86
|
+
'Output'
|
|
87
|
+
)
|
bigtalk/command.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"write your own commands"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import inspect
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .methods import Methods
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Commands:
|
|
14
|
+
|
|
15
|
+
cmds = {}
|
|
16
|
+
names = {}
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def add(*args):
|
|
20
|
+
for func in args:
|
|
21
|
+
name = func.__name__
|
|
22
|
+
Commands.cmds[name] = func
|
|
23
|
+
Commands.names[name] = func.__module__.split(".")[-1]
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def command(evt):
|
|
27
|
+
Methods.parse(evt, evt.text)
|
|
28
|
+
func = Commands.get(evt.cmd)
|
|
29
|
+
if func:
|
|
30
|
+
func(evt)
|
|
31
|
+
evt.display()
|
|
32
|
+
evt.ready()
|
|
33
|
+
|
|
34
|
+
@staticmethod
|
|
35
|
+
def get(cmd):
|
|
36
|
+
return Commands.cmds.get(cmd, None)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def scan(module):
|
|
40
|
+
for key, cmdz in inspect.getmembers(module, inspect.isfunction):
|
|
41
|
+
if 'event' not in inspect.signature(cmdz).parameters:
|
|
42
|
+
continue
|
|
43
|
+
Commands.add(cmdz)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def __dir__():
|
|
47
|
+
return (
|
|
48
|
+
'Commands',
|
|
49
|
+
)
|
bigtalk/handler.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"handle your own events"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import queue
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .threads import Threads
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Handler:
|
|
14
|
+
|
|
15
|
+
def __init__(self):
|
|
16
|
+
self.cbs = {}
|
|
17
|
+
self.queue = queue.Queue()
|
|
18
|
+
|
|
19
|
+
def callback(self, event):
|
|
20
|
+
func = self.cbs.get(event.kind, None)
|
|
21
|
+
if not func:
|
|
22
|
+
event.ready()
|
|
23
|
+
return
|
|
24
|
+
name = event.text and event.text.split()[0]
|
|
25
|
+
event._thr = Threads.launch(func, event, name=name)
|
|
26
|
+
|
|
27
|
+
def loop(self):
|
|
28
|
+
while True:
|
|
29
|
+
event = self.poll()
|
|
30
|
+
if not event:
|
|
31
|
+
break
|
|
32
|
+
event.orig = repr(self)
|
|
33
|
+
self.callback(event)
|
|
34
|
+
|
|
35
|
+
def poll(self):
|
|
36
|
+
return self.queue.get()
|
|
37
|
+
|
|
38
|
+
def put(self, event):
|
|
39
|
+
self.queue.put(event)
|
|
40
|
+
|
|
41
|
+
def register(self, kind, callback):
|
|
42
|
+
self.cbs[kind] = callback
|
|
43
|
+
|
|
44
|
+
def start(self):
|
|
45
|
+
Threads.launch(self.loop)
|
|
46
|
+
|
|
47
|
+
def stop(self):
|
|
48
|
+
self.queue.put(None)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def __dir__():
|
|
52
|
+
return (
|
|
53
|
+
'Handler',
|
|
54
|
+
)
|
bigtalk/kernels.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"in the beginning"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .command import Commands
|
|
11
|
+
from .loggers import Logging
|
|
12
|
+
from .objects import Default
|
|
13
|
+
from .package import Mods
|
|
14
|
+
from .threads import Threads
|
|
15
|
+
from .utility import Utils
|
|
16
|
+
from .workdir import Workdir
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Config(Default):
|
|
20
|
+
|
|
21
|
+
debug = False
|
|
22
|
+
init = ""
|
|
23
|
+
level = "info"
|
|
24
|
+
name = ""
|
|
25
|
+
opts = ""
|
|
26
|
+
sets = Default()
|
|
27
|
+
version = 0
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Kernel:
|
|
31
|
+
|
|
32
|
+
@staticmethod
|
|
33
|
+
def configure(local=False, network=False):
|
|
34
|
+
assert Config.name
|
|
35
|
+
Logging.level(Config.sets.level or "info")
|
|
36
|
+
Workdir.configure(Config.name)
|
|
37
|
+
Mods.configure(local, network)
|
|
38
|
+
|
|
39
|
+
@staticmethod
|
|
40
|
+
def forever():
|
|
41
|
+
while True:
|
|
42
|
+
try:
|
|
43
|
+
time.sleep(0.1)
|
|
44
|
+
except (KeyboardInterrupt, EOFError):
|
|
45
|
+
break
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def init(names, wait=False):
|
|
49
|
+
thrs = []
|
|
50
|
+
for name in Utils.spl(names):
|
|
51
|
+
mod = Mods.get(name)
|
|
52
|
+
if "init" not in dir(mod):
|
|
53
|
+
continue
|
|
54
|
+
thrs.append(Threads.launch(mod.init))
|
|
55
|
+
if wait:
|
|
56
|
+
for thr in thrs:
|
|
57
|
+
thr.join()
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def scanner(names):
|
|
61
|
+
for mod in Mods.mods(names):
|
|
62
|
+
Commands.scan(mod)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def __dir__():
|
|
66
|
+
return (
|
|
67
|
+
'Config',
|
|
68
|
+
'Kernel'
|
|
69
|
+
)
|
bigtalk/locater.py
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"find objects"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from .methods import Methods
|
|
12
|
+
from .objects import Object
|
|
13
|
+
from .persist import Cache, Disk
|
|
14
|
+
from .workdir import Workdir
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
keys = Object.keys
|
|
18
|
+
update = Object.update
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Locater:
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def attrs(kind):
|
|
25
|
+
objs = list(Locater.find(kind))
|
|
26
|
+
if objs:
|
|
27
|
+
return list(keys(objs[0][1]))
|
|
28
|
+
return []
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def find(kind, selector={}, removed=False, matching=False):
|
|
32
|
+
fullname = Workdir.long(kind)
|
|
33
|
+
for pth in Locater.fns(fullname):
|
|
34
|
+
obj = Cache.get(pth)
|
|
35
|
+
if not obj:
|
|
36
|
+
obj = Object()
|
|
37
|
+
Disk.read(obj, pth)
|
|
38
|
+
Cache.add(pth, obj)
|
|
39
|
+
if not removed and Methods.deleted(obj):
|
|
40
|
+
continue
|
|
41
|
+
if selector and not Methods.search(obj, selector, matching):
|
|
42
|
+
continue
|
|
43
|
+
yield pth, obj
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def fns(kind):
|
|
47
|
+
path = Workdir.store(kind)
|
|
48
|
+
for rootdir, dirs, _files in os.walk(path, topdown=True):
|
|
49
|
+
for dname in dirs:
|
|
50
|
+
if dname.count("-") != 2:
|
|
51
|
+
continue
|
|
52
|
+
ddd = os.path.join(rootdir, dname)
|
|
53
|
+
for fll in os.listdir(ddd):
|
|
54
|
+
yield os.path.join(ddd, fll)
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def fntime(daystr):
|
|
58
|
+
datestr = " ".join(daystr.split(os.sep)[-2:])
|
|
59
|
+
datestr = datestr.replace("_", " ")
|
|
60
|
+
if "." in datestr:
|
|
61
|
+
datestr, rest = datestr.rsplit(".", 1)
|
|
62
|
+
else:
|
|
63
|
+
rest = ""
|
|
64
|
+
timed = time.mktime(time.strptime(datestr, "%Y-%m-%d %H:%M:%S"))
|
|
65
|
+
if rest:
|
|
66
|
+
timed += float("." + rest)
|
|
67
|
+
return float(timed)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def last(obj, selector={}):
|
|
71
|
+
result = sorted(
|
|
72
|
+
Locater.find(Object.fqn(obj), selector),
|
|
73
|
+
key=lambda x: Locater.fntime(x[0])
|
|
74
|
+
)
|
|
75
|
+
res = ""
|
|
76
|
+
if result:
|
|
77
|
+
inp = result[-1]
|
|
78
|
+
update(obj, inp[-1])
|
|
79
|
+
res = inp[0]
|
|
80
|
+
return res
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def __dir__():
|
|
84
|
+
return (
|
|
85
|
+
'Locater',
|
|
86
|
+
)
|
bigtalk/loggers.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"log exceptions"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Format(logging.Formatter):
|
|
11
|
+
|
|
12
|
+
def format(self, record):
|
|
13
|
+
record.module = record.module.upper()
|
|
14
|
+
return logging.Formatter.format(self, record)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Logging:
|
|
18
|
+
|
|
19
|
+
datefmt = "%H:%M:%S"
|
|
20
|
+
format = "%(module).3s %(message)s"
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
def level(loglevel):
|
|
24
|
+
formatter = Format(Logging.format, Logging.datefmt)
|
|
25
|
+
stream = logging.StreamHandler()
|
|
26
|
+
stream.setFormatter(formatter)
|
|
27
|
+
logging.basicConfig(
|
|
28
|
+
level=loglevel.upper(),
|
|
29
|
+
handlers=[stream,],
|
|
30
|
+
force=True
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __dir__():
|
|
35
|
+
return (
|
|
36
|
+
'Logging',
|
|
37
|
+
)
|
bigtalk/message.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"only message"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import threading
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
from .brokers import Broker
|
|
12
|
+
from .objects import Default
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Message(Default):
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__()
|
|
19
|
+
self._ready = threading.Event()
|
|
20
|
+
self.result = {}
|
|
21
|
+
self.thr = None
|
|
22
|
+
self.args = []
|
|
23
|
+
self.index = 0
|
|
24
|
+
self.kind = "event"
|
|
25
|
+
self.orig = ""
|
|
26
|
+
|
|
27
|
+
def display(evt):
|
|
28
|
+
bot = Broker.get(evt.orig)
|
|
29
|
+
bot.display(evt)
|
|
30
|
+
|
|
31
|
+
def ready(self):
|
|
32
|
+
self._ready.set()
|
|
33
|
+
|
|
34
|
+
def reply(self, text):
|
|
35
|
+
self.result[time.time()] = text
|
|
36
|
+
|
|
37
|
+
def wait(self, timeout=0.0):
|
|
38
|
+
if self.thr:
|
|
39
|
+
self.thr.join(timeout)
|
|
40
|
+
self._ready.wait(timeout or None)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def __dir__():
|
|
44
|
+
return (
|
|
45
|
+
'Message',
|
|
46
|
+
)
|
bigtalk/methods.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"functions with an object as the first argument"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from .objects import Default, Object
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Methods:
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def deleted(obj):
|
|
14
|
+
return "__deleted__" in dir(obj) and obj.__deleted__
|
|
15
|
+
|
|
16
|
+
@staticmethod
|
|
17
|
+
def edit(obj, setter={}, skip=False):
|
|
18
|
+
for key, val in Object, items(setter):
|
|
19
|
+
if skip and val == "":
|
|
20
|
+
continue
|
|
21
|
+
try:
|
|
22
|
+
setattr(obj, key, int(val))
|
|
23
|
+
continue
|
|
24
|
+
except ValueError:
|
|
25
|
+
pass
|
|
26
|
+
try:
|
|
27
|
+
setattr(obj, key, float(val))
|
|
28
|
+
continue
|
|
29
|
+
except ValueError:
|
|
30
|
+
pass
|
|
31
|
+
if val in ["True", "true"]:
|
|
32
|
+
setattr(obj, key, True)
|
|
33
|
+
elif val in ["False", "false"]:
|
|
34
|
+
setattr(obj, key, False)
|
|
35
|
+
else:
|
|
36
|
+
setattr(obj, key, val)
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def fmt(obj, args=[], skip=[], plain=False, empty=False):
|
|
40
|
+
if args == []:
|
|
41
|
+
args = list(obj.__dict__.keys())
|
|
42
|
+
txt = ""
|
|
43
|
+
for key in args:
|
|
44
|
+
if key.startswith("__"):
|
|
45
|
+
continue
|
|
46
|
+
if key in skip:
|
|
47
|
+
continue
|
|
48
|
+
value = getattr(obj, key, None)
|
|
49
|
+
if value is None:
|
|
50
|
+
continue
|
|
51
|
+
if not empty and not value:
|
|
52
|
+
continue
|
|
53
|
+
if plain:
|
|
54
|
+
txt += f"{value} "
|
|
55
|
+
elif isinstance(value, str):
|
|
56
|
+
txt += f'{key}="{value}" '
|
|
57
|
+
elif isinstance(value, (int, float, dict, bool, list)):
|
|
58
|
+
txt += f"{key}={value} "
|
|
59
|
+
else:
|
|
60
|
+
txt += f"{key}={Object.fqn(value)}((value))"
|
|
61
|
+
if txt == "":
|
|
62
|
+
txt = "{}"
|
|
63
|
+
return txt.strip()
|
|
64
|
+
|
|
65
|
+
@staticmethod
|
|
66
|
+
def parse(obj, text):
|
|
67
|
+
data = {
|
|
68
|
+
"args": [],
|
|
69
|
+
"cmd": "",
|
|
70
|
+
"gets": Default(),
|
|
71
|
+
"index": None,
|
|
72
|
+
"init": "",
|
|
73
|
+
"opts": "",
|
|
74
|
+
"otxt": text,
|
|
75
|
+
"rest": "",
|
|
76
|
+
"silent": Default(),
|
|
77
|
+
"sets": Default(),
|
|
78
|
+
"text": text
|
|
79
|
+
}
|
|
80
|
+
for k, v in data.items():
|
|
81
|
+
setattr(obj, k, getattr(obj, k, v) or v)
|
|
82
|
+
args = []
|
|
83
|
+
nr = -1
|
|
84
|
+
for spli in text.split():
|
|
85
|
+
if spli.startswith("-"):
|
|
86
|
+
try:
|
|
87
|
+
obj.index = int(spli[1:])
|
|
88
|
+
except ValueError:
|
|
89
|
+
obj.opts += spli[1:]
|
|
90
|
+
continue
|
|
91
|
+
if "-=" in spli:
|
|
92
|
+
key, value = spli.split("-=", maxsplit=1)
|
|
93
|
+
setattr(obj.silent, key, value)
|
|
94
|
+
setattr(obj.gets, key. value)
|
|
95
|
+
continue
|
|
96
|
+
if "==" in spli:
|
|
97
|
+
key, value = spli.split("==", maxsplit=1)
|
|
98
|
+
setattr(obj.gets, key, value)
|
|
99
|
+
continue
|
|
100
|
+
if "=" in spli:
|
|
101
|
+
key, value = spli.split("=", maxsplit=1)
|
|
102
|
+
setattr(obj.sets, key, value)
|
|
103
|
+
continue
|
|
104
|
+
nr += 1
|
|
105
|
+
if nr == 0:
|
|
106
|
+
obj.cmd = spli
|
|
107
|
+
continue
|
|
108
|
+
args.append(spli)
|
|
109
|
+
if args:
|
|
110
|
+
obj.args = args
|
|
111
|
+
obj.text = obj.cmd or ""
|
|
112
|
+
obj.rest = " ".join(obj.args)
|
|
113
|
+
obj.text = obj.cmd + " " + obj.rest
|
|
114
|
+
else:
|
|
115
|
+
obj.text = obj.cmd or ""
|
|
116
|
+
|
|
117
|
+
@staticmethod
|
|
118
|
+
def search(obj, selector={}, matching=False):
|
|
119
|
+
res = False
|
|
120
|
+
for key, value in items(selector):
|
|
121
|
+
val = getattr(obj, key, None)
|
|
122
|
+
if not val:
|
|
123
|
+
res = False
|
|
124
|
+
break
|
|
125
|
+
elif matching and value != val:
|
|
126
|
+
res = False
|
|
127
|
+
break
|
|
128
|
+
elif str(value).lower() not in str(val).lower():
|
|
129
|
+
res = False
|
|
130
|
+
break
|
|
131
|
+
else:
|
|
132
|
+
res = True
|
|
133
|
+
return res
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def __dir__():
|
|
137
|
+
return (
|
|
138
|
+
'Methods',
|
|
139
|
+
)
|
bigtalk/objects.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# This file is placed in the Public Domain.
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
"a clean namespace"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import types
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Reserved(Exception):
|
|
11
|
+
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Object:
|
|
16
|
+
|
|
17
|
+
def __contains__(self, key):
|
|
18
|
+
return key in dir(self)
|
|
19
|
+
|
|
20
|
+
def __iter__(self):
|
|
21
|
+
return iter(self.__dict__)
|
|
22
|
+
|
|
23
|
+
def __len__(self):
|
|
24
|
+
return len(self.__dict__)
|
|
25
|
+
|
|
26
|
+
def __str__(self):
|
|
27
|
+
return str(self.__dict__)
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def construct(obj, *args, **kwargs):
|
|
31
|
+
if args:
|
|
32
|
+
val = args[0]
|
|
33
|
+
if isinstance(val, zip):
|
|
34
|
+
Object.update(obj, dict(val))
|
|
35
|
+
elif isinstance(val, dict):
|
|
36
|
+
Object.update(obj, val)
|
|
37
|
+
else:
|
|
38
|
+
Object.update(obj, vars(val))
|
|
39
|
+
if kwargs:
|
|
40
|
+
Object.update(obj, kwargs)
|
|
41
|
+
|
|
42
|
+
@staticmethod
|
|
43
|
+
def fqn(obj):
|
|
44
|
+
kin = str(type(obj)).split()[-1][1:-2]
|
|
45
|
+
if kin == "type":
|
|
46
|
+
tpe = type(obj)
|
|
47
|
+
kin = f"{tpe.__module__}.{tpe.__name__}"
|
|
48
|
+
return kin
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def items(obj):
|
|
52
|
+
if isinstance(obj, dict):
|
|
53
|
+
return obj.items()
|
|
54
|
+
if isinstance(obj, types.MappingProxyType):
|
|
55
|
+
return obj.items()
|
|
56
|
+
return obj.__dict__.items()
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def keys(obj):
|
|
60
|
+
if isinstance(obj, dict):
|
|
61
|
+
return obj.keys()
|
|
62
|
+
return obj.__dict__.keys()
|
|
63
|
+
|
|
64
|
+
@staticmethod
|
|
65
|
+
def update(obj, data, empty=True):
|
|
66
|
+
if isinstance(obj, type):
|
|
67
|
+
for k, v in Object.items(data):
|
|
68
|
+
if isinstance(getattr(obj, k, None), types.MethodType):
|
|
69
|
+
raise Reserved(k)
|
|
70
|
+
setattr(obj, k, v)
|
|
71
|
+
elif isinstance(obj, dict):
|
|
72
|
+
for k, v in items(data):
|
|
73
|
+
setattr(obj, k, v)
|
|
74
|
+
else:
|
|
75
|
+
for key, value in Object.items(data):
|
|
76
|
+
if not empty and not value:
|
|
77
|
+
continue
|
|
78
|
+
setattr(obj, key, value)
|
|
79
|
+
|
|
80
|
+
@staticmethod
|
|
81
|
+
def values(obj):
|
|
82
|
+
if isinstance(obj, dict):
|
|
83
|
+
return obj.values()
|
|
84
|
+
return obj.__dict__.values()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Default(Object):
|
|
88
|
+
|
|
89
|
+
def __getattr__(self, key):
|
|
90
|
+
return self.__dict__.get(key, "")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def __dir__():
|
|
95
|
+
return (
|
|
96
|
+
'Default',
|
|
97
|
+
'Object',
|
|
98
|
+
'Reserved'
|
|
99
|
+
)
|