Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adding peru override watch #163

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions peru/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ def do_copy(params):
peru override [list]
peru override add <module> <path>
peru override delete <module>
peru override watch
peru override --help

Adding an override tells peru to use the contents of a given directory
Expand All @@ -205,6 +206,7 @@ def do_copy(params):
Options:
-h --help (>'-')> <('-'<) ^('-')^
''')

def do_override(params):
if params.args['add']:
name = params.args['<module>']
Expand All @@ -213,6 +215,8 @@ def do_override(params):
elif params.args['delete']:
key = params.args['<module>']
del params.runtime.overrides[key]
elif params.args['watch']:
params.runtime.watch_overrides()
else:
for module in sorted(params.runtime.overrides):
print('{}: {}'.format(module, params.runtime.get_override(module)))
Expand Down
66 changes: 66 additions & 0 deletions peru/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import os
from pathlib import Path
import tempfile
import logging
import sys
import time

from . import cache
from . import compat
Expand All @@ -11,6 +14,8 @@
from .keyval import KeyVal
from . import parser
from . import plugin
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler


@asyncio.coroutine
Expand Down Expand Up @@ -139,6 +144,67 @@ def print_overrides(self):
self.display.print(' {}: {}'.format(
name, self.get_override(name)))

def watch_overrides(self):
class WatchHandler(LoggingEventHandler):
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')

def on_moved(self, event):
super(LoggingEventHandler, self).on_moved(event)
what = 'directory' if event.is_directory else 'file'
logging.info('moved %s: from %s to %s', what, event.src_path,
event.dest_path)
logging.info('running peru sync --force')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sync and reup commands use a fancy display to draw to the terminal and clean things up as jobs finish. This conflicts with regular printing. The display object (usually runtime.display) has a print method that lets us do regular printing in a way that doesn't screw up the redrawing.

os.system('peru sync --force')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd probably want some way to control whether syncs are done with --force or not. Maybe with a --force flag on the watch command?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than shelling out with os.system, we'd probably want to call directly into imports.checkout the way that do_sync does. That would mean that these functions would need to be coroutines.

Copy link
Member

@oconnor663 oconnor663 Jul 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Peru doesn't currently do any kind of filesystem locking to prevent running multiple commands in parallel in the same project. But if you do that, it could cause weird conflicts and errors. We should definitely add proper locking at some point, but it still also probably makes sense for a watcher to avoid queueing up several waiting instances at once (or running commands that will error out, depending on how we want to implement lock contention).

logging.info('overrides synced')

def on_created(self, event):
super(LoggingEventHandler, self).on_created(event)
what = 'directory' if event.is_directory else 'file'
logging.info('Created %s: %s', what, event.src_path)
logging.info('running peru sync --force')
os.system('peru sync --force')
logging.info('overrides synced')

def on_deleted(self, event):
super(LoggingEventHandler, self).on_deleted(event)
what = 'directory' if event.is_directory else 'file'
logging.info('Deleted %s: %s', what, event.src_path)
logging.info('running peru sync --force')
os.system('peru sync --force')
logging.info('overrides synced')

def on_modified(self, event):
super(LoggingEventHandler, self).on_modified(event)
what = 'directory' if event.is_directory else 'file'
logging.info('Modified %s: %s', what, event.src_path)
logging.info('running peru sync --force')
os.system('peru sync --force')
logging.info('overrides synced')

event_handler = WatchHandler()
observer = Observer()

if not self.overrides:
print('WARNING: no overrides found')
return

print('watching overrides:')
for module in self.overrides:
observer.schedule(event_handler, self.get_override(module), recursive=True)
print(' ' + module)

observer.start()

try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()

observer.join()

def warn_unused_overrides(self):
if self.quiet or self.no_overrides:
return
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_all_resources_filepaths():


def get_install_requires():
dependencies = ['docopt', 'PyYAML']
dependencies = ['docopt', 'PyYAML', 'watchdog']
# Python 3.3 needs extra libs that aren't installed by default.
if sys.version_info < (3, 3):
raise RuntimeError('The minimum supported Python version is 3.3.')
Expand Down