From 4150a9a25094d18001883b627b657022a469a2e3 Mon Sep 17 00:00:00 2001 From: Andrew Hamilton Date: Mon, 29 Nov 2021 15:57:16 +1000 Subject: [PATCH] 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. --- eris/eris/__main__.py | 63 +++++++++++++++---------------------- eris/eris/tools.py | 6 ++-- eris/eris/worker.py | 4 +-- eris/tests/__main___test.py | 20 +++++------- fill3/fill3/__init__.py | 38 +++++++++++----------- 5 files changed, 55 insertions(+), 76 deletions(-) diff --git a/eris/eris/__main__.py b/eris/eris/__main__.py index da8b618..f38f9be 100755 --- a/eris/eris/__main__.py +++ b/eris/eris/__main__.py @@ -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: diff --git a/eris/eris/tools.py b/eris/eris/tools.py index a843a15..7413066 100755 --- a/eris/eris/tools.py +++ b/eris/eris/tools.py @@ -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"]) diff --git a/eris/eris/worker.py b/eris/eris/worker.py index 7459f1b..69fbd54 100755 --- a/eris/eris/worker.py +++ b/eris/eris/worker.py @@ -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: diff --git a/eris/tests/__main___test.py b/eris/tests/__main___test.py index 5f6b70c..6bc1267 100755 --- a/eris/tests/__main___test.py +++ b/eris/tests/__main___test.py @@ -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 diff --git a/fill3/fill3/__init__.py b/fill3/fill3/__init__.py index bb28aed..b51abb4 100755 --- a/fill3/fill3/__init__.py +++ b/fill3/fill3/__init__.py @@ -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()