Skip to content

feat: add Launcher class with V1/V2 protocol support#19

Open
Garulf wants to merge 3 commits into
mainfrom
feat/launcher-class
Open

feat: add Launcher class with V1/V2 protocol support#19
Garulf wants to merge 3 commits into
mainfrom
feat/launcher-class

Conversation

@Garulf

@Garulf Garulf commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a Launcher ABC that owns FlowLauncher communication, program directory detection, icons, and API access — decoupling I/O protocol from Plugin
  • FlowLauncherV1 preserves the existing one-shot sys.argv[1] protocol with zero breaking changes
  • FlowLauncherV2 implements a persistent JSON-RPC 2.0 loop over stdin/stdout (newline-delimited), with id echoing, lifecycle method handling (initialize, reload_data, close), and transparent query param normalisation
  • Plugin auto-detects V1 vs V2 from plugin.json's Language field — existing plugins need no changes; V2 plugins just set Language: "Python_v2"
  • plugin.launcher.api.change_query(...) and plugin.launcher.icons.admin now available
  • FlowLauncherV1 / FlowLauncherV2 exported from pyflowlauncher for explicit injection

Usage

# Unchanged — auto-detected from plugin.json
plugin = Plugin()
plugin.run()

# Explicit V2
plugin = Plugin(launcher=FlowLauncherV2())
plugin.run()

# Launcher API and icons
plugin.launcher.api.change_query("new query")
plugin.launcher.icons.admin  # → path string or None

Test plan

  • All 84 tests pass (python3 -m pytest tests/ -q)
  • Existing V1 plugin with no changes continues to work
  • Plugin() with no plugin.json falls back to FlowLauncherV1
  • Plugin() with Language: "Python_v2" in plugin.json selects FlowLauncherV2

Garulf added 3 commits June 26, 2026 19:36
- Add Launcher ABC with program directory detection (env var → roaming
  AppData → local AppData → portable walk-up), Icons class access via
  launcher.icons.<name>, and Api class access via launcher.api.*
- Add FlowLauncherV1: wraps JsonRPCClient, preserves existing one-shot
  argv[1] protocol behaviour exactly
- Add FlowLauncherV2: persistent JSON-RPC 2.0 loop over stdin/stdout
  with newline framing, id echoing, lifecycle method handling
  (initialize, reload_data, close), and transparent query param
  normalisation so plugin methods still receive plain strings
- Plugin accepts optional launcher= param; auto-detects V1/V2 from
  plugin.json Language field (python_v2 → V2, else V1) with
  FileNotFoundError fallback to V1 for test environments
- Plugin.run() delegates to launcher; Plugin.settings delegates to
  launcher; Plugin.launcher property exposes the launcher instance
- Add Icons class to icons.py with __getattr__ for flexible icon access
- Add Api class to api.py wrapping existing module functions as statics
- Export FlowLauncherV1, FlowLauncherV2 from pyflowlauncher
- 21 new tests in tests/test_launcher.py; update test_settings to use
  launcher injection instead of patching removed _client attribute
- FlowLauncherV1: remove settings property override that re-parsed
  sys.argv[1] on every access; base Launcher.settings (returns
  self._settings) is now used, set once by run()
- FlowLauncherV2._send_response: send empty ack when result is None
  so Flow Launcher is not left waiting for a response that never comes
- FlowLauncherV2.run: fix null search value passthrough — use `or`
  instead of dict.get default so null values fall through to trimmedQuery
- Plugin._detect_launcher: guard against manifest.language being None
  with `(language or '').lower()` to avoid AttributeError on null field
- Plugin: re-add JsonRPCRequest import removed by previous refactor;
  used in Plugin.action() return annotation
- Icons.__getattr__: raise AttributeError for dunder attribute names
  so copy/pickle protocols work correctly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant