Skip to content

Commit f40c977

Browse files
committed
v2.0.1 - first-run sample project, Windows PATH hint, English CLI output
- Bundle a real WoS + Scopus sample dataset; first launch seeds a ready "Simple Project" (one-time, marker-guarded - not recreated if deleted) - Windows: when "bibexpy" is not on PATH (Store Python / --user installs), startup prints the exact Scripts folder + a copy-paste PowerShell fix; python -m bibexpy documented as universal fallback - CLI banner and error messages switched to English - READMEs: troubleshooting note + sample-project highlight
1 parent b66f16a commit f40c977

8 files changed

Lines changed: 59952 additions & 16 deletions

File tree

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,23 @@ inside the wheel). Works on Windows, macOS and Linux.
4747
bibexpy --port 8080 # custom port
4848
bibexpy --no-browser # server only
4949
bibexpy --storage ./data # custom storage folder
50-
bibexpy --version # → BibexPy 2.0.0 (Helium)
50+
bibexpy --version # → BibexPy 2.0.1 (Helium)
5151
```
5252

53+
> **Windows — `bibexpy` is not recognized?** Your Python `Scripts` folder isn't on PATH
54+
> (common with Microsoft Store Python and `pip install --user`). Just run it as
55+
> **`python -m bibexpy`** — on startup it prints your exact `Scripts` path together with a
56+
> copy-paste PowerShell command that fixes PATH permanently. Alternatively install via
57+
> [pipx](https://pipx.pypa.io) (`pipx install bibexpy`), which manages PATH for you.
58+
5359
Projects/data live under `~/.bibexpy/storage`; settings and API keys under `~/.bibexpy/.env`
5460
(managed from the in-app Settings page).
5561

5662
## What's new in v2
5763

64+
- **Built-in sample dataset** — the first launch creates a ready-to-explore **Simple
65+
Project** (real Web of Science + Scopus exports), so you can try the whole pipeline
66+
before uploading your own data.
5867
- **One-click Smart Merge** — multi-stage probabilistic record linkage: exact DOI/identifier
5968
matching + Jaro–Winkler title similarity, confidence scoring, and an optional
6069
borderline-review queue. The result includes a copy-ready methodology paragraph.
@@ -125,7 +134,7 @@ bash scripts/build_wheel.sh # macOS / Linux
125134
pwsh scripts/build_wheel.ps1 # Windows
126135
```
127136

128-
`python_pkg/dist/bibexpy-2.0.0-py3-none-any.whl` — a pure-python `py3-none-any` wheel that
137+
`python_pkg/dist/bibexpy-2.0.1-py3-none-any.whl` — a pure-python `py3-none-any` wheel that
129138
installs on Windows / macOS / Linux with no compiler.
130139

131140
## Release

apps/api/main.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,49 @@ def create_app() -> FastAPI:
121121
system_router, tools_router, report_router):
122122
app.include_router(r.router, prefix="/api")
123123

124+
# Startup: ilk kurulumda paketle gelen örnek veriden "Simple Project" oluştur.
125+
# Yalnız packaged çalıştırmada (cli.py BIBEXPY_SAMPLES_DIR'i set eder) ve
126+
# depo TAMAMEN boşken bir kez çalışır; `.sample_seeded` işaret dosyası
127+
# sayesinde kullanıcı projeyi silerse yeniden OLUŞTURULMAZ.
128+
@app.on_event("startup")
129+
def _seed_sample_project_on_startup() -> None:
130+
try:
131+
import os
132+
import shutil
133+
134+
samples_dir = os.environ.get("BIBEXPY_SAMPLES_DIR", "").strip()
135+
if not samples_dir:
136+
return
137+
src = Path(samples_dir)
138+
if not src.is_dir():
139+
return
140+
marker = settings.storage_path / ".sample_seeded"
141+
if marker.exists():
142+
return
143+
from services import storage as _storage
144+
145+
if _storage.list_projects():
146+
# Mevcut kullanıcı deposu — örnek ekleme, ama bir daha da deneme.
147+
marker.touch()
148+
return
149+
meta = _storage.create_project(
150+
"Simple Project",
151+
"Built-in sample dataset (Web of Science + Scopus) — try the pipeline end-to-end.",
152+
)
153+
raw = _storage.project_dir(meta.id) / "raw"
154+
copied = 0
155+
for f in sorted(src.iterdir()):
156+
if f.is_file() and _storage.detect_file_kind(f.name) != "unknown":
157+
shutil.copy2(f, raw / f.name)
158+
copied += 1
159+
marker.touch()
160+
import logging
161+
logging.getLogger("uvicorn").info(
162+
f"Seeded sample project 'Simple Project' ({copied} file(s))"
163+
)
164+
except Exception:
165+
pass
166+
124167
# Startup: soft-deleted analiz klasörlerini fiziksel temizle.
125168
@app.on_event("startup")
126169
def _purge_soft_deleted_on_startup() -> None:

apps/api/tests/test_sample_seed.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""Paketle gelen örnek verinin ilk açılışta "Simple Project" olarak yüklenmesi.
2+
3+
cli.py packaged çalıştırmada BIBEXPY_SAMPLES_DIR'i set eder; main.py startup'ı
4+
depo TAMAMEN boşken örnek projeyi BİR KEZ oluşturur (.sample_seeded işareti).
5+
Kullanıcı projeyi silerse yeniden oluşturulmaz; env yoksa hiç çalışmaz.
6+
"""
7+
8+
import sys
9+
from pathlib import Path
10+
11+
from fastapi.testclient import TestClient
12+
13+
14+
def _fresh_app(monkeypatch, storage: Path, samples: Path | None):
15+
monkeypatch.setenv("STORAGE_DIR", str(storage))
16+
storage.mkdir(parents=True, exist_ok=True)
17+
if samples is None:
18+
monkeypatch.delenv("BIBEXPY_SAMPLES_DIR", raising=False)
19+
else:
20+
monkeypatch.setenv("BIBEXPY_SAMPLES_DIR", str(samples))
21+
api_root = Path(__file__).resolve().parents[1]
22+
sys.path.insert(0, str(api_root))
23+
# config/main'i temiz import et (env'i her testte yeniden okumak için)
24+
for mod in list(sys.modules):
25+
if mod.startswith(("main", "config", "routers", "services", "models")):
26+
sys.modules.pop(mod, None)
27+
from main import app # noqa: E402
28+
29+
return app
30+
31+
32+
def test_seed_creates_simple_project_once(monkeypatch, tmp_path):
33+
samples = tmp_path / "samples"
34+
samples.mkdir()
35+
(samples / "scopus.csv").write_text("a,b\n1,2\n", encoding="utf-8")
36+
(samples / "savedrecs.txt").write_text("FN Clarivate\nVR 1.0\n", encoding="utf-8")
37+
(samples / "notes.md").write_text("ignored", encoding="utf-8") # unknown tür → kopyalanmaz
38+
storage = tmp_path / "storage"
39+
40+
# İlk açılış (boş depo) → Simple Project + yalnız tanınan 2 dosya
41+
app = _fresh_app(monkeypatch, storage, samples)
42+
with TestClient(app) as client: # context manager → startup event'leri çalışır
43+
projects = client.get("/api/projects").json()
44+
assert [p["name"] for p in projects] == ["Simple Project"]
45+
pid = projects[0]["id"]
46+
files = client.get(f"/api/projects/{pid}/files").json()
47+
assert {f["kind"] for f in files} == {"scopus_csv", "wos_txt"}
48+
assert len(files) == 2
49+
50+
# Kullanıcı örnek projeyi siler...
51+
app2 = _fresh_app(monkeypatch, storage, samples)
52+
with TestClient(app2) as client:
53+
pid = client.get("/api/projects").json()[0]["id"]
54+
assert client.delete(f"/api/projects/{pid}").status_code == 204
55+
56+
# ...sonraki açılışta YENİDEN OLUŞMAZ (.sample_seeded işareti)
57+
app3 = _fresh_app(monkeypatch, storage, samples)
58+
with TestClient(app3) as client:
59+
assert client.get("/api/projects").json() == []
60+
61+
62+
def test_no_seed_without_env(monkeypatch, tmp_path):
63+
app = _fresh_app(monkeypatch, tmp_path / "storage", None)
64+
with TestClient(app) as client:
65+
assert client.get("/api/projects").json() == []
66+
67+
68+
def test_no_seed_when_projects_exist(monkeypatch, tmp_path):
69+
samples = tmp_path / "samples"
70+
samples.mkdir()
71+
(samples / "scopus.csv").write_text("a,b\n1,2\n", encoding="utf-8")
72+
storage = tmp_path / "storage"
73+
74+
# Önce örneksiz bir proje oluşturulmuş depo hazırla
75+
app = _fresh_app(monkeypatch, storage, None)
76+
with TestClient(app) as client:
77+
client.post("/api/projects", json={"name": "Mine"})
78+
79+
# Env set edilse bile dolu depoya örnek EKLENMEZ
80+
app2 = _fresh_app(monkeypatch, storage, samples)
81+
with TestClient(app2) as client:
82+
names = [p["name"] for p in client.get("/api/projects").json()]
83+
assert names == ["Mine"]

python_pkg/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,16 @@ bibexpy --version
3131
Defaults: UI at `http://127.0.0.1:6060`, data under `~/.bibexpy/storage`, settings/API keys
3232
under `~/.bibexpy/.env` (managed from the in-app Settings page). Press `Ctrl+C` to stop.
3333

34+
> **Windows — `bibexpy` is not recognized?** Your Python `Scripts` folder isn't on PATH
35+
> (common with Microsoft Store Python and `pip install --user`). Just run it as
36+
> **`python -m bibexpy`** — on startup it prints your exact `Scripts` path together with a
37+
> copy-paste PowerShell command that fixes PATH permanently. Alternatively install via
38+
> [pipx](https://pipx.pypa.io) (`pipx install bibexpy`), which manages PATH for you.
39+
3440
## Highlights (v2)
3541

42+
- **Built-in sample dataset** — first launch creates a ready-to-explore *Simple Project*
43+
(real WoS + Scopus exports) so you can try the whole pipeline immediately.
3644
- One-click **Smart Merge** — probabilistic record linkage (DOI + Jaro–Winkler), confidence
3745
scoring, optional borderline review, and a copy-ready methodology paragraph.
3846
- **ORCID-first** author disambiguation + **address harmonization** (organization roll-up,

python_pkg/pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ build-backend = "setuptools.build_meta"
1616

1717
[project]
1818
name = "bibexpy"
19-
version = "2.0.0"
19+
version = "2.0.1"
2020
description = "Self-hosted bibliometric data preparation tool (Scopus + Web of Science)"
2121
readme = "README.md"
2222
requires-python = ">=3.10"
@@ -101,5 +101,6 @@ packages = [
101101
]
102102

103103
[tool.setuptools.package-data]
104-
# _web saf statik UI — recursive glob (setuptools>=62 `**` destekler).
105-
bibexpy = ["_web/**/*", "_web/**/.*"]
104+
# _web saf statik UI + _samples örnek veri seti ("Simple Project") —
105+
# recursive glob (setuptools>=62 `**` destekler).
106+
bibexpy = ["_web/**/*", "_web/**/.*", "_samples/**/*"]

0 commit comments

Comments
 (0)