markback 0.1.0__py3-none-any.whl → 0.1.1__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.
- markback/linter.py +29 -1
- markback/parser.py +8 -2
- markback/types.py +3 -0
- markback/writer.py +9 -2
- {markback-0.1.0.dist-info → markback-0.1.1.dist-info}/METADATA +11 -1
- markback-0.1.1.dist-info/RECORD +14 -0
- markback-0.1.0.dist-info/RECORD +0 -14
- {markback-0.1.0.dist-info → markback-0.1.1.dist-info}/WHEEL +0 -0
- {markback-0.1.0.dist-info → markback-0.1.1.dist-info}/entry_points.txt +0 -0
- {markback-0.1.0.dist-info → markback-0.1.1.dist-info}/licenses/LICENSE +0 -0
markback/linter.py
CHANGED
|
@@ -110,6 +110,33 @@ def lint_source_exists(
|
|
|
110
110
|
return diagnostics
|
|
111
111
|
|
|
112
112
|
|
|
113
|
+
def lint_prior_exists(
|
|
114
|
+
record: Record,
|
|
115
|
+
base_path: Optional[Path],
|
|
116
|
+
record_idx: int,
|
|
117
|
+
) -> list[Diagnostic]:
|
|
118
|
+
"""Check if @prior file exists."""
|
|
119
|
+
diagnostics: list[Diagnostic] = []
|
|
120
|
+
|
|
121
|
+
if record.prior and not record.prior.is_uri:
|
|
122
|
+
try:
|
|
123
|
+
resolved = record.prior.resolve(base_path)
|
|
124
|
+
if not resolved.exists():
|
|
125
|
+
diagnostics.append(Diagnostic(
|
|
126
|
+
file=record._source_file,
|
|
127
|
+
line=record._start_line,
|
|
128
|
+
column=None,
|
|
129
|
+
severity=Severity.WARNING,
|
|
130
|
+
code=WarningCode.W009,
|
|
131
|
+
message=f"@prior file not found: {record.prior}",
|
|
132
|
+
record_index=record_idx,
|
|
133
|
+
))
|
|
134
|
+
except ValueError:
|
|
135
|
+
pass # URI that can't be resolved to path
|
|
136
|
+
|
|
137
|
+
return diagnostics
|
|
138
|
+
|
|
139
|
+
|
|
113
140
|
def lint_canonical_format(
|
|
114
141
|
records: list[Record],
|
|
115
142
|
original_text: str,
|
|
@@ -173,10 +200,11 @@ def lint_string(
|
|
|
173
200
|
idx,
|
|
174
201
|
))
|
|
175
202
|
|
|
176
|
-
# Check source file existence
|
|
203
|
+
# Check source and prior file existence
|
|
177
204
|
if check_sources:
|
|
178
205
|
base_path = source_file.parent if source_file else None
|
|
179
206
|
result.diagnostics.extend(lint_source_exists(record, base_path, idx))
|
|
207
|
+
result.diagnostics.extend(lint_prior_exists(record, base_path, idx))
|
|
180
208
|
|
|
181
209
|
# Check canonical format
|
|
182
210
|
if check_canonical and result.records and not result.has_errors:
|
markback/parser.py
CHANGED
|
@@ -17,7 +17,7 @@ from .types import (
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
# Known header keywords
|
|
20
|
-
KNOWN_HEADERS = {"uri", "source"}
|
|
20
|
+
KNOWN_HEADERS = {"uri", "source", "prior"}
|
|
21
21
|
|
|
22
22
|
# Patterns
|
|
23
23
|
HEADER_PATTERN = re.compile(r"^@([a-z]+)\s+(.+)$")
|
|
@@ -147,6 +147,8 @@ def parse_string(
|
|
|
147
147
|
uri = current_headers.get("uri") or pending_uri
|
|
148
148
|
source_str = current_headers.get("source")
|
|
149
149
|
source = SourceRef(source_str) if source_str else None
|
|
150
|
+
prior_str = current_headers.get("prior")
|
|
151
|
+
prior = SourceRef(prior_str) if prior_str else None
|
|
150
152
|
|
|
151
153
|
content = None
|
|
152
154
|
if current_content_lines:
|
|
@@ -163,6 +165,7 @@ def parse_string(
|
|
|
163
165
|
feedback=feedback,
|
|
164
166
|
uri=uri,
|
|
165
167
|
source=source,
|
|
168
|
+
prior=prior,
|
|
166
169
|
content=content,
|
|
167
170
|
_source_file=source_file,
|
|
168
171
|
_start_line=current_start_line,
|
|
@@ -239,13 +242,16 @@ def parse_string(
|
|
|
239
242
|
line_num,
|
|
240
243
|
)
|
|
241
244
|
|
|
242
|
-
# Use any pending @uri from previous line
|
|
245
|
+
# Use any pending @uri from previous line and @prior if present
|
|
243
246
|
uri = pending_uri or current_headers.get("uri")
|
|
247
|
+
prior_str = current_headers.get("prior")
|
|
248
|
+
prior = SourceRef(prior_str) if prior_str else None
|
|
244
249
|
|
|
245
250
|
record = Record(
|
|
246
251
|
feedback=feedback or "",
|
|
247
252
|
uri=uri,
|
|
248
253
|
source=source,
|
|
254
|
+
prior=prior,
|
|
249
255
|
content=None,
|
|
250
256
|
_source_file=source_file,
|
|
251
257
|
_start_line=current_start_line,
|
markback/types.py
CHANGED
|
@@ -37,6 +37,7 @@ class WarningCode(Enum):
|
|
|
37
37
|
W006 = "W006" # Missing @uri (record has no identifier)
|
|
38
38
|
W007 = "W007" # Paired feedback file not found
|
|
39
39
|
W008 = "W008" # Non-canonical formatting detected
|
|
40
|
+
W009 = "W009" # @prior file not found
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
@dataclass
|
|
@@ -122,6 +123,7 @@ class Record:
|
|
|
122
123
|
feedback: str
|
|
123
124
|
uri: Optional[str] = None
|
|
124
125
|
source: Optional[SourceRef] = None
|
|
126
|
+
prior: Optional[SourceRef] = None
|
|
125
127
|
content: Optional[str] = None
|
|
126
128
|
metadata: dict = field(default_factory=dict)
|
|
127
129
|
|
|
@@ -154,6 +156,7 @@ class Record:
|
|
|
154
156
|
return {
|
|
155
157
|
"uri": self.uri,
|
|
156
158
|
"source": str(self.source) if self.source else None,
|
|
159
|
+
"prior": str(self.prior) if self.prior else None,
|
|
157
160
|
"content": self.content,
|
|
158
161
|
"feedback": self.feedback,
|
|
159
162
|
"metadata": self.metadata,
|
markback/writer.py
CHANGED
|
@@ -38,15 +38,19 @@ def write_record_canonical(
|
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
if use_compact:
|
|
41
|
-
# Compact format: @uri on its own line (if present), then @source ... <<<
|
|
41
|
+
# Compact format: @uri on its own line (if present), then @prior, then @source ... <<<
|
|
42
42
|
if record.uri:
|
|
43
43
|
lines.append(f"@uri {record.uri}")
|
|
44
|
+
if record.prior:
|
|
45
|
+
lines.append(f"@prior {record.prior}")
|
|
44
46
|
lines.append(f"@source {record.source} <<< {record.feedback}")
|
|
45
47
|
else:
|
|
46
48
|
# Full format
|
|
47
|
-
# Headers: @uri first, then @source
|
|
49
|
+
# Headers: @uri first, then @prior, then @source
|
|
48
50
|
if record.uri:
|
|
49
51
|
lines.append(f"@uri {record.uri}")
|
|
52
|
+
if record.prior:
|
|
53
|
+
lines.append(f"@prior {record.prior}")
|
|
50
54
|
if record.source:
|
|
51
55
|
lines.append(f"@source {record.source}")
|
|
52
56
|
|
|
@@ -147,6 +151,9 @@ def write_label_file(record: Record) -> str:
|
|
|
147
151
|
|
|
148
152
|
if record.uri:
|
|
149
153
|
lines.append(f"@uri {record.uri}")
|
|
154
|
+
|
|
155
|
+
if record.prior:
|
|
156
|
+
lines.append(f"@prior {record.prior}")
|
|
150
157
|
|
|
151
158
|
lines.append(f"<<< {record.feedback}")
|
|
152
159
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markback
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: A compact, human-writable format for storing content paired with feedback/labels
|
|
5
5
|
Project-URL: Homepage, https://github.com/dandriscoll/markback
|
|
6
6
|
Project-URL: Repository, https://github.com/dandriscoll/markback
|
|
@@ -196,6 +196,16 @@ Second content.
|
|
|
196
196
|
@source ./images/003.jpg <<< approved; scene=mountain
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
+
### With Prior Reference
|
|
200
|
+
|
|
201
|
+
Use `@prior` to reference an item that precedes the source (e.g., a prompt that generated an image):
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
@uri local:generated-001
|
|
205
|
+
@prior ./prompts/sunset-prompt.txt
|
|
206
|
+
@source ./images/generated-sunset.jpg <<< accurate; matches prompt well
|
|
207
|
+
```
|
|
208
|
+
|
|
199
209
|
### Paired Files
|
|
200
210
|
|
|
201
211
|
**content.txt:**
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
markback/__init__.py,sha256=B0-2dpUu5nkbnUI0hPz-x7PHiOl7M-tiRi6s3UCYJFk,1540
|
|
2
|
+
markback/cli.py,sha256=5wMk1OUG7W_voS9DxeFxRJrBTMabEdOK_s_o3Irxuu0,13639
|
|
3
|
+
markback/config.py,sha256=eTVhb7UwDER9FRYo8QUAvneLHSqXD2ZtLUgtBtnljUs,5455
|
|
4
|
+
markback/linter.py,sha256=JfhQV9R6K6Rm1I0Tu9ugU5d19MegQ9eZHlI_wyjk55k,9653
|
|
5
|
+
markback/llm.py,sha256=ON5_2C6v4KIk7_aIceulfWjEEI6hmallaPlLv-1-s_o,4692
|
|
6
|
+
markback/parser.py,sha256=P7GRjlwhy8j6Tnub7XAqILtZ4pFdkfdHhB-aIjLVRYU,18881
|
|
7
|
+
markback/types.py,sha256=6-aO1tkn9JZ1B47IFi7N9lf5_V8Y0LFrNQMoPgkp8Kc,8707
|
|
8
|
+
markback/workflow.py,sha256=zC1RUm1i1wgiciFDqUilJKJ0-bgInvctxhQ0h5WSdoQ,10485
|
|
9
|
+
markback/writer.py,sha256=3-LeupyuruGv4WZH9pV65hU4YDKuC5HgIIZ8YZ2SZnM,7896
|
|
10
|
+
markback-0.1.1.dist-info/METADATA,sha256=KsRmvJPyZLbvHGcNIeMiemLDTH2z2znLrs9U1SPCUVE,5133
|
|
11
|
+
markback-0.1.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
markback-0.1.1.dist-info/entry_points.txt,sha256=Bc9aXvtlPxVPuOJ9BWGngAVrkx5dMvRgujjVzXC-V5U,46
|
|
13
|
+
markback-0.1.1.dist-info/licenses/LICENSE,sha256=lLK1n13C_CXb0M10O-6itEIDY6dsXKutZYQH-09n6s0,1068
|
|
14
|
+
markback-0.1.1.dist-info/RECORD,,
|
markback-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
markback/__init__.py,sha256=B0-2dpUu5nkbnUI0hPz-x7PHiOl7M-tiRi6s3UCYJFk,1540
|
|
2
|
-
markback/cli.py,sha256=5wMk1OUG7W_voS9DxeFxRJrBTMabEdOK_s_o3Irxuu0,13639
|
|
3
|
-
markback/config.py,sha256=eTVhb7UwDER9FRYo8QUAvneLHSqXD2ZtLUgtBtnljUs,5455
|
|
4
|
-
markback/linter.py,sha256=6jrfngF4PiYFQlDddm09OEmVSSGwacE5YFxMub5mqlA,8707
|
|
5
|
-
markback/llm.py,sha256=ON5_2C6v4KIk7_aIceulfWjEEI6hmallaPlLv-1-s_o,4692
|
|
6
|
-
markback/parser.py,sha256=5CrLeOWGuiE0_BOK9dJUnLLrJ72KTmucyOQEzR1nDh4,18570
|
|
7
|
-
markback/types.py,sha256=rRy41h1ZYYP9lo_FhvP5X5-OlwEM7vzHCw--Sq5L2LA,8564
|
|
8
|
-
markback/workflow.py,sha256=zC1RUm1i1wgiciFDqUilJKJ0-bgInvctxhQ0h5WSdoQ,10485
|
|
9
|
-
markback/writer.py,sha256=v5KT2o2Ma2I9I4U-r06PgzKyqwQFSsx49Ri5qIsovhY,7645
|
|
10
|
-
markback-0.1.0.dist-info/METADATA,sha256=aqRMZiWqsEExkqi_dwSyWtcFb3uhOx2Ol6HbNBU7Ggw,4864
|
|
11
|
-
markback-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
-
markback-0.1.0.dist-info/entry_points.txt,sha256=Bc9aXvtlPxVPuOJ9BWGngAVrkx5dMvRgujjVzXC-V5U,46
|
|
13
|
-
markback-0.1.0.dist-info/licenses/LICENSE,sha256=lLK1n13C_CXb0M10O-6itEIDY6dsXKutZYQH-09n6s0,1068
|
|
14
|
-
markback-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|