sciwrite-lint 0.2.0__py3-none-any.whl
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.
- sciwrite_lint/__init__.py +3 -0
- sciwrite_lint/__main__.py +527 -0
- sciwrite_lint/_network.py +195 -0
- sciwrite_lint/api.py +1484 -0
- sciwrite_lint/checks/__init__.py +1 -0
- sciwrite_lint/checks/_section_utils.py +111 -0
- sciwrite_lint/checks/cite_purpose.py +122 -0
- sciwrite_lint/checks/claim_support.py +96 -0
- sciwrite_lint/checks/cross_section_consistency.py +185 -0
- sciwrite_lint/checks/dangling_cite.py +93 -0
- sciwrite_lint/checks/dangling_ref.py +116 -0
- sciwrite_lint/checks/full_paper_consistency.py +604 -0
- sciwrite_lint/checks/ref_internal_checks.py +919 -0
- sciwrite_lint/checks/reference_accuracy.py +277 -0
- sciwrite_lint/checks/reference_exists.py +119 -0
- sciwrite_lint/checks/reference_unreliable.py +244 -0
- sciwrite_lint/checks/registry.py +136 -0
- sciwrite_lint/checks/retracted_cite.py +96 -0
- sciwrite_lint/checks/structure_promises.py +115 -0
- sciwrite_lint/checks/unreferenced_figure.py +70 -0
- sciwrite_lint/claims.py +330 -0
- sciwrite_lint/claude_backend.py +94 -0
- sciwrite_lint/claude_cli.py +405 -0
- sciwrite_lint/cli/__init__.py +1 -0
- sciwrite_lint/cli/check.py +480 -0
- sciwrite_lint/cli/config.py +229 -0
- sciwrite_lint/cli/fetch.py +250 -0
- sciwrite_lint/cli/misc.py +1202 -0
- sciwrite_lint/cli/rank.py +470 -0
- sciwrite_lint/cli/verify.py +437 -0
- sciwrite_lint/config.py +646 -0
- sciwrite_lint/cross_paper.py +174 -0
- sciwrite_lint/eval_claims.py +1196 -0
- sciwrite_lint/fulltext.py +851 -0
- sciwrite_lint/llm_utils.py +386 -0
- sciwrite_lint/local_pdfs.py +122 -0
- sciwrite_lint/manuscript_store.py +674 -0
- sciwrite_lint/models.py +139 -0
- sciwrite_lint/pdf/__init__.py +1 -0
- sciwrite_lint/pdf/grobid.py +785 -0
- sciwrite_lint/pdf/pdf_download.py +258 -0
- sciwrite_lint/pipeline.py +2694 -0
- sciwrite_lint/prompt_safety.py +30 -0
- sciwrite_lint/rate_limiter.py +227 -0
- sciwrite_lint/references/__init__.py +1 -0
- sciwrite_lint/references/citations.py +715 -0
- sciwrite_lint/references/crossref.py +282 -0
- sciwrite_lint/references/embedding_store.py +380 -0
- sciwrite_lint/references/matching.py +273 -0
- sciwrite_lint/references/metadata.py +273 -0
- sciwrite_lint/references/reference_store.py +823 -0
- sciwrite_lint/references/retraction_watch.py +178 -0
- sciwrite_lint/references/workspace_db.py +1390 -0
- sciwrite_lint/report.py +163 -0
- sciwrite_lint/schemas.py +260 -0
- sciwrite_lint/scoring/__init__.py +1 -0
- sciwrite_lint/scoring/chain.py +716 -0
- sciwrite_lint/scoring/contribution.py +322 -0
- sciwrite_lint/scoring/scilint_score.py +611 -0
- sciwrite_lint/tex_parser.py +248 -0
- sciwrite_lint/usage.py +594 -0
- sciwrite_lint/vision/__init__.py +1 -0
- sciwrite_lint/vision/cache.py +140 -0
- sciwrite_lint/vision/describe.py +311 -0
- sciwrite_lint/vision/image_extraction.py +491 -0
- sciwrite_lint/vision/pipeline.py +207 -0
- sciwrite_lint/vllm/__init__.py +1 -0
- sciwrite_lint/vllm/metrics.py +157 -0
- sciwrite_lint/vllm/vllm_server.py +445 -0
- sciwrite_lint/web.py +369 -0
- sciwrite_lint-0.2.0.dist-info/METADATA +268 -0
- sciwrite_lint-0.2.0.dist-info/RECORD +76 -0
- sciwrite_lint-0.2.0.dist-info/WHEEL +5 -0
- sciwrite_lint-0.2.0.dist-info/entry_points.txt +2 -0
- sciwrite_lint-0.2.0.dist-info/licenses/LICENSE +21 -0
- sciwrite_lint-0.2.0.dist-info/top_level.txt +1 -0
sciwrite_lint/models.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Data models for sciwrite-lint."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Finding(BaseModel):
|
|
11
|
+
"""A single issue found by a check."""
|
|
12
|
+
|
|
13
|
+
level: Literal["error", "warning", "info"]
|
|
14
|
+
rule_id: str # check ID, e.g., "dangling-cite", "reference-exists"
|
|
15
|
+
message: str
|
|
16
|
+
file: str = ""
|
|
17
|
+
line: int | None = None
|
|
18
|
+
context: str = ""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CheckMeta(BaseModel):
|
|
22
|
+
"""Metadata for a registered check."""
|
|
23
|
+
|
|
24
|
+
id: str # "dangling-cite", "cross-section-consistency", etc.
|
|
25
|
+
severity: Literal["error", "warning", "info"]
|
|
26
|
+
category: Literal["manuscript", "reference-db", "local-llm"]
|
|
27
|
+
description: str
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Legacy alias for backwards compatibility
|
|
31
|
+
RuleMeta = CheckMeta
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CheckResult(BaseModel):
|
|
35
|
+
"""Result from running checks on a paper."""
|
|
36
|
+
|
|
37
|
+
checker: str # e.g., "check", "verify"
|
|
38
|
+
paper: str # e.g., "my_paper" or filename
|
|
39
|
+
findings: list[Finding] = Field(default_factory=list)
|
|
40
|
+
|
|
41
|
+
@property
|
|
42
|
+
def errors(self) -> list[Finding]:
|
|
43
|
+
return [f for f in self.findings if f.level == "error"]
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def warnings(self) -> list[Finding]:
|
|
47
|
+
return [f for f in self.findings if f.level == "warning"]
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def ok(self) -> bool:
|
|
51
|
+
return not self.errors
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Citation(BaseModel):
|
|
55
|
+
"""A citation extracted from a .tex file."""
|
|
56
|
+
|
|
57
|
+
key: str
|
|
58
|
+
raw_text: str
|
|
59
|
+
authors: list[str] = Field(default_factory=list)
|
|
60
|
+
title: str = ""
|
|
61
|
+
year: str = ""
|
|
62
|
+
venue: str = ""
|
|
63
|
+
doi: str = ""
|
|
64
|
+
url: str = ""
|
|
65
|
+
arxiv_id: str = "" # e.g. "2310.01798"
|
|
66
|
+
pmid: str = "" # e.g. "12345678"
|
|
67
|
+
pmc_id: str = "" # e.g. "PMC1234567"
|
|
68
|
+
isbn: str = "" # e.g. "9780226458113"
|
|
69
|
+
lccn: str = "" # e.g. "2019012345"
|
|
70
|
+
source_paper: str = ""
|
|
71
|
+
bib_format: str = "" # "simple", "natbib", or "bib"
|
|
72
|
+
entry_type: str = "" # BibTeX entry type: "article", "misc", etc.
|
|
73
|
+
|
|
74
|
+
# Local source
|
|
75
|
+
local_status: Literal["pdf", "md", "none"] = "none"
|
|
76
|
+
local_path: str = ""
|
|
77
|
+
|
|
78
|
+
# API verification
|
|
79
|
+
api_match: Literal[
|
|
80
|
+
"",
|
|
81
|
+
"verified",
|
|
82
|
+
"mismatch",
|
|
83
|
+
"not_found",
|
|
84
|
+
"skipped",
|
|
85
|
+
"web_verified",
|
|
86
|
+
"web_dead",
|
|
87
|
+
"manual",
|
|
88
|
+
] = ""
|
|
89
|
+
api_source: str = ""
|
|
90
|
+
api_data: dict = Field(default_factory=dict)
|
|
91
|
+
issues: list[str] = Field(default_factory=list)
|
|
92
|
+
|
|
93
|
+
# Tier (computed from metadata)
|
|
94
|
+
tier: Literal["T1", "T2", "T3", ""] = ""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class CitationMetadata(BaseModel):
|
|
98
|
+
"""Persistent per-citation verification record stored as JSON."""
|
|
99
|
+
|
|
100
|
+
key: str
|
|
101
|
+
verified_date: str = ""
|
|
102
|
+
api_source: str = "" # "crossref", "openalex", "semantic_scholar"
|
|
103
|
+
api_match: Literal[
|
|
104
|
+
"",
|
|
105
|
+
"verified",
|
|
106
|
+
"mismatch",
|
|
107
|
+
"not_found",
|
|
108
|
+
"skipped",
|
|
109
|
+
"web_verified",
|
|
110
|
+
"web_dead",
|
|
111
|
+
"manual",
|
|
112
|
+
] = ""
|
|
113
|
+
|
|
114
|
+
# Canonical data from API (what the world says)
|
|
115
|
+
canonical: dict[str, Any] = Field(default_factory=dict)
|
|
116
|
+
|
|
117
|
+
# What our .tex bibitem says
|
|
118
|
+
bibitem: dict[str, Any] = Field(default_factory=dict)
|
|
119
|
+
|
|
120
|
+
# Access status
|
|
121
|
+
access: dict[str, Any] = Field(default_factory=dict)
|
|
122
|
+
|
|
123
|
+
mismatches: list[str] = Field(default_factory=list)
|
|
124
|
+
issues: list[str] = Field(default_factory=list)
|
|
125
|
+
|
|
126
|
+
# Manual override
|
|
127
|
+
manual_override: dict[str, Any] = Field(default_factory=dict)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class SectionInfo(BaseModel):
|
|
131
|
+
"""A section in a LaTeX document."""
|
|
132
|
+
|
|
133
|
+
label: str # e.g., "sec:intro" (empty if no label)
|
|
134
|
+
title: str
|
|
135
|
+
depth: int # 0=section, 1=subsection, 2=subsubsection
|
|
136
|
+
start_line: int
|
|
137
|
+
end_line: int
|
|
138
|
+
word_count: int
|
|
139
|
+
cite_count: int = 0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""PDF acquisition and parsing: GROBID and download utilities."""
|