initial commit (public reset)
This commit is contained in:
1
execlog/routers/__init__.py
Normal file
1
execlog/routers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from execlog.routers.path import PathRouter
|
||||
90
execlog/routers/path.py
Normal file
90
execlog/routers/path.py
Normal file
@@ -0,0 +1,90 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from execlog.router import Router
|
||||
from execlog.listeners.path import PathListener
|
||||
from execlog.util.path import glob_match
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class PathRouter(Router):
|
||||
def __init__(self, loop=None, workers=None, listener_cls=PathListener):
|
||||
'''
|
||||
Parameters:
|
||||
workers: number of workers to assign the thread pool when the event loop is
|
||||
started. Defaults to `None`, which, when passed to
|
||||
ThreadPoolExecutor, will by default use 5x the number of available
|
||||
processors on the machine (which the docs claim is a reasonable
|
||||
assumption given threads are more commonly leveraged for I/O work
|
||||
rather than intense CPU operations). Given the intended context for
|
||||
this class, this assumption aligns appropriately.
|
||||
'''
|
||||
super().__init__(loop=loop, workers=workers, listener_cls=listener_cls)
|
||||
|
||||
def register(
|
||||
self,
|
||||
path,
|
||||
func,
|
||||
glob='**/!(.*|*.tmp|*~)', # recursive, non-temp
|
||||
debounce=200,
|
||||
delay=30,
|
||||
**listener_kwargs,
|
||||
):
|
||||
'''
|
||||
Parameters:
|
||||
path: Path (directory) to watch with `inotify`
|
||||
func: Callback to run if FS event target matches glob
|
||||
glob: Relative glob pattern to match files in provided path. The FS event's
|
||||
filename must match this pattern for the callback to queued. (Default:
|
||||
"*"; matching all files in path).
|
||||
listener_kwargs: Additional params for associated listener "listen" routes.
|
||||
See `PathListener.listen`.
|
||||
'''
|
||||
super().register(
|
||||
#endpoint=Path(path),
|
||||
endpoint=path,
|
||||
callback=func,
|
||||
pattern=glob,
|
||||
debounce=debounce,
|
||||
delay=delay,
|
||||
**listener_kwargs
|
||||
)
|
||||
|
||||
def filter(self, event, glob, **listen_kwargs) -> bool:
|
||||
'''
|
||||
Note:
|
||||
If `handle_events` is called externally, note that this loop will block in the
|
||||
calling thread until the jobs have been submitted. It will _not_ block until
|
||||
jobs have completed, however, as a list of futures is returned. The calling
|
||||
Watcher instance may have already been started, in which case `run()` will
|
||||
already be executing in a separate thread. Calling this method externally will
|
||||
not interfere with this loop insofar as it adds jobs to the same thread pool.
|
||||
|
||||
Because this method only submits jobs associated with the provided `events`,
|
||||
the calling thread can await the returned list of futures and be confident
|
||||
that top-level callbacks associated with these file events have completed. Do
|
||||
note that, if the Watcher has already been started, any propagating file
|
||||
events will be picked up and possibly process simultaneously (although their
|
||||
associated callbacks will have nothing to do with the return list of futures).
|
||||
|
||||
Parameters:
|
||||
event : Event instance
|
||||
glob : Single string or tuple of glob patterns to check against event endpoint
|
||||
'''
|
||||
not_tmp_glob = '**/!(.*|*.tmp|*~)'
|
||||
if not glob_match(Path(event.name), not_tmp_glob):
|
||||
return False
|
||||
|
||||
listen_flags = listen_kwargs.get('flags')
|
||||
# only filter by flags if explicitly specified on registry
|
||||
# (o/w route likely just wanting to use defaults)
|
||||
if listen_flags is not None:
|
||||
# negative filter if action not one of the listened flags
|
||||
if not any(flag & listen_flags for flag in event.action):
|
||||
logger.debug(
|
||||
f'Event [{event.name}] caught in flag filter under [{glob}] for action [{event.action}]'
|
||||
)
|
||||
return False
|
||||
|
||||
return glob_match(Path(event.name), glob)
|
||||
Reference in New Issue
Block a user