Make keyboard monitoring optional (#259) (#260)

* Make keyboard monitoring optional (#259)

* release version 0.9.9
This commit is contained in:
Bo
2025-09-17 08:58:24 -05:00
committed by GitHub
parent 5cd86e7068
commit 9bb9d0b944
10 changed files with 1296 additions and 1237 deletions

View File

@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
None yet. ## [0.9.9]
- [Issue 259](https://github.com/BoPeng/ai-marketplace-monitor/pull/259). Disallow keyboard monitoring by default.
## [0.9.8] ## [0.9.8]

View File

@@ -60,7 +60,7 @@ Features
- **Search Statistics**: Track pages searched, listings examined, and matches found - **Search Statistics**: Track pages searched, listings examined, and matches found
- **Performance Metrics**: Monitor search frequency and success rates - **Performance Metrics**: Monitor search frequency and success rates
- **Interactive Mode**: Real-time statistics and manual listing checks - **Interactive Mode**: Real-time statistics and manual listing checks (optional)
- **Persistent Counters**: Statistics maintained across program restarts - **Persistent Counters**: Statistics maintained across program restarts
- **Individual Listing Analysis**: Debug why specific listings were included or excluded - **Individual Listing Analysis**: Debug why specific listings were included or excluded

View File

@@ -223,10 +223,8 @@ Logs are typically saved to:
**Interactive debugging** **Interactive debugging**
While monitor is running: - Use option ``--check URL`` when starting ai-marketplace-monitor to test individual listings
- Press ``Esc`` to view statistics - Enter interactive mode by pressing any key while monitor is running. This feature requires the installation of `pynput` package.
- Use ``--check URL`` to test individual listings
- Enter interactive mode to debug specific issues
Getting Help Getting Help
============ ============

View File

@@ -74,6 +74,14 @@ While the monitor is running, you can:
- Enter interactive mode to check individual URLs - Enter interactive mode to check individual URLs
- Type ``exit`` to leave interactive mode - Type ``exit`` to leave interactive mode
* This feature requires the installation of `pynput` package, which can be installed separately or through
```bash
pip install 'ai-marketplace-monitor[pynput]'
```
You can disable this feature by define environment variable `DISABLE_PYNPUT=true` if `pynput` is already installed.
Cost Considerations Cost Considerations
------------------ ------------------

View File

@@ -1,7 +1,7 @@
[project] [project]
readme = "README.md" readme = "README.md"
name = "ai-marketplace-monitor" name = "ai-marketplace-monitor"
version = "0.9.8" version = "0.9.9"
description = "An AI-based tool for monitoring facebook marketplace" description = "An AI-based tool for monitoring facebook marketplace"
authors = [{ name = "Bo Peng", email = "ben.bob@gmail.com" }] authors = [{ name = "Bo Peng", email = "ben.bob@gmail.com" }]
requires-python = ">=3.10" requires-python = ">=3.10"
@@ -28,7 +28,6 @@ dependencies = [
"humanize>=4.0.0", "humanize>=4.0.0",
"schedule>=1.2.2", "schedule>=1.2.2",
"inflect>=7.0.0", "inflect>=7.0.0",
"pynput>=1.7.0",
"pillow>=10.0.0", "pillow>=10.0.0",
"jinja2>=3.0.0", "jinja2>=3.0.0",
"pyparsing>=3.1.0", "pyparsing>=3.1.0",
@@ -50,6 +49,7 @@ Documentation = "https://ai-marketplace-monitor.readthedocs.io"
ai-marketplace-monitor = "ai_marketplace_monitor.cli:app" ai-marketplace-monitor = "ai_marketplace_monitor.cli:app"
[project.optional-dependencies] [project.optional-dependencies]
pynput = ["pynput>=1.7.0"]
dev = [ dev = [
"pre-commit>=4.0.1", "pre-commit>=4.0.1",
"invoke>=2.2.0", "invoke>=2.2.0",

View File

@@ -2,4 +2,4 @@
__author__ = """Bo Peng""" __author__ = """Bo Peng"""
__email__ = "ben.bob@gmail.com" __email__ = "ben.bob@gmail.com"
__version__ = "0.9.8" __version__ = "0.9.9"

View File

@@ -32,10 +32,10 @@ from rich.pretty import pretty_repr
try: try:
from pynput import keyboard # type: ignore from pynput import keyboard # type: ignore
pynput_installed = True pynput_enabled = os.environ.get("DISABLE_PYNPUT", "").lower() not in ("1", "y", "true", "yes")
except ImportError: except ImportError:
# some platforms are not supported # some platforms are not supported
pynput_installed = False pynput_enabled = False
import io import io
@@ -136,7 +136,7 @@ class KeyboardMonitor:
self._confirmed: bool | None = None self._confirmed: bool | None = None
def start(self: "KeyboardMonitor") -> None: def start(self: "KeyboardMonitor") -> None:
if pynput_installed: if pynput_enabled:
self._listener = keyboard.Listener(on_press=self.handle_key_press) self._listener = keyboard.Listener(on_press=self.handle_key_press)
self._listener.start() # start to listen on a separate thread self._listener.start() # start to listen on a separate thread
@@ -183,7 +183,7 @@ class KeyboardMonitor:
def set_paused(self: "KeyboardMonitor", paused: bool = True) -> None: def set_paused(self: "KeyboardMonitor", paused: bool = True) -> None:
self._paused = paused self._paused = paused
if pynput_installed: if pynput_enabled:
def handle_key_press( def handle_key_press(
self: "KeyboardMonitor", key: keyboard.Key | keyboard.KeyCode | None self: "KeyboardMonitor", key: keyboard.Key | keyboard.KeyCode | None

View File

@@ -226,6 +226,55 @@ def release(c: Context, version: str) -> None:
with open(file_path, "w") as f: with open(file_path, "w") as f:
f.write("\n".join(lines)) f.write("\n".join(lines))
# Update CHANGELOG.md
print("Updating CHANGELOG.md...")
changelog_path = "CHANGELOG.md"
with open(changelog_path, "r") as f:
changelog_content = f.read()
# Find the [Unreleased] section
lines = changelog_content.split("\n")
updated_lines = []
i = 0
while i < len(lines):
if lines[i].strip() == "## [Unreleased]":
# Add the [Unreleased] header
updated_lines.append(lines[i])
# Collect all content under [Unreleased] until the next section
i += 1
unreleased_content = []
while i < len(lines) and not lines[i].startswith("## ["):
if lines[i].strip(): # Non-empty content line
unreleased_content.append(lines[i])
i += 1
# If there's content to move to the new version
if unreleased_content:
# Keep [Unreleased] section empty
updated_lines.append("")
# Add new version section with the content
updated_lines.append(f"## [{version}]")
updated_lines.append("")
updated_lines.extend(unreleased_content)
else:
# Just add empty line after [Unreleased]
updated_lines.append("")
# Continue with the rest of the file (next version sections)
if i < len(lines) and lines[i].startswith("## ["):
updated_lines.append("") # Add blank line before next section
updated_lines.append(lines[i])
i += 1
else:
updated_lines.append(lines[i])
i += 1
# Write back the updated changelog
with open(changelog_path, "w") as f:
f.write("\n".join(updated_lines))
# Clean previous builds # Clean previous builds
print("Cleaning previous builds...") print("Cleaning previous builds...")
_run(c, "rm -fr build/ dist/ *.egg-info") _run(c, "rm -fr build/ dist/ *.egg-info")

View File

@@ -13,7 +13,7 @@ from ai_marketplace_monitor.user import User
def test_version(version: str) -> None: def test_version(version: str) -> None:
"""Sample pytest test function with the pytest fixture as an argument.""" """Sample pytest test function with the pytest fixture as an argument."""
assert version == "0.9.8" assert version == "0.9.9"
def test_listing_cache(temp_cache: Cache, listing: Listing) -> None: def test_listing_cache(temp_cache: Cache, listing: Listing) -> None:

2448
uv.lock generated
View File

File diff suppressed because it is too large Load Diff