-
-
Notifications
You must be signed in to change notification settings - Fork 75
feat(macos): support native title exclusion flags #128
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| from .main import main | ||
| def main(): | ||
| from .main import main as _main | ||
|
|
||
| return _main() | ||
|
|
||
| __all__ = ["main"] | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -123,6 +123,8 @@ var baseurl = "http://localhost:5600" | |||||||||||||||||||||||||||||||||
| var clientHostname = ProcessInfo.processInfo.hostName | ||||||||||||||||||||||||||||||||||
| var clientName = "aw-watcher-window" | ||||||||||||||||||||||||||||||||||
| var bucketName = "\(clientName)_\(clientHostname)" | ||||||||||||||||||||||||||||||||||
| var excludeTitle = false | ||||||||||||||||||||||||||||||||||
| var excludeTitlePatterns: [NSRegularExpression] = [] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| let main = MainThing() | ||||||||||||||||||||||||||||||||||
| var oldHeartbeat: Heartbeat? | ||||||||||||||||||||||||||||||||||
|
|
@@ -140,6 +142,49 @@ encoder.dateEncodingStrategy = .custom({ date, encoder in | |||||||||||||||||||||||||||||||||
| start() | ||||||||||||||||||||||||||||||||||
| RunLoop.main.run() | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| func compileExcludeTitlePattern(_ pattern: String) -> NSRegularExpression { | ||||||||||||||||||||||||||||||||||
| do { | ||||||||||||||||||||||||||||||||||
| return try NSRegularExpression(pattern: pattern, options: [.caseInsensitive]) | ||||||||||||||||||||||||||||||||||
| } catch let regexError { | ||||||||||||||||||||||||||||||||||
| error("Invalid regex pattern: \(pattern) — \(regexError.localizedDescription)") | ||||||||||||||||||||||||||||||||||
| exit(1) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+145
to
+152
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| func parseOptionalArguments(_ arguments: ArraySlice<String>) { | ||||||||||||||||||||||||||||||||||
| var index = arguments.startIndex | ||||||||||||||||||||||||||||||||||
| while index < arguments.endIndex { | ||||||||||||||||||||||||||||||||||
| let argument = arguments[index] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if argument == "--exclude-title" { | ||||||||||||||||||||||||||||||||||
| excludeTitle = true | ||||||||||||||||||||||||||||||||||
| index = arguments.index(after: index) | ||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if argument == "--exclude-titles" { | ||||||||||||||||||||||||||||||||||
| let nextIndex = arguments.index(after: index) | ||||||||||||||||||||||||||||||||||
| guard nextIndex < arguments.endIndex else { | ||||||||||||||||||||||||||||||||||
| error("Missing value for --exclude-titles") | ||||||||||||||||||||||||||||||||||
| exit(1) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| excludeTitlePatterns.append(compileExcludeTitlePattern(arguments[nextIndex])) | ||||||||||||||||||||||||||||||||||
| index = arguments.index(after: nextIndex) | ||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| error("Unknown argument: \(argument)") | ||||||||||||||||||||||||||||||||||
| exit(1) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| func titleShouldBeExcluded(_ title: String) -> Bool { | ||||||||||||||||||||||||||||||||||
| let range = NSRange(title.startIndex..<title.endIndex, in: title) | ||||||||||||||||||||||||||||||||||
| return excludeTitlePatterns.contains { pattern in | ||||||||||||||||||||||||||||||||||
| pattern.firstMatch(in: title, options: [], range: range) != nil | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| func start() { | ||||||||||||||||||||||||||||||||||
| // Arguments should be: | ||||||||||||||||||||||||||||||||||
| // - url + port | ||||||||||||||||||||||||||||||||||
|
|
@@ -148,16 +193,17 @@ func start() { | |||||||||||||||||||||||||||||||||
| // - client_id | ||||||||||||||||||||||||||||||||||
| let arguments = CommandLine.arguments | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Check that we get 4 arguments | ||||||||||||||||||||||||||||||||||
| if arguments.count != 5 { | ||||||||||||||||||||||||||||||||||
| print("Usage: aw-watcher-window <url> <bucket> <hostname> <client>") | ||||||||||||||||||||||||||||||||||
| // Check that we get the 4 required arguments plus any optional flags | ||||||||||||||||||||||||||||||||||
| if arguments.count < 5 { | ||||||||||||||||||||||||||||||||||
| print("Usage: aw-watcher-window <url> <bucket> <hostname> <client> [--exclude-title] [--exclude-titles <pattern> ...]") | ||||||||||||||||||||||||||||||||||
| exit(1) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| baseurl = arguments[1] | ||||||||||||||||||||||||||||||||||
| bucketName = arguments[2] | ||||||||||||||||||||||||||||||||||
| clientHostname = arguments[3] | ||||||||||||||||||||||||||||||||||
| clientName = arguments[4] | ||||||||||||||||||||||||||||||||||
| parseOptionalArguments(arguments.dropFirst(5)) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| guard checkAccess() else { | ||||||||||||||||||||||||||||||||||
| DispatchQueue.main.asyncAfter(deadline: .now() + 10) { | ||||||||||||||||||||||||||||||||||
|
|
@@ -388,6 +434,10 @@ class MainThing { | |||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if excludeTitle || titleShouldBeExcluded(data.title) { | ||||||||||||||||||||||||||||||||||
| data.title = "excluded" | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| let heartbeat = Heartbeat(timestamp: nowTime, data: data) | ||||||||||||||||||||||||||||||||||
| sendHeartbeat(heartbeat) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| def build_swift_command( | ||
| binpath, | ||
| server_address, | ||
| bucket_id, | ||
| client_hostname, | ||
| client_name, | ||
| exclude_title=False, | ||
| exclude_titles=None, | ||
| ): | ||
| command = [binpath, server_address, bucket_id, client_hostname, client_name] | ||
| if exclude_title: | ||
| command.append("--exclude-title") | ||
| for title in exclude_titles or []: | ||
| command.extend(["--exclude-titles", title]) | ||
| return command |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| from aw_watcher_window.macos_cli import build_swift_command | ||
|
|
||
|
|
||
| def test_build_swift_command_omits_optional_filters(): | ||
| command = build_swift_command( | ||
| "/tmp/aw-watcher-window-macos", | ||
| "http://localhost:5600", | ||
| "bucket", | ||
| "host.localdomain", | ||
| "aw-watcher-window", | ||
| ) | ||
|
|
||
| assert command == [ | ||
| "/tmp/aw-watcher-window-macos", | ||
| "http://localhost:5600", | ||
| "bucket", | ||
| "host.localdomain", | ||
| "aw-watcher-window", | ||
| ] | ||
|
|
||
|
|
||
| def test_build_swift_command_passes_title_filters(): | ||
| command = build_swift_command( | ||
| "/tmp/aw-watcher-window-macos", | ||
| "http://localhost:5600", | ||
| "bucket", | ||
| "host.localdomain", | ||
| "aw-watcher-window", | ||
| exclude_title=True, | ||
| exclude_titles=["Zoom", "Slack.*huddle"], | ||
| ) | ||
|
|
||
| assert command == [ | ||
| "/tmp/aw-watcher-window-macos", | ||
| "http://localhost:5600", | ||
| "bucket", | ||
| "host.localdomain", | ||
| "aw-watcher-window", | ||
| "--exclude-title", | ||
| "--exclude-titles", | ||
| "Zoom", | ||
| "--exclude-titles", | ||
| "Slack.*huddle", | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The wrapper function is needed to avoid pulling in
aw_client/aw_corewhen the package is imported (e.g. during test collection), but it changes the identity of the exported symbol:aw_watcher_window.main.__module__is nowaw_watcher_windowinstead ofaw_watcher_window.main, and attributes like__doc__from the realmainare no longer visible. A comment explaining why the deferred import exists would help future readers understand the intent.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!