Coding style.
- Since there is only one display, appearance_changed_event can be a module level global in fill3. - Remove all the appearance_changed_event plumbing.
This commit is contained in:
parent
71b9da128b
commit
4150a9a250
5 changed files with 55 additions and 76 deletions
|
|
@ -340,7 +340,7 @@ class Summary:
|
|||
if y >= len(self._entries):
|
||||
self._cursor_position = (x, len(self._entries) - 1)
|
||||
|
||||
async def sync_with_filesystem(self, appearance_changed_event, log=None):
|
||||
async def sync_with_filesystem(self, log=None):
|
||||
start_time = time.time()
|
||||
cache = {}
|
||||
log.log_message("Started loading summary…")
|
||||
|
|
@ -350,7 +350,7 @@ class Summary:
|
|||
await asyncio.sleep(0)
|
||||
self.add_entry(entry)
|
||||
if index % 1000 == 0:
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
cache[entry.path] = entry.change_time
|
||||
duration = time.time() - start_time
|
||||
log.log_message(f"Finished loading summary. {round(duration, 2)} secs")
|
||||
|
|
@ -371,7 +371,7 @@ class Summary:
|
|||
entry.change_time = change_time
|
||||
else:
|
||||
self.on_file_added(path)
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
for path in cache.keys() - all_paths:
|
||||
await asyncio.sleep(0)
|
||||
self.on_file_deleted(path)
|
||||
|
|
@ -565,16 +565,10 @@ class Log:
|
|||
_GREY_BOLD_STYLE = termstr.CharStyle(termstr.Color.grey_100, is_bold=True)
|
||||
_GREEN_STYLE = termstr.CharStyle(termstr.Color.lime)
|
||||
|
||||
def __init__(self, appearance_changed_event):
|
||||
self._appearance_changed_event = appearance_changed_event
|
||||
def __init__(self):
|
||||
self.lines = []
|
||||
self._appearance = None
|
||||
|
||||
def __getstate__(self):
|
||||
state = self.__dict__.copy()
|
||||
state["_appearance_changed_event"] = None
|
||||
return state
|
||||
|
||||
def log_message(self, message, timestamp=None, char_style=None):
|
||||
if isinstance(message, list):
|
||||
message = [part[1] if isinstance(part, tuple) else part for part in message]
|
||||
|
|
@ -588,7 +582,7 @@ class Log:
|
|||
return
|
||||
self.lines.append(line)
|
||||
self._appearance = None
|
||||
self._appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def log_command(self, message, timestamp=None):
|
||||
self.log_message(message, char_style=Log._GREEN_STYLE)
|
||||
|
|
@ -631,20 +625,20 @@ class Help:
|
|||
def _exit_help(self):
|
||||
self.screen._is_help_visible = False
|
||||
|
||||
def on_mouse_input(self, term_code, appearance_changed_event):
|
||||
def on_mouse_input(self, term_code):
|
||||
event = terminal.decode_mouse_input(term_code)
|
||||
if event[1] == terminal.WHEEL_UP_MOUSE:
|
||||
self.view.portal.scroll_up()
|
||||
appearance_changed_event.set()
|
||||
fiil3.APPEARANCE_CHANGED_EVENT.set()
|
||||
elif event[1] == terminal.WHEEL_DOWN_MOUSE:
|
||||
self.view.portal.scroll_down()
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def on_keyboard_input(self, term_code, appearance_changed_event):
|
||||
def on_keyboard_input(self, term_code):
|
||||
action = self.key_map.get(term_code) or self.key_map.get(term_code.lower())
|
||||
if action is not None:
|
||||
action()
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def appearance(self, dimensions):
|
||||
return self.widget.appearance(dimensions)
|
||||
|
|
@ -663,10 +657,9 @@ class Listing:
|
|||
|
||||
class Screen:
|
||||
|
||||
def __init__(self, summary, log, appearance_changed_event, main_loop):
|
||||
def __init__(self, summary, log, main_loop):
|
||||
self._summary = summary
|
||||
self._log = log
|
||||
self._appearance_changed_event = appearance_changed_event
|
||||
self._main_loop = main_loop
|
||||
self._is_summary_focused = True
|
||||
self.workers = None
|
||||
|
|
@ -679,7 +672,6 @@ class Screen:
|
|||
|
||||
def __getstate__(self):
|
||||
state = self.__dict__.copy()
|
||||
state["_appearance_changed_event"] = None
|
||||
state["_main_loop"] = None
|
||||
state["workers"] = None
|
||||
return state
|
||||
|
|
@ -690,8 +682,7 @@ class Screen:
|
|||
worker_ = worker.Worker(is_being_tested, compression)
|
||||
workers.append(worker_)
|
||||
future = worker_.job_runner(self, self._summary, self._log,
|
||||
self._summary._jobs_added_event,
|
||||
self._appearance_changed_event)
|
||||
self._summary._jobs_added_event)
|
||||
worker_.future = future
|
||||
self.workers = workers
|
||||
|
||||
|
|
@ -886,7 +877,7 @@ class Screen:
|
|||
|
||||
def on_mouse_input(self, term_code):
|
||||
if self._is_help_visible:
|
||||
self._help_widget.on_mouse_input(term_code, self._appearance_changed_event)
|
||||
self._help_widget.on_mouse_input(term_code)
|
||||
return
|
||||
event = terminal.decode_mouse_input(term_code)
|
||||
if event[0] not in [terminal.PRESS_MOUSE, terminal.DRAG_MOUSE]:
|
||||
|
|
@ -912,16 +903,16 @@ class Screen:
|
|||
self._select_entry_at_position(
|
||||
x, y, view_width, view_height)
|
||||
self._last_mouse_position = x, y
|
||||
self._appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def on_keyboard_input(self, term_code):
|
||||
if self._is_help_visible:
|
||||
self._help_widget.on_keyboard_input(term_code, self._appearance_changed_event)
|
||||
self._help_widget.on_keyboard_input(term_code)
|
||||
return
|
||||
action = Screen._KEY_MAP.get(term_code) or Screen._KEY_MAP.get(term_code.lower())
|
||||
if action is not None:
|
||||
action(self)
|
||||
self._appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def _fix_listing(self):
|
||||
widget = self._summary.get_selection()
|
||||
|
|
@ -999,29 +990,27 @@ def setup_inotify(root_path, loop, on_filesystem_event, exclude_filter):
|
|||
return pyinotify.AsyncioNotifier(watch_manager, loop, callback=lambda notifier: None)
|
||||
|
||||
|
||||
def load_state(pickle_path, jobs_added_event, appearance_changed_event, root_path, loop):
|
||||
def load_state(pickle_path, jobs_added_event, root_path, loop):
|
||||
is_first_run = True
|
||||
try:
|
||||
with gzip.open(pickle_path, "rb") as file_:
|
||||
screen = pickle.load(file_)
|
||||
except (FileNotFoundError, AttributeError):
|
||||
summary = Summary(root_path, jobs_added_event)
|
||||
log = Log(appearance_changed_event)
|
||||
screen = Screen(summary, log, appearance_changed_event, loop)
|
||||
log = Log()
|
||||
screen = Screen(summary, log, loop)
|
||||
else:
|
||||
is_first_run = False
|
||||
screen._appearance_changed_event = appearance_changed_event
|
||||
screen._main_loop = loop
|
||||
summary = screen._summary
|
||||
summary._jobs_added_event = jobs_added_event
|
||||
summary._root_path = root_path
|
||||
summary.clear_running()
|
||||
log = screen._log
|
||||
log._appearance_changed_event = appearance_changed_event
|
||||
return summary, screen, log, is_first_run
|
||||
|
||||
|
||||
def on_filesystem_event(event, summary, root_path, appearance_changed_event):
|
||||
def on_filesystem_event(event, summary, root_path):
|
||||
path = list(fix_paths(root_path, [event.pathname]))[0]
|
||||
if is_path_excluded(path[2:]):
|
||||
return
|
||||
|
|
@ -1038,7 +1027,7 @@ def on_filesystem_event(event, summary, root_path, appearance_changed_event):
|
|||
except Exception:
|
||||
tools.log_error()
|
||||
raise KeyboardInterrupt
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
|
||||
def main(root_path, loop, worker_count=None, editor_command=None, theme=None,
|
||||
|
|
@ -1052,15 +1041,13 @@ def main(root_path, loop, worker_count=None, editor_command=None, theme=None,
|
|||
os.environ["PYGMENT_STYLE"] = theme
|
||||
pickle_path = os.path.join(tools.CACHE_PATH, "summary.pickle")
|
||||
jobs_added_event = asyncio.Event()
|
||||
appearance_changed_event = asyncio.Event()
|
||||
summary, screen, log, is_first_run = load_state(pickle_path, jobs_added_event,
|
||||
appearance_changed_event, root_path, loop)
|
||||
summary, screen, log, is_first_run = load_state(pickle_path, jobs_added_event, root_path, loop)
|
||||
screen.editor_command = editor_command
|
||||
log.log_message("Program started.")
|
||||
jobs_added_event.set()
|
||||
|
||||
def callback(event):
|
||||
on_filesystem_event(event, summary, root_path, appearance_changed_event)
|
||||
on_filesystem_event(event, summary, root_path)
|
||||
notifier = setup_inotify(root_path, loop, callback, is_path_excluded)
|
||||
try:
|
||||
log.log_message(f"Starting workers ({worker_count}) …")
|
||||
|
|
@ -1071,11 +1058,11 @@ def main(root_path, loop, worker_count=None, editor_command=None, theme=None,
|
|||
time.sleep(0.05)
|
||||
screen.stop_workers()
|
||||
loop.stop()
|
||||
loop.create_task(summary.sync_with_filesystem(appearance_changed_event, log))
|
||||
loop.create_task(summary.sync_with_filesystem(log))
|
||||
for worker_ in screen.workers:
|
||||
loop.create_task(worker_.future)
|
||||
if sys.stdout.isatty():
|
||||
with fill3.context(loop, appearance_changed_event, screen, exit_loop=exit_loop):
|
||||
with fill3.context(loop, screen, exit_loop=exit_loop):
|
||||
loop.run_forever()
|
||||
log.log_message("Program stopped.")
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -559,18 +559,18 @@ class Result:
|
|||
def is_completed(self):
|
||||
return self.status in Result.COMPLETED_STATUSES
|
||||
|
||||
async def run(self, log, appearance_changed_event, runner):
|
||||
async def run(self, log, runner):
|
||||
tool_name = tool_name_colored(self.tool, self.path)
|
||||
path = path_colored(self.path)
|
||||
log.log_message(["Running ", tool_name, " on ", path, "…"])
|
||||
self.set_status(Status.running)
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
start_time = time.time()
|
||||
new_status = await runner.run_tool(self.path, self.tool)
|
||||
Result.result.fget.evict(self)
|
||||
end_time = time.time()
|
||||
self.set_status(new_status)
|
||||
appearance_changed_event.set()
|
||||
fill3.APPEARANCE_CHANGED_EVENT.set()
|
||||
log.log_message(["Finished running ", tool_name, " on ", path, ". ",
|
||||
STATUS_TO_TERMSTR[new_status], f" {round(end_time - start_time, 2)} secs"])
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class Worker:
|
|||
break
|
||||
return tools.Status(int(data))
|
||||
|
||||
async def job_runner(self, screen, summary, log, jobs_added_event, appearance_changed_event):
|
||||
async def job_runner(self, screen, summary, log, jobs_added_event):
|
||||
await self.create_process()
|
||||
while True:
|
||||
await jobs_added_event.wait()
|
||||
|
|
@ -55,7 +55,7 @@ class Worker:
|
|||
except StopAsyncIteration:
|
||||
self.result = None
|
||||
break
|
||||
await self.result.run(log, appearance_changed_event, self)
|
||||
await self.result.run(log, self)
|
||||
self.result.compression = self.compression
|
||||
Worker.unsaved_jobs_total += 1
|
||||
if Worker.unsaved_jobs_total == 5000 and summary.is_loaded:
|
||||
|
|
|
|||
|
|
@ -50,11 +50,9 @@ class ScreenWidgetTestCase(unittest.TestCase):
|
|||
foo_path = os.path.join(project_dir, "foo.py")
|
||||
_touch(foo_path)
|
||||
jobs_added_event = asyncio.Event()
|
||||
appearance_changed_event = asyncio.Event()
|
||||
summary = __main__.Summary(project_dir, jobs_added_event)
|
||||
log = __main__.Log(appearance_changed_event)
|
||||
self.main_widget = __main__.Screen(
|
||||
summary, log, appearance_changed_event, _MockMainLoop())
|
||||
log = __main__.Log()
|
||||
self.main_widget = __main__.Screen(summary, log, _MockMainLoop())
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.temp_dir)
|
||||
|
|
@ -123,20 +121,17 @@ class SummarySyncWithFilesystemTestCase(unittest.TestCase):
|
|||
self.bar_path = os.path.join(self.temp_dir, "bar.md")
|
||||
self.zoo_path = os.path.join(self.temp_dir, "zoo.html")
|
||||
self.jobs_added_event = asyncio.Event()
|
||||
self.appearance_changed_event = asyncio.Event()
|
||||
self.summary = __main__.Summary(self.temp_dir, self.jobs_added_event)
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
def callback(event):
|
||||
__main__.on_filesystem_event(event, self.summary, self.temp_dir,
|
||||
self.appearance_changed_event)
|
||||
__main__.on_filesystem_event(event, self.summary, self.temp_dir)
|
||||
__main__.setup_inotify(self.temp_dir, self.loop, callback,
|
||||
__main__.is_path_excluded)
|
||||
_touch(self.foo_path)
|
||||
_touch(self.bar_path)
|
||||
self.log = __main__.Log(self.appearance_changed_event)
|
||||
self.loop.run_until_complete(self.summary.sync_with_filesystem(
|
||||
self.appearance_changed_event, self.log))
|
||||
self.log = __main__.Log()
|
||||
self.loop.run_until_complete(self.summary.sync_with_filesystem(self.log))
|
||||
self.jobs_added_event.clear()
|
||||
|
||||
def tearDown(self):
|
||||
|
|
@ -188,9 +183,8 @@ class SummarySyncWithFilesystemTestCase(unittest.TestCase):
|
|||
baz_path = os.path.join(self.temp_dir, "baz")
|
||||
os.symlink(self.foo_path, baz_path)
|
||||
os.link(self.foo_path, self.zoo_path)
|
||||
log = __main__.Log(self.appearance_changed_event)
|
||||
self.loop.run_until_complete(self.summary.sync_with_filesystem(
|
||||
self.appearance_changed_event, log))
|
||||
log = __main__.Log()
|
||||
self.loop.run_until_complete(self.summary.sync_with_filesystem(log))
|
||||
self._assert_paths(["./bar.md", "./baz", "./foo", "./zoo.html"])
|
||||
self.assertTrue(id(self.summary._entries[1]) != # baz
|
||||
id(self.summary._entries[2])) # foo
|
||||
|
|
|
|||
|
|
@ -406,30 +406,31 @@ class Fixed:
|
|||
##########################
|
||||
|
||||
|
||||
_last_appearance = []
|
||||
APPEARANCE_CHANGED_EVENT = asyncio.Event()
|
||||
_LAST_APPEARANCE = []
|
||||
|
||||
|
||||
def draw_screen(widget):
|
||||
global _last_appearance
|
||||
global _LAST_APPEARANCE
|
||||
appearance = widget.appearance(os.get_terminal_size())
|
||||
print(terminal.move(0, 0), *appearance, sep="", end="", flush=True)
|
||||
_last_appearance = appearance
|
||||
_LAST_APPEARANCE = appearance
|
||||
|
||||
|
||||
def patch_screen(widget):
|
||||
global _last_appearance
|
||||
global _LAST_APPEARANCE
|
||||
appearance = widget.appearance(os.get_terminal_size())
|
||||
zip_func = (itertools.zip_longest if len(appearance) > len(_last_appearance) else zip)
|
||||
zip_func = (itertools.zip_longest if len(appearance) > len(_LAST_APPEARANCE) else zip)
|
||||
changed_lines = (str(terminal.move(0, row_index)) + line for row_index, (line, old_line)
|
||||
in enumerate(zip_func(appearance, _last_appearance)) if line != old_line)
|
||||
in enumerate(zip_func(appearance, _LAST_APPEARANCE)) if line != old_line)
|
||||
print(*changed_lines, sep="", end="", flush=True)
|
||||
_last_appearance = appearance
|
||||
_LAST_APPEARANCE = appearance
|
||||
|
||||
|
||||
async def update_screen(screen_widget, appearance_changed_event):
|
||||
async def update_screen(screen_widget):
|
||||
while True:
|
||||
await appearance_changed_event.wait()
|
||||
appearance_changed_event.clear()
|
||||
await APPEARANCE_CHANGED_EVENT.wait()
|
||||
APPEARANCE_CHANGED_EVENT.clear()
|
||||
patch_screen(screen_widget)
|
||||
await asyncio.sleep(0.01)
|
||||
|
||||
|
|
@ -453,8 +454,8 @@ def signal_handler(loop, signal_, func):
|
|||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def context(loop, appearance_changed_event, screen_widget, exit_loop=None):
|
||||
appearance_changed_event.set()
|
||||
def context(loop, screen_widget, exit_loop=None):
|
||||
APPEARANCE_CHANGED_EVENT.set()
|
||||
if exit_loop is None:
|
||||
exit_loop = loop.stop
|
||||
with (signal_handler(loop, signal.SIGWINCH, lambda: draw_screen(screen_widget)),
|
||||
|
|
@ -462,7 +463,7 @@ def context(loop, appearance_changed_event, screen_widget, exit_loop=None):
|
|||
signal_handler(loop, signal.SIGTERM, exit_loop), terminal.alternate_buffer(),
|
||||
terminal.interactive(), terminal.mouse_tracking()):
|
||||
update_task = loop.create_task(
|
||||
update_screen(screen_widget, appearance_changed_event))
|
||||
update_screen(screen_widget))
|
||||
try:
|
||||
loop.add_reader(sys.stdin, on_terminal_input, screen_widget)
|
||||
try:
|
||||
|
|
@ -478,8 +479,7 @@ def context(loop, appearance_changed_event, screen_widget, exit_loop=None):
|
|||
|
||||
class _Screen:
|
||||
|
||||
def __init__(self, appearance_changed_event):
|
||||
self._appearance_changed_event = appearance_changed_event
|
||||
def __init__(self):
|
||||
self.content = Filler(Text("Hello World"))
|
||||
|
||||
def appearance(self, dimensions):
|
||||
|
|
@ -490,19 +490,17 @@ class _Screen:
|
|||
asyncio.get_event_loop().stop()
|
||||
else:
|
||||
self.content = Filler(Text(repr(term_code)))
|
||||
self._appearance_changed_event.set()
|
||||
APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
def on_mouse_input(self, term_code):
|
||||
mouse_code = terminal.decode_mouse_input(term_code)
|
||||
self.content = Filler(Text(repr(term_code) + " " + repr(mouse_code)))
|
||||
self._appearance_changed_event.set()
|
||||
APPEARANCE_CHANGED_EVENT.set()
|
||||
|
||||
|
||||
def _main():
|
||||
loop = asyncio.get_event_loop()
|
||||
appearance_changed_event = asyncio.Event()
|
||||
screen = _Screen(appearance_changed_event)
|
||||
with context(loop, appearance_changed_event, screen):
|
||||
with context(loop, _Screen()):
|
||||
loop.run_forever()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue