bigtalk 1__tar.gz

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 (51) hide show
  1. bigtalk-1/MANIFEST.in +3 -0
  2. bigtalk-1/PKG-INFO +70 -0
  3. bigtalk-1/README.rst +55 -0
  4. bigtalk-1/bigtalk/brokers.py +36 -0
  5. bigtalk-1/bigtalk/clients.py +87 -0
  6. bigtalk-1/bigtalk/command.py +49 -0
  7. bigtalk-1/bigtalk/handler.py +54 -0
  8. bigtalk-1/bigtalk/kernels.py +69 -0
  9. bigtalk-1/bigtalk/locater.py +86 -0
  10. bigtalk-1/bigtalk/loggers.py +37 -0
  11. bigtalk-1/bigtalk/message.py +46 -0
  12. bigtalk-1/bigtalk/methods.py +139 -0
  13. bigtalk-1/bigtalk/objects.py +99 -0
  14. bigtalk-1/bigtalk/package.py +79 -0
  15. bigtalk-1/bigtalk/persist.py +69 -0
  16. bigtalk-1/bigtalk/repeats.py +63 -0
  17. bigtalk-1/bigtalk/serials.py +53 -0
  18. bigtalk-1/bigtalk/statics.py +52 -0
  19. bigtalk-1/bigtalk/threads.py +92 -0
  20. bigtalk-1/bigtalk/utility.py +245 -0
  21. bigtalk-1/bigtalk/workdir.py +67 -0
  22. bigtalk-1/bigtalk.egg-info/PKG-INFO +70 -0
  23. bigtalk-1/bigtalk.egg-info/SOURCES.txt +49 -0
  24. bigtalk-1/bigtalk.egg-info/dependency_links.txt +1 -0
  25. bigtalk-1/bigtalk.egg-info/top_level.txt +1 -0
  26. bigtalk-1/bin/clean +50 -0
  27. bigtalk-1/mods/atr.py +23 -0
  28. bigtalk-1/mods/flt.py +18 -0
  29. bigtalk-1/mods/fnd.py +31 -0
  30. bigtalk-1/mods/irc.py +657 -0
  31. bigtalk-1/mods/log.py +33 -0
  32. bigtalk-1/mods/lst.py +12 -0
  33. bigtalk-1/mods/man.py +242 -0
  34. bigtalk-1/mods/mbx.py +123 -0
  35. bigtalk-1/mods/mdl.py +447 -0
  36. bigtalk-1/mods/mod.py +8 -0
  37. bigtalk-1/mods/pth.py +12 -0
  38. bigtalk-1/mods/req.py +71 -0
  39. bigtalk-1/mods/rss.py +517 -0
  40. bigtalk-1/mods/rst.py +125 -0
  41. bigtalk-1/mods/sil.py +19 -0
  42. bigtalk-1/mods/slg.py +8 -0
  43. bigtalk-1/mods/tdo.py +49 -0
  44. bigtalk-1/mods/thr.py +33 -0
  45. bigtalk-1/mods/tmr.py +109 -0
  46. bigtalk-1/mods/udp.py +117 -0
  47. bigtalk-1/mods/upt.py +14 -0
  48. bigtalk-1/mods/web.py +138 -0
  49. bigtalk-1/mods/wsd.py +210 -0
  50. bigtalk-1/pyproject.toml +36 -0
  51. bigtalk-1/setup.cfg +4 -0
bigtalk-1/MANIFEST.in ADDED
@@ -0,0 +1,3 @@
1
+ include bin/clean
2
+ include bin/nixt
3
+ recursive-include mods *
bigtalk-1/PKG-INFO ADDED
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: bigtalk
3
+ Version: 1
4
+ Summary: Big Talk
5
+ Author-email: Bart <bthate@dds.nl>
6
+ License-Expression: Unlicense
7
+ Project-URL: home, https://pypi.org/project/bigtalk
8
+ Project-URL: bugs, https://github.com/nixtniet/bigtalk/issues
9
+ Project-URL: source, https://github.com/nixtniet/bigtalk
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Operating System :: Unix
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Utilities
14
+ Description-Content-Type: text/x-rst
15
+
16
+ B I G T A L K
17
+ =============
18
+
19
+
20
+ **NAME**
21
+
22
+
23
+ |
24
+ | ``bigtalk`` - Big Talk
25
+ |
26
+
27
+
28
+ **SYNOPSIS**
29
+
30
+ ::
31
+
32
+ >>> from bigtalk.objects import Object
33
+ >>> from bigtalk.serials import Jsondumps, loads
34
+ >>> o = Object()
35
+ >>> o.a = "b"
36
+ >>> print(Json.loads(Json.dumps(o)))
37
+ {'a': 'b'}
38
+
39
+
40
+ **DESCRIPTION**
41
+
42
+ BigTalk has all you need to program a unix cli program, such as disk
43
+ perisistence for configuration files, event handler to handle the
44
+ client/server connection, etc.
45
+
46
+ BiGTalk contains python3 code to program objects in a functional
47
+ way. it provides an “clean namespace” Object class that only has
48
+ dunder methods, so the namespace is not cluttered with method names.
49
+ This makes storing and reading to/from json possible.
50
+
51
+
52
+ **INSTALL**
53
+
54
+ installation is done with pip
55
+
56
+ |
57
+ | ``$ pip install bigtalk``
58
+ |
59
+
60
+ **AUTHOR**
61
+
62
+ |
63
+ | Bart Thate <``bthate@dds.nl``>
64
+ |
65
+
66
+ **COPYRIGHT**
67
+
68
+ |
69
+ | ``BigTalk`` is Public Domain.
70
+ |
bigtalk-1/README.rst ADDED
@@ -0,0 +1,55 @@
1
+ B I G T A L K
2
+ =============
3
+
4
+
5
+ **NAME**
6
+
7
+
8
+ |
9
+ | ``bigtalk`` - Big Talk
10
+ |
11
+
12
+
13
+ **SYNOPSIS**
14
+
15
+ ::
16
+
17
+ >>> from bigtalk.objects import Object
18
+ >>> from bigtalk.serials import Jsondumps, loads
19
+ >>> o = Object()
20
+ >>> o.a = "b"
21
+ >>> print(Json.loads(Json.dumps(o)))
22
+ {'a': 'b'}
23
+
24
+
25
+ **DESCRIPTION**
26
+
27
+ BigTalk has all you need to program a unix cli program, such as disk
28
+ perisistence for configuration files, event handler to handle the
29
+ client/server connection, etc.
30
+
31
+ BiGTalk contains python3 code to program objects in a functional
32
+ way. it provides an “clean namespace” Object class that only has
33
+ dunder methods, so the namespace is not cluttered with method names.
34
+ This makes storing and reading to/from json possible.
35
+
36
+
37
+ **INSTALL**
38
+
39
+ installation is done with pip
40
+
41
+ |
42
+ | ``$ pip install bigtalk``
43
+ |
44
+
45
+ **AUTHOR**
46
+
47
+ |
48
+ | Bart Thate <``bthate@dds.nl``>
49
+ |
50
+
51
+ **COPYRIGHT**
52
+
53
+ |
54
+ | ``BigTalk`` is Public Domain.
55
+ |
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )
@@ -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
+ )