calkit-python 0.41.8__py3-none-any.whl → 0.41.9__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.
- calkit/cli/new.py +33 -39
- calkit/releases.py +103 -0
- calkit/tests/cli/test_new.py +15 -0
- calkit/tests/test_releases.py +85 -0
- {calkit_python-0.41.8.dist-info → calkit_python-0.41.9.dist-info}/METADATA +1 -1
- {calkit_python-0.41.8.dist-info → calkit_python-0.41.9.dist-info}/RECORD +24 -24
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/etc/jupyter/jupyter_server_config.d/calkit.json +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/install.json +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/package.json +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/909.e3f9cc3408834a7fdcc3.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/remoteEntry.65469af996e7a96aa983.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/style.js +0 -0
- {calkit_python-0.41.8.data → calkit_python-0.41.9.data}/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json +0 -0
- {calkit_python-0.41.8.dist-info → calkit_python-0.41.9.dist-info}/WHEEL +0 -0
- {calkit_python-0.41.8.dist-info → calkit_python-0.41.9.dist-info}/entry_points.txt +0 -0
- {calkit_python-0.41.8.dist-info → calkit_python-0.41.9.dist-info}/licenses/LICENSE +0 -0
calkit/cli/new.py
CHANGED
|
@@ -3143,7 +3143,7 @@ def new_release(
|
|
|
3143
3143
|
)
|
|
3144
3144
|
with open("LICENSE", "w") as f:
|
|
3145
3145
|
f.write(license_txt)
|
|
3146
|
-
|
|
3146
|
+
repo.git.add("LICENSE")
|
|
3147
3147
|
license_ids = ["mit", "cc-by-4.0"]
|
|
3148
3148
|
else:
|
|
3149
3149
|
typer.echo(f"Detecting license(s) from {license_file}")
|
|
@@ -3394,38 +3394,23 @@ def new_release(
|
|
|
3394
3394
|
doi_base_url = calkit.releases.SERVICES[to]["url"]
|
|
3395
3395
|
doi_md = (
|
|
3396
3396
|
f"[]"
|
|
3397
|
-
f"(https://
|
|
3397
|
+
f"(https://doi.org/{doi})"
|
|
3398
3398
|
)
|
|
3399
3399
|
if os.path.isfile("README.md"):
|
|
3400
3400
|
with open("README.md") as f:
|
|
3401
3401
|
readme_txt = f.read()
|
|
3402
3402
|
else:
|
|
3403
|
-
readme_txt =
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
first_content_line_index = None
|
|
3407
|
-
for n, line in enumerate(existing_lines):
|
|
3408
|
-
if line.startswith(doi_md[:6]):
|
|
3409
|
-
pass # Skip DOI lines
|
|
3410
|
-
else:
|
|
3411
|
-
if (
|
|
3412
|
-
n != 0
|
|
3413
|
-
and line.strip()
|
|
3414
|
-
and first_content_line_index is None
|
|
3415
|
-
):
|
|
3416
|
-
first_content_line_index = len(new_lines)
|
|
3417
|
-
new_lines.append(line)
|
|
3418
|
-
# Ensure first 3 lines are title, blank, DOI lines
|
|
3419
|
-
new_lines = (
|
|
3420
|
-
[new_lines[0]]
|
|
3421
|
-
+ ["", doi_md, ""]
|
|
3422
|
-
+ new_lines[first_content_line_index:]
|
|
3403
|
+
readme_txt = ""
|
|
3404
|
+
readme_txt = calkit.releases.add_doi_badge_to_readme(
|
|
3405
|
+
readme_txt, badge=doi_md, title=title
|
|
3423
3406
|
)
|
|
3424
|
-
readme_txt = "\n".join(new_lines)
|
|
3425
3407
|
if not dry_run:
|
|
3426
3408
|
with open("README.md", "w") as f:
|
|
3427
3409
|
f.write(readme_txt)
|
|
3428
|
-
|
|
3410
|
+
# Stage only after the file is closed; otherwise the buffered
|
|
3411
|
+
# contents may not be flushed to disk yet and Git would stage an
|
|
3412
|
+
# empty file
|
|
3413
|
+
repo.git.add("README.md")
|
|
3429
3414
|
else:
|
|
3430
3415
|
typer.echo(f"Would have updated README.md to:\n{readme_txt}")
|
|
3431
3416
|
# Create Git tag
|
|
@@ -3480,11 +3465,13 @@ def new_release(
|
|
|
3480
3465
|
references = reference_collections[0]
|
|
3481
3466
|
ref_path = references.get("path", "references.bib")
|
|
3482
3467
|
try:
|
|
3468
|
+
# Read the existing references as raw text so we can append the new
|
|
3469
|
+
# entry without reformatting the user's existing entries
|
|
3483
3470
|
if os.path.isfile(ref_path):
|
|
3484
3471
|
with open(ref_path) as f:
|
|
3485
|
-
|
|
3472
|
+
existing_text = f.read()
|
|
3486
3473
|
else:
|
|
3487
|
-
|
|
3474
|
+
existing_text = ""
|
|
3488
3475
|
bibtex_doi = doi
|
|
3489
3476
|
if bibtex_doi is None and dry_run:
|
|
3490
3477
|
mock_suffix = "".join(
|
|
@@ -3504,31 +3491,38 @@ def new_release(
|
|
|
3504
3491
|
if not new_entries:
|
|
3505
3492
|
raise ValueError("Failed to parse generated BibTeX entry")
|
|
3506
3493
|
new_entry = new_entries[0]
|
|
3507
|
-
# Search through entries for
|
|
3508
|
-
# there is a match
|
|
3494
|
+
# Search through existing entries for any with the same DOI, and
|
|
3495
|
+
# replace them (by citation key) if there is a match. Tolerate parse
|
|
3496
|
+
# errors here (e.g., non-standard or temporarily-invalid BibTeX) by
|
|
3497
|
+
# skipping replacement detection and still appending the new entry.
|
|
3509
3498
|
new_doi = new_entry.get("doi")
|
|
3510
|
-
|
|
3499
|
+
replace_ids = []
|
|
3511
3500
|
if new_doi:
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3501
|
+
try:
|
|
3502
|
+
existing_entries = bibtexparser.loads(existing_text).entries
|
|
3503
|
+
except Exception as e:
|
|
3504
|
+
warn(f"Could not parse existing references to dedupe: {e}")
|
|
3505
|
+
existing_entries = []
|
|
3506
|
+
replace_ids = [
|
|
3507
|
+
entry["ID"]
|
|
3508
|
+
for entry in existing_entries
|
|
3515
3509
|
if entry.get("doi") == new_doi
|
|
3516
3510
|
]
|
|
3517
|
-
if
|
|
3511
|
+
if replace_ids:
|
|
3518
3512
|
typer.echo(
|
|
3519
3513
|
"Found matching DOI in existing references "
|
|
3520
|
-
f"({len(
|
|
3521
|
-
f"{'y' if len(
|
|
3514
|
+
f"({len(replace_ids)} entr"
|
|
3515
|
+
f"{'y' if len(replace_ids) == 1 else 'ies'}); "
|
|
3522
3516
|
"replacing"
|
|
3523
3517
|
)
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3518
|
+
new_text = calkit.releases.add_bibtex_entry(
|
|
3519
|
+
existing_text, invenio_bibtex, replace_ids=replace_ids
|
|
3520
|
+
)
|
|
3527
3521
|
if dry_run:
|
|
3528
3522
|
typer.echo(f"Would write updated references to {ref_path}")
|
|
3529
3523
|
else:
|
|
3530
3524
|
with open(ref_path, "w") as f:
|
|
3531
|
-
|
|
3525
|
+
f.write(new_text)
|
|
3532
3526
|
repo.git.add(ref_path)
|
|
3533
3527
|
except Exception as e:
|
|
3534
3528
|
warn(f"Failed to add to references: {e}")
|
calkit/releases.py
CHANGED
|
@@ -86,6 +86,109 @@ def create_bibtex(
|
|
|
86
86
|
)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
def _find_bibtex_entry_span(
|
|
90
|
+
text: str, entry_id: str
|
|
91
|
+
) -> tuple[int, int] | None:
|
|
92
|
+
"""Locate the raw character span of a BibTeX entry by its citation key.
|
|
93
|
+
|
|
94
|
+
Returns ``(start, end)`` offsets into ``text`` where ``end`` is exclusive
|
|
95
|
+
(just past the entry's closing brace), or ``None`` if no entry with that
|
|
96
|
+
key is found.
|
|
97
|
+
"""
|
|
98
|
+
# Match e.g. ``@misc{the-key,`` allowing arbitrary surrounding whitespace
|
|
99
|
+
pattern = re.compile(
|
|
100
|
+
r"@\w+\s*\{\s*" + re.escape(entry_id) + r"\s*,", re.IGNORECASE
|
|
101
|
+
)
|
|
102
|
+
match = pattern.search(text)
|
|
103
|
+
if match is None:
|
|
104
|
+
return None
|
|
105
|
+
# Walk from the entry's opening brace to its matching close, counting depth
|
|
106
|
+
depth = 0
|
|
107
|
+
i = text.index("{", match.start())
|
|
108
|
+
while i < len(text):
|
|
109
|
+
if text[i] == "{":
|
|
110
|
+
depth += 1
|
|
111
|
+
elif text[i] == "}":
|
|
112
|
+
depth -= 1
|
|
113
|
+
if depth == 0:
|
|
114
|
+
return match.start(), i + 1
|
|
115
|
+
i += 1
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def add_bibtex_entry(
|
|
120
|
+
existing_text: str, new_entry: str, replace_ids: list[str] | None = None
|
|
121
|
+
) -> str:
|
|
122
|
+
"""Append a BibTeX entry to existing references without reformatting them.
|
|
123
|
+
|
|
124
|
+
Any entries whose citation keys are in ``replace_ids`` are removed first
|
|
125
|
+
(so a re-released version replaces its prior entry); all other existing
|
|
126
|
+
content is preserved byte-for-byte. ``new_entry`` is appended at the end.
|
|
127
|
+
"""
|
|
128
|
+
text = existing_text
|
|
129
|
+
# Remove replaced entries from the raw text, last-to-first so earlier spans
|
|
130
|
+
# stay valid as we splice. De-duplicate spans in case a key matched more
|
|
131
|
+
# than once.
|
|
132
|
+
spans = set()
|
|
133
|
+
for entry_id in replace_ids or []:
|
|
134
|
+
span = _find_bibtex_entry_span(text, entry_id)
|
|
135
|
+
if span is not None:
|
|
136
|
+
spans.add(span)
|
|
137
|
+
for start, end in sorted(spans, reverse=True):
|
|
138
|
+
# Consume any trailing newlines so we don't leave a gap behind
|
|
139
|
+
while end < len(text) and text[end] in "\r\n":
|
|
140
|
+
end += 1
|
|
141
|
+
text = text[:start] + text[end:]
|
|
142
|
+
# Append the new entry, leaving the existing content untouched and adding
|
|
143
|
+
# only the separator newlines needed for exactly one blank line between the
|
|
144
|
+
# last existing entry and the new one
|
|
145
|
+
if not text.strip():
|
|
146
|
+
return new_entry.strip() + "\n"
|
|
147
|
+
if text.endswith("\n\n"):
|
|
148
|
+
separator = ""
|
|
149
|
+
elif text.endswith("\n"):
|
|
150
|
+
separator = "\n"
|
|
151
|
+
else:
|
|
152
|
+
separator = "\n\n"
|
|
153
|
+
return text + separator + new_entry.strip() + "\n"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def add_doi_badge_to_readme(
|
|
157
|
+
readme_text: str, badge: str, title: str | None
|
|
158
|
+
) -> str:
|
|
159
|
+
"""Insert (or refresh) a DOI badge near the top of a README.
|
|
160
|
+
|
|
161
|
+
The badge is placed directly beneath the title with exactly one blank line
|
|
162
|
+
on either side. Any pre-existing DOI badge line is replaced rather than
|
|
163
|
+
duplicated, the title is never duplicated, and all other existing content
|
|
164
|
+
is preserved.
|
|
165
|
+
"""
|
|
166
|
+
# Drop any existing DOI badge line(s); the current badge is re-added below
|
|
167
|
+
lines = [
|
|
168
|
+
line
|
|
169
|
+
for line in (readme_text.split("\n") if readme_text else [])
|
|
170
|
+
if not line.startswith("[![DOI")
|
|
171
|
+
]
|
|
172
|
+
# The first non-blank line is treated as the title; synthesize one from the
|
|
173
|
+
# project title if the README has no content yet
|
|
174
|
+
while lines and not lines[0].strip():
|
|
175
|
+
lines.pop(0)
|
|
176
|
+
if lines:
|
|
177
|
+
title_line = lines[0]
|
|
178
|
+
rest = lines[1:]
|
|
179
|
+
else:
|
|
180
|
+
title_line = f"# {title}"
|
|
181
|
+
rest = []
|
|
182
|
+
# Drop leading blank lines from the remaining content so the spacing around
|
|
183
|
+
# the badge is controlled entirely here
|
|
184
|
+
while rest and not rest[0].strip():
|
|
185
|
+
rest.pop(0)
|
|
186
|
+
new_lines = [title_line, "", badge]
|
|
187
|
+
if rest:
|
|
188
|
+
new_lines += [""] + rest
|
|
189
|
+
return "\n".join(new_lines)
|
|
190
|
+
|
|
191
|
+
|
|
89
192
|
CITATION_CFF_TEMPLATE = """
|
|
90
193
|
cff-version: 1.2.0
|
|
91
194
|
message: If you use this software, please cite it using these metadata.
|
calkit/tests/cli/test_new.py
CHANGED
|
@@ -810,6 +810,21 @@ def test_new_release(tmp_dir, monkeypatch, httpserver):
|
|
|
810
810
|
assert "v0.1.0" in ck_info["releases"]
|
|
811
811
|
release = ck_info["releases"]["v0.1.0"]
|
|
812
812
|
assert release["doi"] is not None
|
|
813
|
+
# Regression test for issue #931: the README must not be emptied, the
|
|
814
|
+
# committed README must match the working tree (otherwise it shows up as a
|
|
815
|
+
# spurious unstaged change), and the DOI badge must link to doi.org rather
|
|
816
|
+
# than the DataCite staging host (which 502s)
|
|
817
|
+
repo = git.Repo()
|
|
818
|
+
readme_working = (tmp_dir / "README.md").read_text()
|
|
819
|
+
assert readme_working.strip()
|
|
820
|
+
readme_committed = repo.git.show("HEAD:README.md")
|
|
821
|
+
assert readme_committed.strip() == readme_working.strip()
|
|
822
|
+
badge_link = f"](https://doi.org/{release['doi']})"
|
|
823
|
+
assert badge_link in readme_working
|
|
824
|
+
assert "datacite.org" not in readme_working
|
|
825
|
+
# The release BibTeX entry should be added to references.bib
|
|
826
|
+
references = (tmp_dir / "references.bib").read_text()
|
|
827
|
+
assert release["doi"] in references
|
|
813
828
|
# TODO: Test that the GitHub link is in the related works
|
|
814
829
|
# Test that we can update this release
|
|
815
830
|
# Side note: This is revealing some design weirdness where we're grouping
|
calkit/tests/test_releases.py
CHANGED
|
@@ -12,6 +12,8 @@ import pytest
|
|
|
12
12
|
import calkit
|
|
13
13
|
from calkit.dvc.zip import write_zip_path_map
|
|
14
14
|
from calkit.releases import (
|
|
15
|
+
add_bibtex_entry,
|
|
16
|
+
add_doi_badge_to_readme,
|
|
15
17
|
check_project_release_archive,
|
|
16
18
|
create_bibtex,
|
|
17
19
|
create_citation_cff,
|
|
@@ -163,6 +165,89 @@ def test_create_bibtex():
|
|
|
163
165
|
assert len(entries) == 1
|
|
164
166
|
|
|
165
167
|
|
|
168
|
+
def test_add_bibtex_entry():
|
|
169
|
+
new_entry = create_bibtex(
|
|
170
|
+
authors=[{"first_name": "Jane", "last_name": "Doe"}],
|
|
171
|
+
release_date="2026-06-03",
|
|
172
|
+
title="New release",
|
|
173
|
+
doi="10.5281/zenodo.999",
|
|
174
|
+
record_id="999",
|
|
175
|
+
)
|
|
176
|
+
# Appending to existing references preserves the original formatting
|
|
177
|
+
# (e.g., tab-indented fields) byte-for-byte and only adds the new entry
|
|
178
|
+
existing = (
|
|
179
|
+
"@article{smith2020,\n"
|
|
180
|
+
"\tauthor = {Smith, John},\n"
|
|
181
|
+
"\tdoi = {10.1/abc},\n"
|
|
182
|
+
"}\n"
|
|
183
|
+
)
|
|
184
|
+
appended = add_bibtex_entry(existing, new_entry, replace_ids=[])
|
|
185
|
+
# The existing content is preserved byte-for-byte at the start, with a
|
|
186
|
+
# single blank line separating it from the appended entry
|
|
187
|
+
assert appended.startswith(existing)
|
|
188
|
+
assert appended == existing + "\n" + new_entry.strip() + "\n"
|
|
189
|
+
assert appended.count("@misc{Doe2026_999,") == 1
|
|
190
|
+
assert bibtexparser.loads(appended).entries[0]["doi"] == "10.1/abc"
|
|
191
|
+
# Appending to an empty/nonexistent file yields just the new entry
|
|
192
|
+
from_empty = add_bibtex_entry("", new_entry, replace_ids=[])
|
|
193
|
+
assert from_empty.strip().startswith("@misc{Doe2026_999,")
|
|
194
|
+
# A matching entry (by citation key) is replaced, while other entries are
|
|
195
|
+
# left untouched and keep their original formatting
|
|
196
|
+
with_old = existing + (
|
|
197
|
+
"\n@misc{old2021,\n"
|
|
198
|
+
"\tauthor = {Doe, Jane},\n"
|
|
199
|
+
"\ttitle = {Old release},\n"
|
|
200
|
+
"\tdoi = {10.5281/zenodo.999},\n"
|
|
201
|
+
"}\n"
|
|
202
|
+
)
|
|
203
|
+
replaced = add_bibtex_entry(with_old, new_entry, replace_ids=["old2021"])
|
|
204
|
+
assert "Old release" not in replaced
|
|
205
|
+
assert "@article{smith2020,\n\tauthor = {Smith, John}," in replaced
|
|
206
|
+
assert replaced.count("@misc{Doe2026_999,") == 1
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def test_add_doi_badge_to_readme():
|
|
210
|
+
badge = "[](https://doi.org/10.5281/zenodo.999)" # noqa: E501
|
|
211
|
+
# A README with a title and body gets the badge inserted directly beneath
|
|
212
|
+
# the title with exactly one blank line on either side, and no content is
|
|
213
|
+
# removed or duplicated
|
|
214
|
+
readme = "# My Project\nSome description.\n\n## Section\nDetails here.\n"
|
|
215
|
+
out = add_doi_badge_to_readme(readme, badge=badge, title="My Project")
|
|
216
|
+
assert out.startswith(f"# My Project\n\n{badge}\n\nSome description.")
|
|
217
|
+
assert out.count("# My Project\n") == 1
|
|
218
|
+
assert "Some description." in out
|
|
219
|
+
assert "## Section" in out
|
|
220
|
+
assert "Details here." in out
|
|
221
|
+
# The badge has exactly one blank line above and below it
|
|
222
|
+
lines = out.split("\n")
|
|
223
|
+
idx = lines.index(badge)
|
|
224
|
+
assert lines[idx - 1] == ""
|
|
225
|
+
assert lines[idx - 2] == "# My Project"
|
|
226
|
+
assert lines[idx + 1] == ""
|
|
227
|
+
assert lines[idx + 2].strip()
|
|
228
|
+
# A title-only README does not duplicate the title
|
|
229
|
+
title_only = add_doi_badge_to_readme(
|
|
230
|
+
"# My Project\n", badge=badge, title="My Project"
|
|
231
|
+
)
|
|
232
|
+
assert title_only == f"# My Project\n\n{badge}"
|
|
233
|
+
# An empty/missing README falls back to the provided project title
|
|
234
|
+
from_empty = add_doi_badge_to_readme("", badge=badge, title="My Project")
|
|
235
|
+
assert from_empty == f"# My Project\n\n{badge}"
|
|
236
|
+
# An existing DOI badge is replaced, not duplicated, and sibling badges are
|
|
237
|
+
# preserved in place
|
|
238
|
+
other_badge = "[](https://example.com)"
|
|
239
|
+
old_badge = "[](https://doi.org/10.5281/zenodo.111)" # noqa: E501
|
|
240
|
+
with_old = f"# My Project\n{other_badge}\n\n{old_badge}\n\nBody.\n"
|
|
241
|
+
refreshed = add_doi_badge_to_readme(
|
|
242
|
+
with_old, badge=badge, title="My Project"
|
|
243
|
+
)
|
|
244
|
+
assert refreshed.count("[ == 1
|
|
245
|
+
assert badge in refreshed
|
|
246
|
+
assert "zenodo.111" not in refreshed
|
|
247
|
+
assert other_badge in refreshed
|
|
248
|
+
assert "Body." in refreshed
|
|
249
|
+
|
|
250
|
+
|
|
166
251
|
def test_read_authors_from_cff(tmp_dir):
|
|
167
252
|
# No file present yields an empty list
|
|
168
253
|
assert read_authors_from_cff() == []
|
|
@@ -27,7 +27,7 @@ calkit/office.py,sha256=mZqCxkIsmWthBAeJZ5SiGe21fn5zD2zXsy1E6nQIpWE,1291
|
|
|
27
27
|
calkit/ops.py,sha256=lLlZAFeplU8uLeMavr99d__Iof-YYwKijus74WfLipk,854
|
|
28
28
|
calkit/overleaf.py,sha256=5SI8HwglLVtVlzj7d15Bft_3ZC6AHn3IrAbqMKOAPX0,30170
|
|
29
29
|
calkit/pipeline.py,sha256=PYOk_RHQAQL_SiSh-nV69OFxQ6Da7zbC4mBd2dw5rCo,63212
|
|
30
|
-
calkit/releases.py,sha256=
|
|
30
|
+
calkit/releases.py,sha256=JSmVX2s28WVJ5Lwitwjq5eRgUHZ38k6VbehEK-dR4mg,17478
|
|
31
31
|
calkit/server.py,sha256=GQm1bI5Q1NLFNwQL-iP6j4iWKUpKpP3cLEyfj5IMwe4,22009
|
|
32
32
|
calkit/cli/__init__.py,sha256=pP_1wFuewdUUvEWTtaEcdKblPaSYuTvthQb2Ef08UMo,1921
|
|
33
33
|
calkit/cli/check.py,sha256=RgFCY1xrqY5Hl2iSH7aA2ybyDpYfk7e65HntNjngN3M,49979
|
|
@@ -39,7 +39,7 @@ calkit/cli/dev.py,sha256=cu4QsfDiA_KurGx4WJcgA2qgfghMoZutE8kl4IZbUcM,1070
|
|
|
39
39
|
calkit/cli/import_.py,sha256=5j2ANLq6v7HOku9kJUWylwvQnJfkb_OUKCNOdv1BQXU,18264
|
|
40
40
|
calkit/cli/latex.py,sha256=dhcbVNcR3YjVSD5mo-OBtZN1FhH4mv4mlGnuP19EbjU,6220
|
|
41
41
|
calkit/cli/list.py,sha256=iWP3gfXnl13ZciXVpbZQlcu4hAQkBnfvp_D--4T08-0,6084
|
|
42
|
-
calkit/cli/new.py,sha256=
|
|
42
|
+
calkit/cli/new.py,sha256=OEw4fiT6KGTIRBevRzmhKy2sZCRs9zjX1M9O_ctTork,125469
|
|
43
43
|
calkit/cli/notebooks.py,sha256=dEjJ1qeh6SG99chhgUaxe_Cpv9hGERR98fBE6dscZmo,21381
|
|
44
44
|
calkit/cli/office.py,sha256=jVSTvbl91TCzlglST5O2b8hdApZA_QHw_UiEQFJqxdc,1754
|
|
45
45
|
calkit/cli/overleaf.py,sha256=bS-SkYsSqqhC9YsP-NCzpYJCGS3820w18w_s8JOFihg,25216
|
|
@@ -89,7 +89,7 @@ calkit/tests/test_magics.py,sha256=1O_hYPLMBVQJj8rLCFV3sU2DejlLLnk6Tv4_Tr-FZHQ,2
|
|
|
89
89
|
calkit/tests/test_matlab.py,sha256=7yFKOYDCtxYIkRyFOwTIxlvzx03Pac0FKGIUT4Zx7zA,7589
|
|
90
90
|
calkit/tests/test_notebooks.py,sha256=6xUpHjCbCv08oJkArj-NkTUMlz9zzm8pf1qam3s27M0,2692
|
|
91
91
|
calkit/tests/test_pipeline.py,sha256=crqI5YJcSb0_-imFubxv-ZWnRJ1j8NYgsuNjI-z9iUg,83661
|
|
92
|
-
calkit/tests/test_releases.py,sha256=
|
|
92
|
+
calkit/tests/test_releases.py,sha256=if6OjeZbUtjyyZ2CMQWhxQPRR8QD2kv5CXkEbOAL9Kc,14199
|
|
93
93
|
calkit/tests/test_templates.py,sha256=RN4RIgmuFlmFYQFgfJUYS-KaLmie8fnWzmfg5Ay1egk,430
|
|
94
94
|
calkit/tests/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
95
95
|
calkit/tests/cli/test_check.py,sha256=TPdG1R-h7Byinsln9n3WegRuBWN0bHltuRcOROCZhwQ,6767
|
|
@@ -98,7 +98,7 @@ calkit/tests/cli/test_config.py,sha256=Tl4LWfi81eQo6fUgJsoZRNPj_LfkKH-s42HRg5Mxh
|
|
|
98
98
|
calkit/tests/cli/test_import.py,sha256=e2BToVPebf4NalFQuIgyTNJHwbc9VMc6AYO-FAhYbQ0,663
|
|
99
99
|
calkit/tests/cli/test_latex.py,sha256=SqDbenoFtnsgkfqFjR2Jhw6TJsYQBtLqIGjM3PJmddc,3604
|
|
100
100
|
calkit/tests/cli/test_list.py,sha256=vwPGDANLzFR9neWmeT4idS8vaYS2w7UoZZ0Q3ItF9kw,1801
|
|
101
|
-
calkit/tests/cli/test_new.py,sha256=
|
|
101
|
+
calkit/tests/cli/test_new.py,sha256=z0XgfJJ-nB_cSuxH_LLL8ug9hmtMspb7dbaqFFIZrY8,45267
|
|
102
102
|
calkit/tests/cli/test_notebooks.py,sha256=pJX6KV45tNBd-ZpqyoayDzNop9-maRIN_fC2j3EcPf0,7899
|
|
103
103
|
calkit/tests/cli/test_overleaf.py,sha256=Y-ud4kZHh3nhyoZlXrtMfx61z-GPNytUpfDHMad3tuA,16474
|
|
104
104
|
calkit/tests/cli/test_scheduler.py,sha256=orCXPBbn9Mx4moemWNSfsil5cGCOcNgRgw6Yy5zDwjk,6061
|
|
@@ -118,23 +118,23 @@ calkit/tests/models/test_pipeline.py,sha256=AJsMAX4928U3_Omt0_8K96U5LU_KoNErgpHe
|
|
|
118
118
|
calkit/agent_skills/add-pipeline-stage/SKILL.md,sha256=kpYYb-rJsS4B9p1Ub3gL21irCG5ZZ4DvWZpdJeEwPZk,3772
|
|
119
119
|
calkit/agent_skills/conventions/SKILL.md,sha256=nAM2FjSMk6ED56Dr5zh2bL_dhfzDra-h2ZgzHU7ruS4,9524
|
|
120
120
|
calkit/agent_skills/create-pipeline/SKILL.md,sha256=2FGw1iDQVRk5FUq79GP3lPdgvgof2Wi1O9O-abGGtgs,5422
|
|
121
|
-
calkit_python-0.41.
|
|
122
|
-
calkit_python-0.41.
|
|
123
|
-
calkit_python-0.41.
|
|
124
|
-
calkit_python-0.41.
|
|
125
|
-
calkit_python-0.41.
|
|
126
|
-
calkit_python-0.41.
|
|
127
|
-
calkit_python-0.41.
|
|
128
|
-
calkit_python-0.41.
|
|
129
|
-
calkit_python-0.41.
|
|
130
|
-
calkit_python-0.41.
|
|
131
|
-
calkit_python-0.41.
|
|
132
|
-
calkit_python-0.41.
|
|
133
|
-
calkit_python-0.41.
|
|
134
|
-
calkit_python-0.41.
|
|
135
|
-
calkit_python-0.41.
|
|
136
|
-
calkit_python-0.41.
|
|
137
|
-
calkit_python-0.41.
|
|
138
|
-
calkit_python-0.41.
|
|
139
|
-
calkit_python-0.41.
|
|
140
|
-
calkit_python-0.41.
|
|
121
|
+
calkit_python-0.41.9.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
|
|
122
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/package.json,sha256=INxx8QhvSl7KP6yL7A7-m2-FIsnB__mYEWG_Eq5RP-c,6651
|
|
123
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=6w0b5y8LztEv2tErajJ5d39yBryld02crX0CG3zZFNs,6509
|
|
124
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
|
|
125
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
|
|
126
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
|
|
127
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
|
|
128
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/909.e3f9cc3408834a7fdcc3.js,sha256=4_nMNAiDSn_cw7UjIHEwone4fizrvqrqSgbwUWvjmoU,114571
|
|
129
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
|
|
130
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
|
|
131
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
|
|
132
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.65469af996e7a96aa983.js,sha256=ZUaa-ZbnqWqpgxIpcQcRX7auvhOBkPH2YHNID5udGQs,8737
|
|
133
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
|
|
134
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
|
|
135
|
+
calkit_python-0.41.9.data/data/share/jupyter/labextensions/calkit/install.json,sha256=DK9d8G-q-rMVlcT3rAeGIyo3REWKw6FySBZceLU9yaw,187
|
|
136
|
+
calkit_python-0.41.9.dist-info/METADATA,sha256=7i5A57UBf2R8wI-wjBdvw-FmhD73A5MG2rCHgrj4OlU,12070
|
|
137
|
+
calkit_python-0.41.9.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
138
|
+
calkit_python-0.41.9.dist-info/entry_points.txt,sha256=2iQBBzjTAOdk66CwS-f3ecXXW5DjUqkG1KBRj8mHI1I,133
|
|
139
|
+
calkit_python-0.41.9.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
|
|
140
|
+
calkit_python-0.41.9.dist-info/RECORD,,
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|