|
|
- # vim: set fileencoding=utf-8 :
-
- """provide a trivial way to send messages between processes
-
- messages are being sent as files to an inbox, which is a path of a directory,
- using a filename as a marker
-
- recv_all() is delivering all messages, which are newer than the marker file
- after completion reading is touching the marker file
-
- to re-read messages touch the marker file with an older timestamp or just
- delete the marker file to re-read all messages
-
- """
-
- # Minimail 1.2
- # Copyleft 2019, 2020, p≡p foundation
-
- # this file is under GNU General Public License 3.0
-
-
- import os
- from secrets import token_urlsafe
- from time import sleep
- from random import random
-
-
- # set timing to None for random timing
- timing = None
-
-
- def snooze():
- if timing is None:
- sleep(random()/2)
- else:
- sleep(timing)
-
- def unlock(inbox):
- "clear the inbox from lockfile"
-
- lockfile = inbox / "lock"
- try:
- lockfile.unlink()
- except:
- pass
-
-
- class Lock:
- "lock inbox context to be used by with statement"
-
- def __init__(self, inbox):
- self.inbox = inbox
-
- def __exit__(self, *exc):
- unlock(self.inbox)
-
- def __enter__(self):
- lockfile = self.inbox / "lock"
- while lockfile.is_file():
- snooze()
- lockfile.touch()
-
-
- def send(inbox, msg, marker):
- "send msg to inbox in MIME format"
-
- snooze()
- with Lock(inbox):
- name = marker + "_" + token_urlsafe(16) + ".eml"
- with open(inbox / name, "wb") as f:
- f.write(str(msg).encode())
-
-
- def newer(file, stamp):
- "return True if file is newer than timestamp stamp"
-
- if not file.is_file():
- return False
-
- if stamp is None:
- return True
-
- stat = file.stat()
- return stat.st_mtime > stamp.st_mtime
-
-
- def recv_all(inbox, marker):
- """receive a list of new MIME messages from inbox, which are newer than the
- marker file"""
-
- r = []
- while not r:
- with Lock(inbox):
- try:
- stamp = (inbox / marker).stat()
- except:
- stamp = None
- l = [ path for path in inbox.glob("*.eml") ]
- (inbox / marker).touch(exist_ok=True)
- for p in reversed(l):
- if newer(p, stamp):
- with open(p, "rb") as f:
- txt = f.read(-1)
- r.append((p, txt))
- if not r:
- snooze()
-
- return r
-
|