rework EventMap
This commit is contained in:
@@ -15,25 +15,125 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
"EventMap"
|
||||||
|
"Watch",
|
||||||
"Pyinotifyd",
|
"Pyinotifyd",
|
||||||
"DaemonInstance",
|
"DaemonInstance",
|
||||||
"main",
|
"scheduler"]
|
||||||
"scheduler",
|
|
||||||
"watch"]
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
|
import pyinotify
|
||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pyinotifyd.watch import EventMap, Watch
|
from pyinotify import ProcessEvent
|
||||||
|
|
||||||
from pyinotifyd._install import install, uninstall
|
from pyinotifyd._install import install, uninstall
|
||||||
|
from pyinotifyd.scheduler import Task
|
||||||
|
|
||||||
__version__ = "0.0.2"
|
__version__ = "0.0.2"
|
||||||
|
|
||||||
|
|
||||||
|
class _TaskList:
|
||||||
|
def __init__(self, tasks=[]):
|
||||||
|
if not isinstance(tasks, list):
|
||||||
|
tasks = [tasks]
|
||||||
|
|
||||||
|
self._tasks = tasks
|
||||||
|
|
||||||
|
def add(self, task):
|
||||||
|
self._tasks.append(task)
|
||||||
|
|
||||||
|
def remove(self, task):
|
||||||
|
self._tasks.remove(task)
|
||||||
|
|
||||||
|
def execute(self, event):
|
||||||
|
for task in self._tasks:
|
||||||
|
task.start(event)
|
||||||
|
|
||||||
|
|
||||||
|
class EventMap(ProcessEvent):
|
||||||
|
flags = {
|
||||||
|
**pyinotify.EventsCodes.OP_FLAGS,
|
||||||
|
**pyinotify.EventsCodes.EVENT_FLAGS}
|
||||||
|
|
||||||
|
def __init__(self, event_map=None, default_task=None, *args, **kwargs):
|
||||||
|
super().__init__(*args, *kwargs)
|
||||||
|
|
||||||
|
if default_task is not None:
|
||||||
|
for flag in EventMap.flags:
|
||||||
|
self.set(flag, default_task)
|
||||||
|
|
||||||
|
if event_map is not None:
|
||||||
|
assert isinstance(event_map, dict), \
|
||||||
|
f"event_map: expected {type(dict)}, got {type(event_map)}"
|
||||||
|
for flag, tasks in event_map.items():
|
||||||
|
self.set(flag, tasks)
|
||||||
|
|
||||||
|
def set(self, flag, tasks):
|
||||||
|
assert flag in EventMap.flags, \
|
||||||
|
f"event_map: invalid flag: {flag}"
|
||||||
|
if tasks is not None:
|
||||||
|
if not isinstance(tasks, list):
|
||||||
|
tasks = [tasks]
|
||||||
|
|
||||||
|
task_instances = []
|
||||||
|
for task in tasks:
|
||||||
|
if not issubclass(type(task), Task):
|
||||||
|
task = Task(task)
|
||||||
|
|
||||||
|
task_instances.append(task)
|
||||||
|
setattr(self, f"process_{flag}", _TaskList(task_instances).execute)
|
||||||
|
|
||||||
|
elif hasattr(self, flag):
|
||||||
|
delattr(self, f"process_{flag}")
|
||||||
|
|
||||||
|
|
||||||
|
class Watch:
|
||||||
|
def __init__(self, path, event_map=None, default_task=None, rec=False,
|
||||||
|
auto_add=False, logname="watch"):
|
||||||
|
assert isinstance(path, str), \
|
||||||
|
f"path: expected {type('')}, got {type(path)}"
|
||||||
|
|
||||||
|
if isinstance(event_map, EventMap):
|
||||||
|
self._event_map = event_map
|
||||||
|
else:
|
||||||
|
self._event_map = EventMap(event_map, default_task)
|
||||||
|
|
||||||
|
assert isinstance(rec, bool), \
|
||||||
|
f"rec: expected {type(bool)}, got {type(rec)}"
|
||||||
|
assert isinstance(auto_add, bool), \
|
||||||
|
f"auto_add: expected {type(bool)}, got {type(auto_add)}"
|
||||||
|
logname = (logname or __name__)
|
||||||
|
|
||||||
|
self._path = path
|
||||||
|
self._rec = rec
|
||||||
|
self._auto_add = auto_add
|
||||||
|
|
||||||
|
self._watch_manager = pyinotify.WatchManager()
|
||||||
|
self._notifier = None
|
||||||
|
self._log = logging.getLogger(logname)
|
||||||
|
|
||||||
|
def path(self):
|
||||||
|
return self._path
|
||||||
|
|
||||||
|
def start(self, loop=asyncio.get_event_loop()):
|
||||||
|
self._watch_manager.add_watch(self._path, pyinotify.ALL_EVENTS,
|
||||||
|
rec=self._rec, auto_add=self._auto_add,
|
||||||
|
do_glob=True)
|
||||||
|
|
||||||
|
self._notifier = pyinotify.AsyncioNotifier(
|
||||||
|
self._watch_manager, loop, default_proc_fun=self._event_map)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._notifier.stop()
|
||||||
|
|
||||||
|
self._notifier = None
|
||||||
|
|
||||||
|
|
||||||
class Pyinotifyd:
|
class Pyinotifyd:
|
||||||
name = "pyinotifyd"
|
name = "pyinotifyd"
|
||||||
|
|
||||||
@@ -48,10 +148,9 @@ class Pyinotifyd:
|
|||||||
def from_cfg_file(config_file):
|
def from_cfg_file(config_file):
|
||||||
config = {}
|
config = {}
|
||||||
name = Pyinotifyd.name
|
name = Pyinotifyd.name
|
||||||
exec(f"import logging", {}, config)
|
exec("import logging", {}, config)
|
||||||
exec(f"from {name} import Pyinotifyd", {}, config)
|
exec(f"from {name} import Pyinotifyd, EventMap, Watch", {}, config)
|
||||||
exec(f"from {name}.scheduler import *", {}, config)
|
exec(f"from {name}.scheduler import *", {}, config)
|
||||||
exec(f"from {name}.watch import *", {}, config)
|
|
||||||
with open(config_file, "r") as fh:
|
with open(config_file, "r") as fh:
|
||||||
exec(fh.read(), {}, config)
|
exec(fh.read(), {}, config)
|
||||||
instance = config[f"{name}"]
|
instance = config[f"{name}"]
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Task",
|
"Task",
|
||||||
|
"Cancel",
|
||||||
"TaskScheduler",
|
"TaskScheduler",
|
||||||
"ShellScheduler",
|
"ShellScheduler",
|
||||||
"FileManagerRule",
|
"FileManagerRule",
|
||||||
@@ -53,8 +54,18 @@ class Task:
|
|||||||
event, task_id, *args, **kwargs))
|
event, task_id, *args, **kwargs))
|
||||||
return (task_id, task)
|
return (task_id, task)
|
||||||
|
|
||||||
def log(self, event):
|
def cancel(self, event):
|
||||||
self._log.info(f"LOG: {event}")
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Cancel(Task):
|
||||||
|
def __init__(self, task):
|
||||||
|
assert issubclass(type(task), Task), \
|
||||||
|
f"task: expected {type(Task)}, got {type(task)}"
|
||||||
|
self._task = task
|
||||||
|
|
||||||
|
def start(self, event, *args, **kwargs):
|
||||||
|
self._task.cancel(event)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
@@ -1,126 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
# pyinotifyd is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# pyinotifyd is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with pyinotifyd. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"EventMap",
|
|
||||||
"Watch"]
|
|
||||||
|
|
||||||
import asyncio
|
|
||||||
import pyinotify
|
|
||||||
|
|
||||||
|
|
||||||
class EventMap:
|
|
||||||
flags = {
|
|
||||||
**pyinotify.EventsCodes.OP_FLAGS,
|
|
||||||
**pyinotify.EventsCodes.EVENT_FLAGS}
|
|
||||||
|
|
||||||
def __init__(self, event_map=None, default_task=None):
|
|
||||||
self._map = {}
|
|
||||||
|
|
||||||
if default_task is not None:
|
|
||||||
assert callable(default_task), \
|
|
||||||
f"default_task: expected callable, got {type(default_task)}"
|
|
||||||
for flag in EventMap.flags:
|
|
||||||
self.set(flag, default_task)
|
|
||||||
|
|
||||||
if event_map is not None:
|
|
||||||
assert isinstance(event_map, dict), \
|
|
||||||
f"event_map: expected {type(dict)}, got {type(event_map)}"
|
|
||||||
for flag, task in event_map.items():
|
|
||||||
self.set(flag, task)
|
|
||||||
|
|
||||||
def items(self):
|
|
||||||
return self._map.items()
|
|
||||||
|
|
||||||
def set(self, flag, values):
|
|
||||||
assert flag in EventMap.flags, \
|
|
||||||
f"event_map: invalid flag: {flag}"
|
|
||||||
if values is not None:
|
|
||||||
if not isinstance(values, list):
|
|
||||||
values = [values]
|
|
||||||
|
|
||||||
for value in values:
|
|
||||||
assert callable(value), \
|
|
||||||
f"event_map: {flag}: expected callable, got {type(value)}"
|
|
||||||
|
|
||||||
self._map[flag] = values
|
|
||||||
elif flag in self._map:
|
|
||||||
del self._map[flag]
|
|
||||||
|
|
||||||
|
|
||||||
class _TaskList:
|
|
||||||
def __init__(self, tasks=[]):
|
|
||||||
if not isinstance(tasks, list):
|
|
||||||
tasks = [tasks]
|
|
||||||
|
|
||||||
self._tasks = tasks
|
|
||||||
|
|
||||||
def add(self, task):
|
|
||||||
self._tasks.append(task)
|
|
||||||
|
|
||||||
def remove(self, task):
|
|
||||||
self._tasks.remove(task)
|
|
||||||
|
|
||||||
def execute(self, event):
|
|
||||||
for task in self._tasks:
|
|
||||||
task(event)
|
|
||||||
|
|
||||||
|
|
||||||
class Watch:
|
|
||||||
def __init__(self, path, event_map, rec=False, auto_add=False,
|
|
||||||
logname="watch"):
|
|
||||||
assert isinstance(path, str), \
|
|
||||||
f"path: expected {type('')}, got {type(path)}"
|
|
||||||
if isinstance(event_map, EventMap):
|
|
||||||
self._event_map = event_map
|
|
||||||
elif isinstance(event_map, dict):
|
|
||||||
self._event_map = EventMap(event_map)
|
|
||||||
else:
|
|
||||||
raise AssertionError(
|
|
||||||
f"event_map: expected {type(EventMap)} or {type(dict)}, "
|
|
||||||
f"got {type(event_map)}")
|
|
||||||
|
|
||||||
assert isinstance(rec, bool), \
|
|
||||||
f"rec: expected {type(bool)}, got {type(rec)}"
|
|
||||||
assert isinstance(auto_add, bool), \
|
|
||||||
f"auto_add: expected {type(bool)}, got {type(auto_add)}"
|
|
||||||
|
|
||||||
self._path = path
|
|
||||||
self._rec = rec
|
|
||||||
self._auto_add = auto_add
|
|
||||||
|
|
||||||
self._watch_manager = pyinotify.WatchManager()
|
|
||||||
self._notifier = None
|
|
||||||
|
|
||||||
def path(self):
|
|
||||||
return self._path
|
|
||||||
|
|
||||||
def start(self, loop=asyncio.get_event_loop()):
|
|
||||||
handler = pyinotify.ProcessEvent()
|
|
||||||
for flag, values in self._event_map.items():
|
|
||||||
setattr(handler, f"process_{flag}", _TaskList(values).execute)
|
|
||||||
|
|
||||||
self._watch_manager.add_watch(self._path, pyinotify.ALL_EVENTS,
|
|
||||||
rec=self._rec, auto_add=self._auto_add,
|
|
||||||
do_glob=True)
|
|
||||||
|
|
||||||
self._notifier = pyinotify.AsyncioNotifier(
|
|
||||||
self._watch_manager, loop, default_proc_fun=handler)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
self._notifier.stop()
|
|
||||||
|
|
||||||
self._notifier = None
|
|
||||||
Reference in New Issue
Block a user