From 613c7132f9f15e3a71bbb95c0061a4eeb46a2629 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Sun, 4 Feb 2024 09:49:11 -0300 Subject: [PATCH 1/7] Add `exclude_titles` feature for enhanced window title exclusion This commit introduces the `--exclude-titles` argument to the aw-watcher-window module, allowing users to specify a list of window titles or regular expression patterns to exclude from tracking. This new feature is designed to complement the existing `--exclude-title` flag, providing enhanced flexibility for users who need to exclude multiple window titles without breaking compatibility with existing configurations. Key Changes: - Added the `--exclude-titles` argument to the argparse configuration in `config.py`, enabling the specification of multiple exclusion patterns. - Updated the `heartbeat_loop` function in `main.py` to support both `exclude_title` and `exclude_titles`, with `exclude_titles` allowing for an array of titles to be excluded. - Utilized the `re` module for regex pattern matching against window titles, ensuring case-insensitive comparisons. This enhancement ensures that users can now more precisely control which window titles are excluded from tracking, making the aw-watcher-window module more versatile and user-friendly. --- aw_watcher_window/config.py | 8 ++++++++ aw_watcher_window/main.py | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/aw_watcher_window/config.py b/aw_watcher_window/config.py index cfa2c7b..470aa00 100644 --- a/aw_watcher_window/config.py +++ b/aw_watcher_window/config.py @@ -19,6 +19,7 @@ def parse_args(): default_poll_time = config["poll_time"] default_exclude_title = config["exclude_title"] + default_exclude_titles = config["exclude_titles"] default_strategy_macos = config["strategy_macos"] parser = argparse.ArgumentParser( @@ -33,6 +34,13 @@ def parse_args(): action="store_true", default=default_exclude_title, ) + parser.add_argument( + "--exclude-titles", + dest="exclude_titles", + nargs='+', + default=default_exclude_titles, + help="List of window titles or regular expression patterns to exclude from tracking. Can specify multiple titles." + ) parser.add_argument("--verbose", dest="verbose", action="store_true") parser.add_argument( "--poll-time", dest="poll_time", type=float, default=default_poll_time diff --git a/aw_watcher_window/main.py b/aw_watcher_window/main.py index 79b23bd..3751535 100644 --- a/aw_watcher_window/main.py +++ b/aw_watcher_window/main.py @@ -1,5 +1,6 @@ import logging import os +import re import signal import subprocess import sys @@ -92,10 +93,11 @@ def main(): poll_time=args.poll_time, strategy=args.strategy, exclude_title=args.exclude_title, + exclude_titles=args.exclude_titles, ) -def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False): +def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False, exclude_titles=[]): while True: if os.getppid() == 1: logger.info("window-watcher stopped because parent process died") @@ -128,6 +130,12 @@ def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False): if current_window is None: logger.debug("Unable to fetch window, trying again on next poll") else: + if exclude_titles: + for title in exclude_titles: + pattern = re.compile(re.escape(title), re.IGNORECASE) + if pattern.search(current_window["title"]): + current_window["title"] = "excluded" + if exclude_title: current_window["title"] = "excluded" From 25c782339e3a8fa516dcca69efcb03913d46b1a9 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Tue, 6 Feb 2024 06:55:22 -0300 Subject: [PATCH 2/7] Added exclude-titles in default config --- aw_watcher_window/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aw_watcher_window/config.py b/aw_watcher_window/config.py index 470aa00..a66573a 100644 --- a/aw_watcher_window/config.py +++ b/aw_watcher_window/config.py @@ -5,6 +5,7 @@ default_config = """ [aw-watcher-window] exclude_title = false +exclude_titles = [] poll_time = 1.0 strategy_macos = "swift" """.strip() From f822183100237f8c3e815e707b05d1b11f279957 Mon Sep 17 00:00:00 2001 From: Ignacio Perez <67933444+BasileusErwin@users.noreply.github.com> Date: Tue, 7 May 2024 06:30:28 -0300 Subject: [PATCH 3/7] Update aw_watcher_window/main.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Erik Bjäreholt --- aw_watcher_window/main.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/aw_watcher_window/main.py b/aw_watcher_window/main.py index 3751535..110fd14 100644 --- a/aw_watcher_window/main.py +++ b/aw_watcher_window/main.py @@ -130,11 +130,10 @@ def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False, if current_window is None: logger.debug("Unable to fetch window, trying again on next poll") else: - if exclude_titles: - for title in exclude_titles: - pattern = re.compile(re.escape(title), re.IGNORECASE) - if pattern.search(current_window["title"]): - current_window["title"] = "excluded" + for title in exclude_titles: + pattern = re.compile(re.escape(title), re.IGNORECASE) + if pattern.search(current_window["title"]): + current_window["title"] = "excluded" if exclude_title: current_window["title"] = "excluded" From 84adff10e6c060b2e1b93bab117192b12f248ee3 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Tue, 7 May 2024 07:17:01 -0300 Subject: [PATCH 4/7] Changed the helper message and changed how regex is compiled --- aw_watcher_window/config.py | 2 +- aw_watcher_window/main.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aw_watcher_window/config.py b/aw_watcher_window/config.py index a66573a..1e949e1 100644 --- a/aw_watcher_window/config.py +++ b/aw_watcher_window/config.py @@ -40,7 +40,7 @@ def parse_args(): dest="exclude_titles", nargs='+', default=default_exclude_titles, - help="List of window titles or regular expression patterns to exclude from tracking. Can specify multiple titles." + help="List of regular expression patterns to exclude from tracking. Each pattern can match any part of a window title. Use standard regex syntax. For example, to exclude windows containing 'Game', simply use 'Game'. Can specify multiple patterns." ) parser.add_argument("--verbose", dest="verbose", action="store_true") parser.add_argument( diff --git a/aw_watcher_window/main.py b/aw_watcher_window/main.py index 110fd14..eae940e 100644 --- a/aw_watcher_window/main.py +++ b/aw_watcher_window/main.py @@ -130,8 +130,8 @@ def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False, if current_window is None: logger.debug("Unable to fetch window, trying again on next poll") else: - for title in exclude_titles: - pattern = re.compile(re.escape(title), re.IGNORECASE) + patterns = [re.compile(re.escape(title), re.IGNORECASE) for title in exclude_titles] + for pattern in patterns: if pattern.search(current_window["title"]): current_window["title"] = "excluded" From 9ac6fb0d9b4d434025970a074fe548d040be47d2 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Tue, 7 May 2024 09:03:23 -0300 Subject: [PATCH 5/7] Changed patterns to pass by parameter to heartbeat_loop --- aw_watcher_window/main.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/aw_watcher_window/main.py b/aw_watcher_window/main.py index eae940e..6161992 100644 --- a/aw_watcher_window/main.py +++ b/aw_watcher_window/main.py @@ -93,7 +93,7 @@ def main(): poll_time=args.poll_time, strategy=args.strategy, exclude_title=args.exclude_title, - exclude_titles=args.exclude_titles, + exclude_titles=[re.compile(re.escape(title), re.IGNORECASE) for title in args.exclude_titles] ) @@ -130,8 +130,7 @@ def heartbeat_loop(client, bucket_id, poll_time, strategy, exclude_title=False, if current_window is None: logger.debug("Unable to fetch window, trying again on next poll") else: - patterns = [re.compile(re.escape(title), re.IGNORECASE) for title in exclude_titles] - for pattern in patterns: + for pattern in exclude_titles: if pattern.search(current_window["title"]): current_window["title"] = "excluded" From 7eb0823ccacb954f21e503bb9415a5327ebb4896 Mon Sep 17 00:00:00 2001 From: Ignacio Perez Date: Mon, 13 May 2024 09:10:32 -0300 Subject: [PATCH 6/7] Change compile regex --- aw_watcher_window/config.py | 2 +- aw_watcher_window/main.py | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/aw_watcher_window/config.py b/aw_watcher_window/config.py index 1e949e1..a66573a 100644 --- a/aw_watcher_window/config.py +++ b/aw_watcher_window/config.py @@ -40,7 +40,7 @@ def parse_args(): dest="exclude_titles", nargs='+', default=default_exclude_titles, - help="List of regular expression patterns to exclude from tracking. Each pattern can match any part of a window title. Use standard regex syntax. For example, to exclude windows containing 'Game', simply use 'Game'. Can specify multiple patterns." + help="List of window titles or regular expression patterns to exclude from tracking. Can specify multiple titles." ) parser.add_argument("--verbose", dest="verbose", action="store_true") parser.add_argument( diff --git a/aw_watcher_window/main.py b/aw_watcher_window/main.py index 6161992..8d954d5 100644 --- a/aw_watcher_window/main.py +++ b/aw_watcher_window/main.py @@ -31,6 +31,13 @@ def kill_process(pid): except ProcessLookupError: logger.info("Process {} already dead".format(pid)) +def try_compile_title_regex(title): + try: + return re.compile(title, re.IGNORECASE) + except re.error: + logger.error(f"Invalid regex pattern: {title}") + exit(1) + def main(): args = parse_args() @@ -93,7 +100,7 @@ def main(): poll_time=args.poll_time, strategy=args.strategy, exclude_title=args.exclude_title, - exclude_titles=[re.compile(re.escape(title), re.IGNORECASE) for title in args.exclude_titles] + exclude_titles=[try_compile_title_regex(title) for title in args.exclude_titles if title is not None] ) From 2847de26cb972592e8dd361ed53536ba7a888684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Mon, 13 May 2024 15:28:11 +0200 Subject: [PATCH 7/7] Apply suggestions from code review --- aw_watcher_window/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aw_watcher_window/config.py b/aw_watcher_window/config.py index a66573a..81eabc2 100644 --- a/aw_watcher_window/config.py +++ b/aw_watcher_window/config.py @@ -40,7 +40,7 @@ def parse_args(): dest="exclude_titles", nargs='+', default=default_exclude_titles, - help="List of window titles or regular expression patterns to exclude from tracking. Can specify multiple titles." + help="Exclude window titles by regular expression. Can specify multiple times." ) parser.add_argument("--verbose", dest="verbose", action="store_true") parser.add_argument(