Files
meshcore-bot/pyproject.toml
T
agessaman 003ffb598c refactor(web_viewer): update web viewer integration and dependencies
Added gevent and gevent-websocket as dependencies to improve performance and compatibility. Updated the web viewer launch process to utilize subprocess instead of multiprocessing for better management. Adjusted the method for checking the viewer process status to use polling, ensuring accurate process state handling. Refactored the meshcore-viewer script entry point for consistency.
2026-05-18 22:07:06 -07:00

196 lines
6.6 KiB
TOML

# pyproject.toml
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "meshcore-bot"
version = "0.9.2"
description = "MeshCore Bot with commands for mesh testing, utilities, and service integration."
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"pyserial>=3.5",
"bleak>=0.20.0",
"asyncio-mqtt>=0.11.0",
"configparser>=5.3.0",
"python-dateutil>=2.8.2",
"apscheduler>=3.10.0",
"colorlog>=6.7.0",
"requests>=2.31.0",
"urllib3>=2.0.0",
"pyephem>=4.1.4",
"geopy>=2.3.0",
"maidenhead>=1.4.0",
"pytz>=2023.3",
"aiohttp>=3.8.0",
"meshcore>=2.3.6",
"openmeteo-requests>=1.7.2",
"requests-cache>=1.1.1",
"retry-requests>=1.0.0",
"flask>=2.3.0",
"flask-socketio>=5.3.0",
"gevent>=24.2.1",
"gevent-websocket>=0.10.1",
"meshcore-cli",
"feedparser>=6.0.10",
"paho-mqtt>=1.6.0",
"cryptography>=41.0.0",
"pynacl>=1.5.0",
"aiosqlite>=0.19.0",
]
[project.optional-dependencies]
profanity = ["better-profanity>=0.7.0", "unidecode>=1.3.0"]
geo = ["pycountry>=23.12.0", "us>=2.0.0"]
test = ["pytest>=7.0", "pytest-asyncio>=0.21", "pytest-mock>=3.10", "pytest-cov>=4.0", "pytest-timeout>=2.1.0", "types-requests>=2.31"]
docs = ["mkdocs-material>=9.0.0", "mkdocs-exclude>=1.0.0"]
[project.scripts]
meshcore-bot = "meshcore_bot:main"
meshcore-viewer = "web_viewer._launcher:_main"
[tool.setuptools]
# Include both the main module and the modules package
py-modules = ["meshcore_bot"]
packages = ["shared", "shared.parsers",
"modules", "modules.commands", "modules.commands.alternatives",
"modules.commands.alternatives.inactive", "modules.service_plugins",
"web_viewer"]
[tool.setuptools.package-data]
"*" = ["*.json"]
web_viewer = [
"templates/*.html",
"static/*",
"static/*/*",
"static/*/*/*",
]
[tool.ruff]
line-length = 120
target-version = "py310"
exclude = [".venv", "build", "dist"]
[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B", "C4", "SIM"]
ignore = [
"E501", # line too long (handled by formatter)
# Legacy-code tolerances — pervasive in pre-typed source, not worth a bulk churn:
"E701", # multiple-statements-on-one-line-colon
"E702", # multiple-statements-on-one-line-semicolon
"E711", # comparison-to-none (== None common in legacy)
"E712", # comparison-to-true (== True/False common in legacy)
"E722", # bare-except (used extensively in graceful-degradation patterns)
"E741", # ambiguous-variable-name (l, O, I in legacy loops)
"E402", # module-level import not at top (conditional imports pattern)
"F601", # multi-value-repeated-key-literal (legacy dict pattern)
"B007", # unused-loop-control-variable (rename to _ is a bulk churn)
"B023", # function-uses-loop-variable (legacy closures in packet capture)
"B904", # raise-without-from-in-except (legacy raise pattern)
"C408", # unnecessary-collection-call
"C414", # unnecessary-double-cast-or-process
# pyupgrade rules that would require a bulk typing rewrite — deferred to a code-quality PR:
"UP007", # non-pep604-annotation-union (Union[X, Y] -> X | Y)
"UP035", # deprecated-import (typing.List/Dict/... remain prevalent)
"UP041", # timeout-error-alias (socket.timeout -> TimeoutError)
"UP045", # non-pep604-annotation-optional (Optional[X] -> X | None)
# Simplification suggestions — stylistic, not enforced on legacy code:
"SIM102", # collapsible-if
"SIM103", # needless-bool
"SIM105", # suppressible-exception
"SIM108", # if-else-block-instead-of-if-exp (ternary preference is subjective)
"SIM109", # compare-with-tuple
"SIM110", # reimplemented-builtin
"SIM114", # if-with-same-arms
"SIM115", # open-file-with-context-handler
"SIM117", # multiple-with-statements
"SIM210", # if-expr-with-true-false
]
[tool.ruff.lint.per-file-ignores]
"tests/*" = ["S101"]
# ---------------------------------------------------------------------------
# mypy — incremental strict mode
# ---------------------------------------------------------------------------
# Global baseline: safe non-breaking options.
# Per-module overrides below tighten settings for fully-typed modules.
[tool.mypy]
python_version = "3.11"
ignore_missing_imports = true
warn_unused_ignores = true
warn_return_any = false # too noisy until all modules are annotated
warn_unused_configs = true
no_implicit_optional = true
strict_optional = true
# New modules written with full type annotations get strict treatment.
[[tool.mypy.overrides]]
module = [
"modules.commands.schedule_command",
"modules.service_plugins.webhook_service",
"modules.service_plugins.base_service",
"modules.message_handler",
"modules.utils",
"modules.plugin_loader",
"shared.security_utils",
"modules.commands.base_command",
]
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
no_implicit_optional = true
# Modules with known type errors not yet brought up to strict standard.
# Suppress all mypy errors for these modules until they are fully annotated.
[[tool.mypy.overrides]]
module = [
"modules.core",
"modules.command_manager",
"modules.feed_manager",
"modules.mesh_graph",
"modules.scheduler",
"modules.maintenance",
"modules.transmission_tracker",
"modules.commands.alert_command",
"modules.commands.announcements_command",
"modules.commands.aurora_command",
"modules.commands.channels_command",
"modules.commands.greeter_command",
"modules.commands.help_command",
"modules.commands.joke_command",
"modules.commands.multitest_command",
"modules.commands.prefix_command",
"modules.commands.wx_command",
"modules.commands.alternatives.wx_international",
"modules.commands.trace_command",
"modules.commands.solarforecast_command",
"modules.commands.roll_command",
"modules.commands.repeater_command",
"modules.commands.path_command",
"modules.commands.sports_command",
"modules.commands.aqi_command",
"modules.service_plugins.discord_bridge_service",
"modules.service_plugins.packet_capture_service",
"modules.service_plugins.weather_service",
"web_viewer.app",
"web_viewer.integration",
]
ignore_errors = true
[tool.pytest.ini_options]
# Hard limit every test to 30 s; prevents hangs from blocking I/O or infinite loops.
# Individual tests that legitimately need longer can use @pytest.mark.timeout(N).
timeout = 30
timeout_method = "thread"
asyncio_mode = "auto"
[tool.coverage.run]
source = ["modules"]
omit = ["tests/*", ".venv/*"]
[tool.coverage.report]
fail_under = 35
show_missing = true