avrae-ls 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/PKG-INFO +4 -3
  2. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/README.md +3 -2
  3. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/pyproject.toml +1 -1
  4. avrae_ls-0.3.0/src/avrae_ls/__main__.py +108 -0
  5. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/api.py +113 -10
  6. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/completions.py +298 -36
  7. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/context.py +25 -7
  8. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/diagnostics.py +32 -8
  9. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/runtime.py +161 -36
  10. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/server.py +1 -1
  11. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/signature_help.py +73 -19
  12. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/PKG-INFO +4 -3
  13. avrae_ls-0.3.0/tests/test_completions.py +114 -0
  14. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_diagnostics.py +11 -0
  15. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_gvars.py +41 -0
  16. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_hover.py +37 -0
  17. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_runtime.py +120 -6
  18. avrae_ls-0.2.1/src/avrae_ls/__main__.py +0 -24
  19. avrae_ls-0.2.1/tests/test_completions.py +0 -30
  20. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/LICENSE +0 -0
  21. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/setup.cfg +0 -0
  22. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/__init__.py +0 -0
  23. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/alias_preview.py +0 -0
  24. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/argparser.py +0 -0
  25. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/argument_parsing.py +0 -0
  26. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/config.py +0 -0
  27. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/cvars.py +0 -0
  28. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/dice.py +0 -0
  29. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/parser.py +0 -0
  30. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls/symbols.py +0 -0
  31. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/SOURCES.txt +0 -0
  32. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/dependency_links.txt +0 -0
  33. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/entry_points.txt +0 -0
  34. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/requires.txt +0 -0
  35. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/avrae_ls.egg-info/top_level.txt +0 -0
  36. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/LICENSE +0 -0
  37. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/__init__.py +0 -0
  38. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/exceptions.py +0 -0
  39. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/helpers.py +0 -0
  40. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/interpreter.py +0 -0
  41. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/string.py +0 -0
  42. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/types.py +0 -0
  43. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/utils.py +0 -0
  44. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/src/draconic/versions.py +0 -0
  45. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_alias_preview.py +0 -0
  46. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_api.py +0 -0
  47. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_argument_parsing.py +0 -0
  48. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_cvars.py +0 -0
  49. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_runtime_dice.py +0 -0
  50. {avrae_ls-0.2.1 → avrae_ls-0.3.0}/tests/test_symbols.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: avrae-ls
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Language server for Avrae draconic aliases
5
5
  Author: 1drturtle
6
6
  Requires-Python: >=3.11
@@ -23,7 +23,7 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
23
23
 
24
24
  ## Install (released package)
25
25
 
26
- - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `uv tool run avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
26
+ - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
27
27
 
28
28
  ## VS Code extension (released)
29
29
 
@@ -37,10 +37,11 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
37
37
  - Build everything locally: `make package` (wheel + VSIX in `dist/`).
38
38
  - Run tests/lint: `make check`.
39
39
  - Run via uv tool from source: `uv tool install --from . avrae-ls`.
40
+ - Run diagnostics for a single file (stdout + stderr logs): `avrae-ls --analyze path/to/alias.txt --log-level DEBUG`.
40
41
 
41
42
  ## Releasing (maintainers)
42
43
 
43
44
  1. Bump `pyproject.toml` version.
44
- 2. `make release` (clean, build, `twine check`, upload to PyPI).
45
+ 2. `make release` (clean, build, upload to PyPI).
45
46
  3. Build and attach the VSIX to the GitHub release (`make vsix`).
46
47
  4. Tag and push.
@@ -4,7 +4,7 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
4
4
 
5
5
  ## Install (released package)
6
6
 
7
- - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `uv tool run avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
7
+ - CLI/server via `uv tool` (preferred): `uv tool install avrae-ls` then `avrae-ls --help` to see stdio/TCP options (same as `python -m avrae_ls`). The VS Code extension uses this invocation by default. The draconic interpreter is vendored, so no Git deps are needed.
8
8
 
9
9
  ## VS Code extension (released)
10
10
 
@@ -18,10 +18,11 @@ Language Server Protocol (LSP) implementation targeting Avrae-style draconic ali
18
18
  - Build everything locally: `make package` (wheel + VSIX in `dist/`).
19
19
  - Run tests/lint: `make check`.
20
20
  - Run via uv tool from source: `uv tool install --from . avrae-ls`.
21
+ - Run diagnostics for a single file (stdout + stderr logs): `avrae-ls --analyze path/to/alias.txt --log-level DEBUG`.
21
22
 
22
23
  ## Releasing (maintainers)
23
24
 
24
25
  1. Bump `pyproject.toml` version.
25
- 2. `make release` (clean, build, `twine check`, upload to PyPI).
26
+ 2. `make release` (clean, build, upload to PyPI).
26
27
  3. Build and attach the VSIX to the GitHub release (`make vsix`).
27
28
  4. Tag and push.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "avrae-ls"
7
- version = "0.2.1"
7
+ version = "0.3.0"
8
8
  description = "Language server for Avrae draconic aliases"
9
9
  authors = [
10
10
  { name = "1drturtle" }
@@ -0,0 +1,108 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import asyncio
5
+ import logging
6
+ import sys
7
+ from pathlib import Path
8
+ from typing import Iterable
9
+
10
+ from lsprotocol import types
11
+
12
+ from .config import CONFIG_FILENAME, load_config
13
+ from .context import ContextBuilder
14
+ from .diagnostics import DiagnosticProvider
15
+ from .runtime import MockExecutor
16
+ from .server import create_server
17
+
18
+
19
+ def main(argv: list[str] | None = None) -> None:
20
+ parser = argparse.ArgumentParser(description="Avrae draconic alias language server")
21
+ parser.add_argument("--tcp", action="store_true", help="Run in TCP mode instead of stdio")
22
+ parser.add_argument("--host", default="127.0.0.1", help="TCP host (when --tcp is set)")
23
+ parser.add_argument("--port", type=int, default=2087, help="TCP port (when --tcp is set)")
24
+ parser.add_argument("--stdio", action="store_true", help="Accept stdio flag for VS Code clients (ignored)")
25
+ parser.add_argument("--log-level", default="WARNING", help="Logging level (DEBUG, INFO, WARNING, ERROR)")
26
+ parser.add_argument("--analyze", metavar="FILE", help="Run diagnostics for a file and print them to stdout")
27
+ args = parser.parse_args(argv)
28
+
29
+ _configure_logging(args.log_level)
30
+
31
+ if args.analyze:
32
+ if args.tcp:
33
+ parser.error("--analyze cannot be combined with --tcp")
34
+ sys.exit(_run_analysis(Path(args.analyze)))
35
+
36
+ server = create_server()
37
+ if args.tcp:
38
+ server.start_tcp(args.host, args.port)
39
+ else:
40
+ server.start_io()
41
+
42
+
43
+ def _configure_logging(level: str) -> None:
44
+ numeric = getattr(logging, level.upper(), logging.WARNING)
45
+ if not isinstance(numeric, int):
46
+ numeric = logging.WARNING
47
+ logging.basicConfig(
48
+ level=numeric,
49
+ format="%(levelname)s %(name)s: %(message)s",
50
+ )
51
+
52
+
53
+ def _run_analysis(path: Path) -> int:
54
+ if not path.exists():
55
+ print(f"File not found: {path}", file=sys.stderr)
56
+ return 2
57
+
58
+ workspace_root = _discover_workspace_root(path)
59
+ log = logging.getLogger(__name__)
60
+ log.info("Analyzing %s (workspace root: %s)", path, workspace_root)
61
+
62
+ config, warnings = load_config(workspace_root)
63
+ for warning in warnings:
64
+ log.warning(warning)
65
+
66
+ builder = ContextBuilder(config)
67
+ ctx_data = builder.build()
68
+ executor = MockExecutor(config.service)
69
+ diagnostics = DiagnosticProvider(executor, config.diagnostics)
70
+
71
+ source = path.read_text()
72
+ results = asyncio.run(diagnostics.analyze(source, ctx_data, builder.gvar_resolver))
73
+ _print_diagnostics(path, results)
74
+ return 1 if results else 0
75
+
76
+
77
+ def _discover_workspace_root(target: Path) -> Path:
78
+ current = target if target.is_dir() else target.parent
79
+ for folder in [current, *current.parents]:
80
+ if (folder / CONFIG_FILENAME).exists():
81
+ return folder
82
+ return current
83
+
84
+
85
+ def _print_diagnostics(path: Path, diagnostics: Iterable[types.Diagnostic]) -> None:
86
+ diags = list(diagnostics)
87
+ if not diags:
88
+ print(f"{path}: no issues found")
89
+ return
90
+
91
+ for diag in diags:
92
+ start = diag.range.start
93
+ severity = _severity_label(diag.severity)
94
+ source = diag.source or "avrae-ls"
95
+ print(f"{path}:{start.line + 1}:{start.character + 1}: {severity} [{source}] {diag.message}")
96
+
97
+
98
+ def _severity_label(severity: types.DiagnosticSeverity | None) -> str:
99
+ if severity is None:
100
+ return "info"
101
+ try:
102
+ return types.DiagnosticSeverity(severity).name.lower()
103
+ except Exception:
104
+ return str(severity).lower()
105
+
106
+
107
+ if __name__ == "__main__":
108
+ main()