confluence-knowledge 0.4.0__tar.gz → 0.4.1__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.
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/PKG-INFO +1 -1
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/pyproject.toml +1 -1
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/cli.py +29 -0
- confluence_knowledge-0.4.1/src/confluence_knowledge/update.py +55 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/PKG-INFO +1 -1
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/SOURCES.txt +3 -1
- confluence_knowledge-0.4.1/tests/test_update.py +40 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/README.md +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/setup.cfg +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/__init__.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/auth.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/client.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/crawl.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract_files.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/index.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/models.lock.json +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/registration.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/retrieval.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/server.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/settings.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/dependency_links.txt +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/entry_points.txt +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/requires.txt +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge.egg-info/top_level.txt +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_agent_doc_consistency.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_client_get_only.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_crawl.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_extract.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_index.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_prepare_models.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_registration.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_retrieval.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_secrets.py +0 -0
- {confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_server_flow.py +0 -0
|
@@ -94,9 +94,21 @@ def _wizard() -> int:
|
|
|
94
94
|
|
|
95
95
|
def _doctor() -> int:
|
|
96
96
|
from .server import status
|
|
97
|
+
from .update import check
|
|
97
98
|
try:
|
|
98
99
|
s = status()
|
|
99
100
|
print(json.dumps(s, indent=2))
|
|
101
|
+
upd = check("confluence-knowledge")
|
|
102
|
+
if upd["installed"]:
|
|
103
|
+
line = f"version: {upd['installed']}"
|
|
104
|
+
if upd["latest"]:
|
|
105
|
+
line += f" (latest: {upd['latest']})"
|
|
106
|
+
elif upd["latest"] is None:
|
|
107
|
+
line += " (latest: unchecked — offline or internal mirror)"
|
|
108
|
+
print(line)
|
|
109
|
+
if upd["update_available"]:
|
|
110
|
+
print("update available: run `confluence-knowledge update` "
|
|
111
|
+
"(or pip install -U confluence-knowledge[models])")
|
|
100
112
|
if s.get("configured"):
|
|
101
113
|
from .server import _client_for # internal but fine in CLI
|
|
102
114
|
profile = SiteProfile.load(default_home())
|
|
@@ -122,6 +134,7 @@ def main() -> None:
|
|
|
122
134
|
sub.add_parser("setup", help="guided credential + config setup")
|
|
123
135
|
sub.add_parser("doctor", help="verify config, credentials, models")
|
|
124
136
|
sub.add_parser("prepare-models", help="download the pinned local models")
|
|
137
|
+
sub.add_parser("update", help="upgrade this package via pip -U")
|
|
125
138
|
reg = sub.add_parser(
|
|
126
139
|
"register",
|
|
127
140
|
help="write this server into the IDE's MCP config (no manual paste)")
|
|
@@ -145,6 +158,22 @@ def main() -> None:
|
|
|
145
158
|
for line in prepare_models(default_home()):
|
|
146
159
|
print(line)
|
|
147
160
|
return
|
|
161
|
+
if args.cmd == "update":
|
|
162
|
+
import subprocess
|
|
163
|
+
cmd = [sys.executable, "-m", "pip", "install", "-U",
|
|
164
|
+
"confluence-knowledge[models]"]
|
|
165
|
+
if os.name == "nt":
|
|
166
|
+
# this exe is the running process on Windows — pip can't replace
|
|
167
|
+
# a file that's in use; hand the user the equivalent python -m
|
|
168
|
+
# pip command instead (same mechanism `pip install -U pip` uses)
|
|
169
|
+
print("on Windows, upgrade via the venv python directly:\n "
|
|
170
|
+
+ " ".join(f'"{c}"' if " " in c else c for c in cmd))
|
|
171
|
+
return
|
|
172
|
+
r = subprocess.run(cmd, check=False)
|
|
173
|
+
if r.returncode == 0:
|
|
174
|
+
print("\nupdated — models are pinned and unchanged; "
|
|
175
|
+
"run `confluence-knowledge doctor` to confirm")
|
|
176
|
+
sys.exit(r.returncode)
|
|
148
177
|
if args.cmd == "register":
|
|
149
178
|
from .registration import register
|
|
150
179
|
try:
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Self-update check — installed vs latest published version.
|
|
2
|
+
|
|
3
|
+
One GET to the package index (PyPI or an internal mirror set via
|
|
4
|
+
KNOWLEDGE_UPDATE_INDEX) — fails silent to ``latest: None`` when offline or
|
|
5
|
+
proxied, and never blocks doctor.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
import urllib.request
|
|
13
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
14
|
+
|
|
15
|
+
INDEX = "https://pypi.org/pypi/{dist}/json"
|
|
16
|
+
ENV_INDEX = "KNOWLEDGE_UPDATE_INDEX"
|
|
17
|
+
TIMEOUT = 5
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def installed_version(dist: str) -> str | None:
|
|
21
|
+
try:
|
|
22
|
+
return version(dist)
|
|
23
|
+
except PackageNotFoundError:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def latest_version(dist: str, timeout: float = TIMEOUT) -> str | None:
|
|
28
|
+
"""Latest version on the index — None when it can't be checked (offline,
|
|
29
|
+
internal mirror without the package, network policy). Never raises."""
|
|
30
|
+
url = os.environ.get(ENV_INDEX, INDEX).format(dist=dist)
|
|
31
|
+
try:
|
|
32
|
+
with urllib.request.urlopen(url, timeout=timeout) as r:
|
|
33
|
+
return json.loads(r.read())["info"]["version"]
|
|
34
|
+
except Exception: # noqa: BLE001 — every failure mode means "couldn't check"
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def check(dist: str) -> dict:
|
|
39
|
+
"""{installed, latest, update_available} — the dict doctor reports."""
|
|
40
|
+
inst = installed_version(dist)
|
|
41
|
+
latest = latest_version(dist)
|
|
42
|
+
return {
|
|
43
|
+
"installed": inst,
|
|
44
|
+
"latest": latest,
|
|
45
|
+
"update_available": bool(
|
|
46
|
+
inst and latest and _version_tuple(latest) > _version_tuple(inst)),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _version_tuple(v: str) -> tuple:
|
|
51
|
+
out = []
|
|
52
|
+
for part in v.split("."):
|
|
53
|
+
num = "".join(c for c in part if c.isdigit())
|
|
54
|
+
out.append(int(num) if num else 0)
|
|
55
|
+
return tuple(out)
|
|
@@ -13,6 +13,7 @@ src/confluence_knowledge/registration.py
|
|
|
13
13
|
src/confluence_knowledge/retrieval.py
|
|
14
14
|
src/confluence_knowledge/server.py
|
|
15
15
|
src/confluence_knowledge/settings.py
|
|
16
|
+
src/confluence_knowledge/update.py
|
|
16
17
|
src/confluence_knowledge.egg-info/PKG-INFO
|
|
17
18
|
src/confluence_knowledge.egg-info/SOURCES.txt
|
|
18
19
|
src/confluence_knowledge.egg-info/dependency_links.txt
|
|
@@ -28,4 +29,5 @@ tests/test_prepare_models.py
|
|
|
28
29
|
tests/test_registration.py
|
|
29
30
|
tests/test_retrieval.py
|
|
30
31
|
tests/test_secrets.py
|
|
31
|
-
tests/test_server_flow.py
|
|
32
|
+
tests/test_server_flow.py
|
|
33
|
+
tests/test_update.py
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Self-update check — mocked index, offline path, version compare."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
from confluence_knowledge import update
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_installed_version():
|
|
8
|
+
v = update.installed_version("confluence-knowledge")
|
|
9
|
+
assert v and v[0].isdigit()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_latest_offline_returns_none(monkeypatch):
|
|
13
|
+
monkeypatch.setattr(update, "INDEX", "https://invalid.invalid/{dist}")
|
|
14
|
+
monkeypatch.delenv("KNOWLEDGE_UPDATE_INDEX", raising=False)
|
|
15
|
+
# urllib will fail to resolve — must return None, not raise
|
|
16
|
+
assert update.latest_version("confluence-knowledge", timeout=1) is None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_check_update_available(monkeypatch):
|
|
20
|
+
monkeypatch.setattr(update, "latest_version", lambda d, **k: "99.0.0")
|
|
21
|
+
r = update.check("confluence-knowledge")
|
|
22
|
+
assert r["update_available"] is True and r["latest"] == "99.0.0"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_check_up_to_date(monkeypatch):
|
|
26
|
+
inst = update.installed_version("confluence-knowledge")
|
|
27
|
+
monkeypatch.setattr(update, "latest_version", lambda d, **k: inst)
|
|
28
|
+
r = update.check("confluence-knowledge")
|
|
29
|
+
assert r["update_available"] is False
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_check_cannot_check(monkeypatch):
|
|
33
|
+
monkeypatch.setattr(update, "latest_version", lambda d, **k: None)
|
|
34
|
+
r = update.check("confluence-knowledge")
|
|
35
|
+
assert r["update_available"] is False and r["latest"] is None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_version_tuple():
|
|
39
|
+
assert update._version_tuple("1.2.10") > update._version_tuple("1.2.9")
|
|
40
|
+
assert update._version_tuple("0.4.1") == update._version_tuple("0.4.1")
|
|
File without changes
|
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/client.py
RENAMED
|
File without changes
|
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract.py
RENAMED
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/extract_files.py
RENAMED
|
File without changes
|
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/models.lock.json
RENAMED
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/registration.py
RENAMED
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/retrieval.py
RENAMED
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/server.py
RENAMED
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/src/confluence_knowledge/settings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{confluence_knowledge-0.4.0 → confluence_knowledge-0.4.1}/tests/test_agent_doc_consistency.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|