calkit-python 0.45.2__py3-none-any.whl → 0.45.3__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.
Files changed (21) hide show
  1. calkit/cli/new.py +4 -1
  2. calkit/tests/cli/test_new.py +50 -6
  3. {calkit_python-0.45.2.dist-info → calkit_python-0.45.3.dist-info}/METADATA +2 -2
  4. {calkit_python-0.45.2.dist-info → calkit_python-0.45.3.dist-info}/RECORD +21 -21
  5. {calkit_python-0.45.2.dist-info → calkit_python-0.45.3.dist-info}/entry_points.txt +1 -1
  6. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/etc/jupyter/jupyter_server_config.d/calkit.json +0 -0
  7. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/package.json +0 -0
  8. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig +0 -0
  9. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json +0 -0
  10. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js +0 -0
  11. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js +0 -0
  12. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js +0 -0
  13. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js +0 -0
  14. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js +0 -0
  15. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  16. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png +0 -0
  17. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js +0 -0
  18. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/style.js +0 -0
  19. {calkit_python-0.45.2.data → calkit_python-0.45.3.data}/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json +0 -0
  20. {calkit_python-0.45.2.dist-info → calkit_python-0.45.3.dist-info}/WHEEL +0 -0
  21. {calkit_python-0.45.2.dist-info → calkit_python-0.45.3.dist-info}/licenses/LICENSE +0 -0
calkit/cli/new.py CHANGED
@@ -3710,6 +3710,9 @@ def new_release(
3710
3710
  f"'{project_name}'."
3711
3711
  )
3712
3712
  record_id = None
3713
+ # SPDX IDs are case-insensitive, but the InvenioRDM license vocabulary
3714
+ # used by Zenodo and CaltechDATA only accepts them lowercased
3715
+ license_ids = [lid.strip().lower() for lid in license_ids]
3713
3716
  # Detect project license IDs if necessary
3714
3717
  if not license_ids:
3715
3718
  license_file = calkit.licenses.find_license_file()
@@ -3756,7 +3759,7 @@ def new_release(
3756
3759
  publication_date=release_date,
3757
3760
  version=name,
3758
3761
  publisher=publisher_name,
3759
- rights=[{"id": lid for lid in license_ids}],
3762
+ rights=[{"id": lid} for lid in license_ids],
3760
3763
  )
3761
3764
  # Add related identifiers
3762
3765
  github_url = calkit.detect_project_github_url()
@@ -1100,6 +1100,10 @@ def test_new_nix_env_stages_flake(tmp_dir):
1100
1100
  def test_new_release(tmp_dir, monkeypatch, httpserver):
1101
1101
  # Set up a mock Zenodo API so the test doesn't depend on the real sandbox
1102
1102
  record_id = "test-record-abc123"
1103
+ # A new version of a record gets its own ID, which the client must switch
1104
+ # to; only the draft endpoints below are shared between the two
1105
+ version_record_id = "test-record-def456"
1106
+ any_record_id = f"(?:{record_id}|{version_record_id})"
1103
1107
  doi = "10.5072/zenodo.test123"
1104
1108
  # Point the Zenodo base URL at the local mock server and provide a dummy
1105
1109
  # token so no real credentials are needed. Both env vars are inherited
@@ -1115,26 +1119,27 @@ def test_new_release(tmp_dir, monkeypatch, httpserver):
1115
1119
  ).respond_with_json({"id": record_id, "pids": {}})
1116
1120
  # POST /records/{id}/draft/files – initiate a file upload slot
1117
1121
  httpserver.expect_request(
1118
- re.compile(rf"^/records/{record_id}/draft/files$"), method="POST"
1122
+ re.compile(rf"^/records/{any_record_id}/draft/files$"), method="POST"
1119
1123
  ).respond_with_json({"entries": []})
1120
1124
  # PUT /records/{id}/draft/files/{filename}/content – stream file bytes
1121
1125
  httpserver.expect_request(
1122
- re.compile(rf"^/records/{record_id}/draft/files/.+/content$"),
1126
+ re.compile(rf"^/records/{any_record_id}/draft/files/.+/content$"),
1123
1127
  method="PUT",
1124
1128
  ).respond_with_data("", status=200)
1125
1129
  # POST /records/{id}/draft/files/{filename}/commit – finalise upload
1126
1130
  httpserver.expect_request(
1127
- re.compile(rf"^/records/{record_id}/draft/files/.+/commit$"),
1131
+ re.compile(rf"^/records/{any_record_id}/draft/files/.+/commit$"),
1128
1132
  method="POST",
1129
1133
  ).respond_with_json({"key": "file", "status": "completed"})
1130
1134
  # POST /records/{id}/draft/pids/doi – reserve a DOI for a draft
1131
1135
  httpserver.expect_request(
1132
- re.compile(rf"^/records/{record_id}/draft/pids/doi$"), method="POST"
1136
+ re.compile(rf"^/records/{any_record_id}/draft/pids/doi$"),
1137
+ method="POST",
1133
1138
  ).respond_with_json({"pids": {"doi": {"identifier": doi}}})
1134
1139
  # GET /records/{id}/draft/files – list files already in the draft
1135
1140
  # (used by --reupload to decide which files to delete first)
1136
1141
  httpserver.expect_request(
1137
- re.compile(rf"^/records/{record_id}/draft/files$"), method="GET"
1142
+ re.compile(rf"^/records/{any_record_id}/draft/files$"), method="GET"
1138
1143
  ).respond_with_json({"entries": []})
1139
1144
  # POST /records/{id}/draft/actions/publish – publish the draft
1140
1145
  httpserver.expect_request(
@@ -1143,6 +1148,16 @@ def test_new_release(tmp_dir, monkeypatch, httpserver):
1143
1148
  ).respond_with_json(
1144
1149
  {"id": record_id, "pids": {"doi": {"identifier": doi}}}
1145
1150
  )
1151
+ # POST /records/{id}/versions – create a new version of a record, and
1152
+ # PUT /records/{new_id}/draft – set that new version's metadata; the draft
1153
+ # is only mocked under the new ID, so a client that failed to switch to it
1154
+ # would get no response here
1155
+ httpserver.expect_request(
1156
+ re.compile(rf"^/records/{record_id}/versions$"), method="POST"
1157
+ ).respond_with_json({"id": version_record_id, "pids": {}})
1158
+ httpserver.expect_request(
1159
+ re.compile(rf"^/records/{version_record_id}/draft$"), method="PUT"
1160
+ ).respond_with_json({"id": version_record_id, "pids": {}})
1146
1161
  # GET /records/{id} – fetch the published record for post-test assertions
1147
1162
  httpserver.expect_request(
1148
1163
  re.compile(rf"^/records/{record_id}$"), method="GET"
@@ -1267,7 +1282,6 @@ def test_new_release(tmp_dir, monkeypatch, httpserver):
1267
1282
  git_tags = git.Repo().tags
1268
1283
  assert "v0.1.0" in [tag.name for tag in git_tags]
1269
1284
  # Check the license is correct
1270
- # TODO: It seems like we can't use multiple license IDs with the API
1271
1285
  record_id = release["record_id"]
1272
1286
  record = calkit.invenio.get(f"/records/{record_id}")
1273
1287
  metadata = record["metadata"]
@@ -1275,6 +1289,36 @@ def test_new_release(tmp_dir, monkeypatch, httpserver):
1275
1289
  assert metadata["license"] == {"id": "cc-by-4.0"}
1276
1290
  related = metadata["related_identifiers"]
1277
1291
  assert related[0]["identifier"] == "https://github.com/calkit/test-project"
1292
+ # Issue #1582: SPDX IDs are case-insensitive, but the InvenioRDM license
1293
+ # vocabulary rejects anything but the lowercase form, so release again
1294
+ # with the licenses spelled in uppercase to check they are normalized
1295
+ subprocess.check_call(
1296
+ [
1297
+ "calkit",
1298
+ "new",
1299
+ "release",
1300
+ "--name",
1301
+ "v0.2.0",
1302
+ "--license",
1303
+ "MIT",
1304
+ "--license",
1305
+ "CC-BY-4.0",
1306
+ "--draft",
1307
+ "--no-github",
1308
+ ]
1309
+ )
1310
+ # Every set of metadata sent to the service should have carried both
1311
+ # licenses as separate lowercase rights entries, rather than collapsing
1312
+ # them into one: the first release detected them from the LICENSE file,
1313
+ # the second took them from the uppercase --license options
1314
+ rights_sent = [
1315
+ body["metadata"]["rights"]
1316
+ for request, _ in httpserver.log
1317
+ if (body := request.get_json(silent=True)) and "metadata" in body
1318
+ ]
1319
+ expected_rights = [{"id": "mit"}, {"id": "cc-by-4.0"}]
1320
+ assert len(rights_sent) >= 2
1321
+ assert rights_sent == [expected_rights] * len(rights_sent)
1278
1322
  # TODO: Test that we can delete the release
1279
1323
  # This will fail if it's not a draft
1280
1324
  # subprocess.check_call(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: calkit-python
3
- Version: 0.45.2
3
+ Version: 0.45.3
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -192,7 +192,7 @@ If you want to use Calkit without installing it,
192
192
  you can use uv's `uvx` command to run it directly:
193
193
 
194
194
  ```sh
195
- uvx calk9 --help
195
+ uvx ck9 --help
196
196
  ```
197
197
 
198
198
  ### Nix
@@ -46,7 +46,7 @@ calkit/cli/hub.py,sha256=ZBOlL7-mV57q_ynr4hPuhV7NlkKEkINSRksXD-jjiOg,2972
46
46
  calkit/cli/import_.py,sha256=ZAfPstDm_EoG9i8RMvVfctLOFMv0GbstkH0Wb7iq-9Q,18875
47
47
  calkit/cli/latex.py,sha256=mvNxzZkWlwJnYA_l6NFEflV0AGYHPIT1ALUxQQGHZJ0,19708
48
48
  calkit/cli/list.py,sha256=E40uJe_jRQcRin1RO4yFMUncKMpQe2syWhC54xzDhoQ,15090
49
- calkit/cli/new.py,sha256=SLhotKsToW0rNo7C2e5uLz9ESvBgnQwprkQqX51A50Y,149508
49
+ calkit/cli/new.py,sha256=t3CHyNFTnzKUAuph31HsWuUxK4iw7s28IVC5STSTxy0,149724
50
50
  calkit/cli/notebooks.py,sha256=aR4I0qatOtkrAxEG5PVLej20SBLKo8qr-lxDSzgljUQ,38836
51
51
  calkit/cli/office.py,sha256=jVSTvbl91TCzlglST5O2b8hdApZA_QHw_UiEQFJqxdc,1754
52
52
  calkit/cli/overleaf.py,sha256=PTL3MH3y3qlSCkZ39yaiWUWU6U7aiGyh6aKLA068-5U,38700
@@ -135,7 +135,7 @@ calkit/tests/cli/test_hub.py,sha256=z3ne8Bnjv-V85OEh15FbAV4STrFwZKMgl_DgWwQ2wzY,
135
135
  calkit/tests/cli/test_import.py,sha256=e2BToVPebf4NalFQuIgyTNJHwbc9VMc6AYO-FAhYbQ0,663
136
136
  calkit/tests/cli/test_latex.py,sha256=92ZhSIYOiBb0TKZmODTVvkp0dU_X5ZuGvrdA4v5bzQo,10976
137
137
  calkit/tests/cli/test_list.py,sha256=5jc_OYI_rXNVv2UQc6IS8ItjQbBwEI5IDw5xKU_Uk98,9165
138
- calkit/tests/cli/test_new.py,sha256=tDat19K_ussPHlYYjqhKFKQUNNbHboiYpn79v0XGdqo,65017
138
+ calkit/tests/cli/test_new.py,sha256=q7kmZQ9IrMhDOcHuIXU0GJs0Z54SpX12vct8ntQaKLM,66977
139
139
  calkit/tests/cli/test_notebooks.py,sha256=2t1KiGhEz9H9LcIdWy4jGM05REUxJpWiIg6fSpX12ME,10678
140
140
  calkit/tests/cli/test_overleaf.py,sha256=w8tqRwOC6ilQX8wfkqppTBmcouxs61zEoq-R5G1emY8,49767
141
141
  calkit/tests/cli/test_scheduler.py,sha256=YfJi_fcRlQt1bdFyo3b8BFelA1PcH-wn5lAVXiH7Zj4,24109
@@ -159,22 +159,22 @@ calkit/tests/models/test_pipeline.py,sha256=hglkTBry1ONKbzN1HmlpefbrqAbc-668C0MQ
159
159
  calkit/agent_skills/add-pipeline-stage/SKILL.md,sha256=kpYYb-rJsS4B9p1Ub3gL21irCG5ZZ4DvWZpdJeEwPZk,3772
160
160
  calkit/agent_skills/conventions/SKILL.md,sha256=osbAtYU0AwROZHgmOoQYbqYr3JwG_v-cJAmandm7yN4,9738
161
161
  calkit/agent_skills/create-pipeline/SKILL.md,sha256=2FGw1iDQVRk5FUq79GP3lPdgvgof2Wi1O9O-abGGtgs,5422
162
- calkit_python-0.45.2.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
163
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/package.json,sha256=tYRdVVqmPBoUJzNrMc7Da9Lk-NB54vhnplKRSlOTMIE,6224
164
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=NBG3t7gFYb6_2J-yPU29qS7Ck9pYgm8-wC5Q1LrzQeI,6082
165
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
166
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
167
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
168
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
169
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js,sha256=bYKFznxFh4rFCPs8tWnbZgaFGp72DuPZGdkzYCoCaSU,114583
170
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
171
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
172
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
173
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js,sha256=16Q8eUj2kNN9Gaeoe3hOSEUPMJ5IUHQnJF1h9DRUIJY,8737
174
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
175
- calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
176
- calkit_python-0.45.2.dist-info/METADATA,sha256=Rr27zNPVQ_KH7uaw8FcHthxM9g6dHF_jsYw6aTp8qhA,12818
177
- calkit_python-0.45.2.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
178
- calkit_python-0.45.2.dist-info/entry_points.txt,sha256=2iQBBzjTAOdk66CwS-f3ecXXW5DjUqkG1KBRj8mHI1I,133
179
- calkit_python-0.45.2.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
180
- calkit_python-0.45.2.dist-info/RECORD,,
162
+ calkit_python-0.45.3.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
163
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/package.json,sha256=tYRdVVqmPBoUJzNrMc7Da9Lk-NB54vhnplKRSlOTMIE,6224
164
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=NBG3t7gFYb6_2J-yPU29qS7Ck9pYgm8-wC5Q1LrzQeI,6082
165
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
166
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
167
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
168
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
169
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js,sha256=bYKFznxFh4rFCPs8tWnbZgaFGp72DuPZGdkzYCoCaSU,114583
170
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
171
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
172
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
173
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js,sha256=16Q8eUj2kNN9Gaeoe3hOSEUPMJ5IUHQnJF1h9DRUIJY,8737
174
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
175
+ calkit_python-0.45.3.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
176
+ calkit_python-0.45.3.dist-info/METADATA,sha256=Z809eOplrqKq9iYfrwUT3yBjzhSR1dfjXNPaHMaaG8w,12816
177
+ calkit_python-0.45.3.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
178
+ calkit_python-0.45.3.dist-info/entry_points.txt,sha256=TtpHpcv2vFVAVYxFVp0XrwCV_z7FWIOguEiypXRDoOw,131
179
+ calkit_python-0.45.3.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
180
+ calkit_python-0.45.3.dist-info/RECORD,,
@@ -1,7 +1,7 @@
1
1
  [console_scripts]
2
- calk9 = calkit.cli:run
3
2
  calkit = calkit.cli:run
4
3
  ck = calkit.cli:run
4
+ ck9 = calkit.cli:run
5
5
 
6
6
  [fsspec.specs]
7
7
  ck = calkit.fs:CalkitFileSystem