calkit-python 0.19.1__tar.gz → 0.20.1__tar.gz

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 (142) hide show
  1. calkit_python-0.20.1/.pre-commit-config.yaml +24 -0
  2. calkit_python-0.20.1/CONTRIBUTING.md +75 -0
  3. calkit_python-0.20.1/Makefile +36 -0
  4. {calkit_python-0.19.1 → calkit_python-0.20.1}/PKG-INFO +23 -23
  5. {calkit_python-0.19.1 → calkit_python-0.20.1}/README.md +16 -12
  6. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/__init__.py +4 -1
  7. calkit_python-0.20.1/calkit/cli/import_.py +247 -0
  8. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/new.py +447 -0
  9. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cloud.py +9 -1
  10. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/config.py +23 -8
  11. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/dvc.py +11 -3
  12. calkit_python-0.20.1/calkit/github.py +70 -0
  13. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/models.py +1 -0
  14. calkit_python-0.20.1/calkit/releases.py +159 -0
  15. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/jfm/jfm.bst +5 -5
  16. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/jfm/jfm.cls +1 -1
  17. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/jfm/lineno-FLM.sty +1 -1
  18. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/jfm/upmath.sty +0 -1
  19. calkit_python-0.20.1/calkit/zenodo.py +82 -0
  20. calkit_python-0.20.1/docs/img/connect-zenodo.png +0 -0
  21. calkit_python-0.20.1/docs/releases.md +86 -0
  22. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/existing-project.md +4 -4
  23. calkit_python-0.20.1/docs/tutorials/index.md +12 -0
  24. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/notebook-pipeline.md +1 -0
  25. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/office.md +26 -25
  26. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/openfoam.md +2 -2
  27. {calkit_python-0.19.1 → calkit_python-0.20.1}/mkdocs.yml +2 -0
  28. {calkit_python-0.19.1 → calkit_python-0.20.1}/pyproject.toml +35 -7
  29. {calkit_python-0.19.1 → calkit_python-0.20.1}/uv.lock +1378 -428
  30. calkit_python-0.19.1/calkit/cli/import_.py +0 -164
  31. {calkit_python-0.19.1 → calkit_python-0.20.1}/.github/FUNDING.yml +0 -0
  32. {calkit_python-0.19.1 → calkit_python-0.20.1}/.github/workflows/docs.yml +0 -0
  33. {calkit_python-0.19.1 → calkit_python-0.20.1}/.github/workflows/publish-test.yml +0 -0
  34. {calkit_python-0.19.1 → calkit_python-0.20.1}/.github/workflows/publish.yml +0 -0
  35. {calkit_python-0.19.1 → calkit_python-0.20.1}/.gitignore +0 -0
  36. {calkit_python-0.19.1 → calkit_python-0.20.1}/LICENSE +0 -0
  37. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/__main__.py +0 -0
  38. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/calc.py +0 -0
  39. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/check.py +0 -0
  40. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/__init__.py +0 -0
  41. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/check.py +0 -0
  42. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/config.py +0 -0
  43. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/core.py +0 -0
  44. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/list.py +0 -0
  45. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/main.py +0 -0
  46. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/notebooks.py +0 -0
  47. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/office.py +0 -0
  48. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/cli/update.py +0 -0
  49. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/conda.py +0 -0
  50. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/core.py +0 -0
  51. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/datasets.py +0 -0
  52. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/docker.py +0 -0
  53. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/git.py +0 -0
  54. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/gui.py +0 -0
  55. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/jupyter.py +0 -0
  56. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/magics.py +0 -0
  57. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/office.py +0 -0
  58. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/ops.py +0 -0
  59. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/server.py +0 -0
  60. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/__init__.py +0 -0
  61. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/core.py +0 -0
  62. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/__init__.py +0 -0
  63. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/article/paper.tex +0 -0
  64. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/core.py +0 -0
  65. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/templates/latex/jfm/paper.tex +0 -0
  66. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/__init__.py +0 -0
  67. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/cli/__init__.py +0 -0
  68. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/cli/test_list.py +0 -0
  69. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/cli/test_main.py +0 -0
  70. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/cli/test_new.py +0 -0
  71. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_calc.py +0 -0
  72. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_check.py +0 -0
  73. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_conda.py +0 -0
  74. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_core.py +0 -0
  75. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_dvc.py +0 -0
  76. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_jupyter.py +0 -0
  77. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_magics.py +0 -0
  78. {calkit_python-0.19.1 → calkit_python-0.20.1}/calkit/tests/test_templates.py +0 -0
  79. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/CNAME +0 -0
  80. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/apps.md +0 -0
  81. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/calculations.md +0 -0
  82. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/calkit-yaml.md +0 -0
  83. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/cli-reference.md +0 -0
  84. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/cloud-integration.md +0 -0
  85. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/datasets.md +0 -0
  86. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/environments.md +0 -0
  87. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/examples.md +0 -0
  88. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/help.md +0 -0
  89. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/img/c-to-the-k-white.svg +0 -0
  90. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/img/calkit-no-bg.png +0 -0
  91. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/index.md +0 -0
  92. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/installation.md +0 -0
  93. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/local-server.md +0 -0
  94. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/pipeline/index.md +0 -0
  95. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/pipeline/manual-steps.md +0 -0
  96. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/references.md +0 -0
  97. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  98. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/conda-envs.md +0 -0
  99. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/first-project.md +0 -0
  100. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  101. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  102. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  103. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  104. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  105. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  106. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  107. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  108. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  109. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  110. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  111. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  112. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  113. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  114. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/create-project.png +0 -0
  115. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  116. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/excel-chart.png +0 -0
  117. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/excel-data.png +0 -0
  118. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  119. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/needs-clone.png +0 -0
  120. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/new-stage.png +0 -0
  121. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  122. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  123. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/status-more-rows.png +0 -0
  124. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  125. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/untracked-data.png +0 -0
  126. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/updated-publication.png +0 -0
  127. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  128. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/office/workflow-page.png +0 -0
  129. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/clone.png +0 -0
  130. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/create-project.png +0 -0
  131. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  132. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  133. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  134. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/new-token.png +0 -0
  135. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/reclone.png +0 -0
  136. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  137. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/img/run-proc.png +0 -0
  138. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/latex-codespaces.md +0 -0
  139. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/matlab.md +0 -0
  140. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/tutorials/procedures.md +0 -0
  141. {calkit_python-0.19.1 → calkit_python-0.20.1}/docs/version-control.md +0 -0
  142. {calkit_python-0.19.1 → calkit_python-0.20.1}/test/pipeline.ipynb +0 -0
@@ -0,0 +1,24 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: "v4.4.0"
4
+ hooks:
5
+ - id: check-case-conflict
6
+ - id: check-merge-conflict
7
+ - id: end-of-file-fixer
8
+ - id: trailing-whitespace
9
+
10
+ - repo: https://github.com/astral-sh/ruff-pre-commit
11
+ rev: "v0.6.3"
12
+ hooks:
13
+ - id: ruff
14
+ args: [--exit-non-zero-on-fix, --config=pyproject.toml]
15
+ exclude: calkit
16
+ - id: ruff-format
17
+ args: [--config=pyproject.toml]
18
+ exclude: calkit
19
+
20
+ - repo: https://github.com/pre-commit/mirrors-prettier
21
+ rev: "v3.0.3"
22
+ hooks:
23
+ - id: prettier
24
+ exclude: calkit
@@ -0,0 +1,75 @@
1
+ # Contributing to Calkit
2
+
3
+ Thank you for considering contributing to Calkit!
4
+ We welcome contributions of all kinds, including code, documentation,
5
+ bug reports, and feature suggestions.
6
+ This guide will help you get started.
7
+
8
+ ## 🛠 How to contribute
9
+
10
+ ### 1. Find an issue to work on
11
+
12
+ - Check the **[backlog](https://github.com/orgs/calkit/projects/1/views/1)**
13
+ for issues that are ready to be worked on.
14
+ - Look for issues labeled `good first issue` if you're new.
15
+ - If you have an idea, open a new issue and discuss it before coding.
16
+
17
+ ### 2. Set up your development environment
18
+
19
+ 1. [**Fork** the repository](https://github.com/calkit/calkit/fork).
20
+ 1. **Clone** your fork locally:
21
+ ```bash
22
+ git clone https://github.com/{your-username}/calkit.git
23
+ cd calkit
24
+ ```
25
+ 1. **Install system-level dependencies:**
26
+ - [Docker](https://docker.com)
27
+ - [Miniforge](https://conda-forge.org/download/)
28
+ - [uv](https://docs.astral.sh/uv/getting-started/installation/)
29
+ 1. **Run tests** to ensure everything is working:
30
+ ```bash
31
+ uv run pytest
32
+ ```
33
+
34
+ ### 3. Make your changes
35
+
36
+ - Create a new branch:
37
+ ```bash
38
+ git checkout -b your-feature-name
39
+ ```
40
+ - Check and fix code formatting:
41
+ ```bash
42
+ make format
43
+ ```
44
+ - Commit your changes
45
+ (use the imperative mood and capitalize the first letter,
46
+ but don't use punctuation):
47
+ ```bash
48
+ git add .
49
+ git commit -m "Short description of your change"
50
+ ```
51
+ - Push your branch:
52
+ ```bash
53
+ git push origin your-feature-name -u
54
+ ```
55
+
56
+ ### 4. Submit a pull request (PR)
57
+
58
+ - Open a **Pull request** on GitHub.
59
+ - Link the PR to the issue it resolves by adding "resolves #{issue number}"
60
+ to the description.
61
+ - Wait for a review and make necessary changes.
62
+
63
+ ## 💡 Other ways to contribute
64
+
65
+ - **Report bugs**: Open an issue with detailed reproduction steps.
66
+ - **Improve documentation**: Help us make Calkit's docs better.
67
+ - **Suggest features**: Share your ideas for improvements.
68
+
69
+ ## 🎉 Join the community
70
+
71
+ - Participate in **[GitHub Discussions](https://github.com/calkit/discussions)**.
72
+ - Join our [**Discord**](https://discord.gg/ubb7gAXc) for real-time collaboration.
73
+ - Follow our updates on [**LinkedIn**](https://linkedin.com/company/calkit).
74
+
75
+ We appreciate your help in making Calkit better! 🚀
@@ -0,0 +1,36 @@
1
+ .PHONY: help
2
+ help: ## Show this help.
3
+ @uv run python -c "import re; \
4
+ [[print(f'\033[36m{m[0]:<20}\033[0m {m[1]}') for m in re.findall(r'^([a-zA-Z_-]+):.*?## (.*)$$', open(makefile).read(), re.M)] for makefile in ('$(MAKEFILE_LIST)').strip().split()]"
5
+
6
+ .PHONY: install
7
+ install: ## Create the project's virtual environment.
8
+ @echo "🚀 Creating virtual environment"
9
+ @uv sync
10
+
11
+ .PHONY: format
12
+ format: ## Automatically format files.
13
+ @echo "🚀 Linting code with pre-commit"
14
+ @uv run pre-commit run -a
15
+
16
+ .PHONY: check
17
+ check: format ## Run code quality tools.
18
+ @echo "🚀 Checking lock file consistency with 'pyproject.toml'"
19
+ @uv lock --locked
20
+ @echo "🚀 Static type checking with mypy"
21
+ @uv run mypy .
22
+ @echo "🚀 Checking for obsolete dependencies with deptry"
23
+ @uv run deptry .
24
+
25
+ .PHONY: test
26
+ test: ## Test the code with pytest.
27
+ @echo "🚀 Testing code with pytest"
28
+ @uv run pytest --cov --cov-config=pyproject.toml --cov-report=xml
29
+
30
+ .PHONY: docs-test
31
+ docs-test: ## Test if documentation can be built without warnings or errors.
32
+ @uv run mkdocs build -s
33
+
34
+ .PHONY: docs
35
+ docs: ## Build and serve the documentation.
36
+ @uv run mkdocs serve
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.19.1
3
+ Version: 0.20.1
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -10,11 +10,12 @@ License-File: LICENSE
10
10
  Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python :: 3
13
- Requires-Python: >=3.8
13
+ Requires-Python: >=3.9
14
14
  Requires-Dist: arithmeval
15
+ Requires-Dist: bibtexparser
15
16
  Requires-Dist: checksumdir
16
17
  Requires-Dist: docx2pdf
17
- Requires-Dist: dvc
18
+ Requires-Dist: dvc>=3.59.0
18
19
  Requires-Dist: eval-type-backport; python_version < '3.10'
19
20
  Requires-Dist: fastapi
20
21
  Requires-Dist: gitpython
@@ -27,17 +28,12 @@ Requires-Dist: pyjwt
27
28
  Requires-Dist: python-dotenv>=1
28
29
  Requires-Dist: pywin32; platform_system == 'Windows'
29
30
  Requires-Dist: requests
31
+ Requires-Dist: tqdm>=4.67.1
30
32
  Requires-Dist: typer
31
33
  Requires-Dist: uvicorn
32
34
  Provides-Extra: data
33
- Requires-Dist: pandas; extra == 'data'
34
- Requires-Dist: polars; extra == 'data'
35
- Provides-Extra: dev
36
- Requires-Dist: pytest; extra == 'dev'
37
- Provides-Extra: docs
38
- Requires-Dist: mkdocs; extra == 'docs'
39
- Requires-Dist: mkdocs-material; extra == 'docs'
40
- Requires-Dist: mkdocs-mermaid2-plugin; extra == 'docs'
35
+ Requires-Dist: pandas>=2.2.3; extra == 'data'
36
+ Requires-Dist: polars>=1.18.0; extra == 'data'
41
37
  Description-Content-Type: text/markdown
42
38
 
43
39
  <p align="center">
@@ -45,6 +41,19 @@ Description-Content-Type: text/markdown
45
41
  <img width="40%" src="docs/img/calkit-no-bg.png" alt="Calkit">
46
42
  </a>
47
43
  </p>
44
+ <p align="center">
45
+ <a href="https://docs.calkit.org" target="_blank">
46
+ Documentation
47
+ </a>
48
+ |
49
+ <a href="https://docs.calkit.org/tutorials" target="_blank">
50
+ Tutorials
51
+ </a>
52
+ |
53
+ <a href="https://github.com/orgs/calkit/discussions" target="_blank">
54
+ Discussions
55
+ </a>
56
+ </p>
48
57
 
49
58
  Calkit is a framework and toolkit for reproducible research projects.
50
59
  It acts as a top-level layer to integrate and simplify the use of enabling
@@ -57,8 +66,6 @@ Calkit also adds a domain-specific data model
57
66
  such that all aspects of the research process can be fully described in a
58
67
  single repository and therefore easily consumed by others.
59
68
 
60
- To learn more, see the [documentation](https://docs.calkit.org).
61
-
62
69
  ## Installation
63
70
 
64
71
  To install Calkit, [Git](https://git-scm.com) and Python must be installed.
@@ -131,17 +138,10 @@ calkit save -am "Run pipeline"
131
138
 
132
139
  This will commit and push to both GitHub and the Calkit Cloud.
133
140
 
134
- ## Tutorials
135
-
136
- - [LaTeX collaboration with GitHub Codespaces](https://docs.calkit.org/tutorials/latex-codespaces/)
137
- - [Jupyter notebook as a DVC pipeline](https://docs.calkit.org/tutorials/notebook-pipeline/)
138
- - [Keeping track of conda environments](https://docs.calkit.org/tutorials/conda-envs/)
139
- - [Defining and executing manual procedures](https://docs.calkit.org/tutorials/procedures/)
140
- - [Adding a new LaTeX-based publication with its own Docker build environment](https://docs.calkit.org/tutorials/adding-latex-pub-docker/)
141
- - [A reproducible workflow using Microsoft Office (Word and Excel)](https://docs.calkit.org/tutorials/office/)
142
- - [Reproducible OpenFOAM simulations](https://docs.calkit.org/tutorials/openfoam/)
141
+ ## Get involved
143
142
 
144
- See more in the [docs](https://docs.calkit.org).
143
+ We welcome all kinds of contributions!
144
+ See [CONTRIBUTING.md](CONTRIBUTING.md) to learn how to get involved.
145
145
 
146
146
  ## Why does reproducibility matter?
147
147
 
@@ -3,6 +3,19 @@
3
3
  <img width="40%" src="docs/img/calkit-no-bg.png" alt="Calkit">
4
4
  </a>
5
5
  </p>
6
+ <p align="center">
7
+ <a href="https://docs.calkit.org" target="_blank">
8
+ Documentation
9
+ </a>
10
+ |
11
+ <a href="https://docs.calkit.org/tutorials" target="_blank">
12
+ Tutorials
13
+ </a>
14
+ |
15
+ <a href="https://github.com/orgs/calkit/discussions" target="_blank">
16
+ Discussions
17
+ </a>
18
+ </p>
6
19
 
7
20
  Calkit is a framework and toolkit for reproducible research projects.
8
21
  It acts as a top-level layer to integrate and simplify the use of enabling
@@ -15,8 +28,6 @@ Calkit also adds a domain-specific data model
15
28
  such that all aspects of the research process can be fully described in a
16
29
  single repository and therefore easily consumed by others.
17
30
 
18
- To learn more, see the [documentation](https://docs.calkit.org).
19
-
20
31
  ## Installation
21
32
 
22
33
  To install Calkit, [Git](https://git-scm.com) and Python must be installed.
@@ -89,17 +100,10 @@ calkit save -am "Run pipeline"
89
100
 
90
101
  This will commit and push to both GitHub and the Calkit Cloud.
91
102
 
92
- ## Tutorials
93
-
94
- - [LaTeX collaboration with GitHub Codespaces](https://docs.calkit.org/tutorials/latex-codespaces/)
95
- - [Jupyter notebook as a DVC pipeline](https://docs.calkit.org/tutorials/notebook-pipeline/)
96
- - [Keeping track of conda environments](https://docs.calkit.org/tutorials/conda-envs/)
97
- - [Defining and executing manual procedures](https://docs.calkit.org/tutorials/procedures/)
98
- - [Adding a new LaTeX-based publication with its own Docker build environment](https://docs.calkit.org/tutorials/adding-latex-pub-docker/)
99
- - [A reproducible workflow using Microsoft Office (Word and Excel)](https://docs.calkit.org/tutorials/office/)
100
- - [Reproducible OpenFOAM simulations](https://docs.calkit.org/tutorials/openfoam/)
103
+ ## Get involved
101
104
 
102
- See more in the [docs](https://docs.calkit.org).
105
+ We welcome all kinds of contributions!
106
+ See [CONTRIBUTING.md](CONTRIBUTING.md) to learn how to get involved.
103
107
 
104
108
  ## Why does reproducibility matter?
105
109
 
@@ -1,4 +1,4 @@
1
- __version__ = "0.19.1"
1
+ __version__ = "0.20.1"
2
2
 
3
3
  from .core import *
4
4
  from . import git
@@ -12,3 +12,6 @@ from . import templates
12
12
  from . import conda
13
13
  from . import calc
14
14
  from . import check
15
+ from . import github
16
+ from . import zenodo
17
+ from . import releases
@@ -0,0 +1,247 @@
1
+ """CLI for importing objects."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import os
7
+ import subprocess
8
+ from typing import Annotated
9
+
10
+ import git
11
+ import requests
12
+ import typer
13
+ from tqdm import tqdm
14
+
15
+ import calkit
16
+ from calkit.cli import raise_error
17
+
18
+ import_app = typer.Typer(no_args_is_help=True)
19
+
20
+
21
+ @import_app.command(name="dataset")
22
+ def import_dataset(
23
+ src_path: Annotated[
24
+ str,
25
+ typer.Argument(
26
+ help=(
27
+ "Location of dataset, including project owner and name, e.g., "
28
+ "someone/some-project/data/some-data.csv"
29
+ )
30
+ ),
31
+ ],
32
+ dest_path: Annotated[
33
+ str,
34
+ typer.Argument(help="Output path at which to save."),
35
+ ] = None,
36
+ filter_paths: Annotated[
37
+ list[str],
38
+ typer.Option(
39
+ "--filter-paths",
40
+ help="Filter paths in target dataset if it's a folder.",
41
+ ),
42
+ ] = None,
43
+ no_commit: Annotated[
44
+ bool,
45
+ typer.Option("--no-commit", help="Do not commit changes to repo."),
46
+ ] = False,
47
+ no_dvc_pull: Annotated[
48
+ bool,
49
+ typer.Option(
50
+ "--no-dvc-pull", help="Do not pull imported dataset with DVC."
51
+ ),
52
+ ] = False,
53
+ overwrite: Annotated[
54
+ bool,
55
+ typer.Option(
56
+ "--overwrite",
57
+ "-f",
58
+ help="Force adding the dataset even if it already exists.",
59
+ ),
60
+ ] = False,
61
+ ):
62
+ """Import a dataset.
63
+
64
+ Currently only supports datasets kept in DVC, not Git.
65
+ """
66
+ # Ensure we don't already have a dataset at this path
67
+ path_split = src_path.split("/")
68
+ owner_name = path_split[0]
69
+ project_name = path_split[1]
70
+ path = "/".join(path_split[2:])
71
+ if dest_path is None:
72
+ ds_dest_path = path
73
+ else:
74
+ ds_dest_path = dest_path
75
+ ck_info = calkit.load_calkit_info()
76
+ datasets = ck_info.get("datasets", [])
77
+ ds_paths = [ds["path"] for ds in datasets]
78
+ if not overwrite and ds_dest_path in ds_paths:
79
+ raise_error("A dataset already exists in this project at this path")
80
+ elif overwrite and ds_dest_path in ds_paths:
81
+ datasets = [ds for ds in datasets if ds["path"] != ds_dest_path]
82
+ repo = git.Repo()
83
+ # Obtain, save, and commit the .dvc file for the dataset, or if this is
84
+ # kept in Git, just download the files and commit them here
85
+ typer.echo("Fetching import info")
86
+ params = None
87
+ if filter_paths is not None:
88
+ params = {"filter_paths": filter_paths}
89
+ try:
90
+ resp = calkit.cloud.get(
91
+ f"/projects/{owner_name}/{project_name}/datasets/{path}",
92
+ params=params,
93
+ )
94
+ except Exception as e:
95
+ raise_error(f"Failed to fetch dataset info from cloud: {e}")
96
+ dvc_import, git_import = resp["dvc_import"], resp["git_import"]
97
+ if dest_path is not None:
98
+ typer.echo(f"Importing to destination path: {dest_path}")
99
+ if dvc_import is not None:
100
+ if dest_path is not None and len(dvc_import["outs"]) > 1:
101
+ raise_error(
102
+ "Cannot specify destination path when importing multiple "
103
+ "DVC files"
104
+ )
105
+ # Ensure we have a DVC remote corresponding to this project, and that we
106
+ # have a token set for that remote
107
+ typer.echo("Adding new DVC remote")
108
+ remote = calkit.dvc.add_external_remote(
109
+ owner_name=owner_name, project_name=project_name
110
+ )
111
+ repo.git.add(".dvc/config")
112
+ # Import this data with DVC
113
+ dvc_fpath = ds_dest_path + ".dvc"
114
+ dvc_dir = os.path.dirname(dvc_fpath)
115
+ os.makedirs(dvc_dir, exist_ok=True)
116
+ # Update paths in .dvc file so they are relative to the DVC file
117
+ if len(dvc_import["outs"]) > 1:
118
+ for n, out in enumerate(dvc_import["outs"]):
119
+ dvc_import["outs"][n]["path"] = os.path.relpath(
120
+ out["path"], dvc_dir
121
+ )
122
+ dvc_import["outs"][n]["remote"] = remote["name"]
123
+ else:
124
+ dvc_import["outs"][0]["path"] = os.path.basename(
125
+ dvc_import["outs"][0]["path"]
126
+ )
127
+ dvc_import["outs"][0]["remote"] = remote["name"]
128
+ typer.echo("Saving .dvc file")
129
+ with open(dvc_fpath, "w") as f:
130
+ calkit.ryaml.dump(dvc_import, f)
131
+ repo.git.add(dvc_fpath)
132
+ # Add to .gitignore
133
+ typer.echo("Checking .gitignore")
134
+ if os.path.isfile(".gitignore"):
135
+ with open(".gitignore") as f:
136
+ gitignore = f.read()
137
+ else:
138
+ gitignore = ""
139
+ if ds_dest_path not in gitignore.split("\n"):
140
+ typer.echo(f"Adding {ds_dest_path} to .gitignore")
141
+ gitignore = gitignore.rstrip() + "\n" + ds_dest_path + "\n"
142
+ with open(".gitignore", "w") as f:
143
+ f.write(gitignore)
144
+ repo.git.add(".gitignore")
145
+ elif git_import is not None:
146
+ typer.echo("Fetching files directly since they're kept in Git")
147
+ files = git_import["files"]
148
+ if dest_path is not None:
149
+ os.makedirs(dest_path, exist_ok=True)
150
+ for f in tqdm(files):
151
+ # Fetch content from API
152
+ resp_i = calkit.cloud.get(
153
+ f"/projects/{owner_name}/{project_name}/contents/{f}"
154
+ )
155
+ content = resp_i.get("content")
156
+ fname = os.path.basename(f)
157
+ dirname = os.path.dirname(f) if dest_path is None else dest_path
158
+ os.makedirs(dirname, exist_ok=True)
159
+ out_path = os.path.join(dirname, fname)
160
+ if content is not None:
161
+ # Decode base64 content and save locally
162
+ with open(out_path, "wb") as f:
163
+ f.write(base64.b64decode(content))
164
+ else:
165
+ url = resp_i.get("url")
166
+ if url is None:
167
+ raise_error(f"Could not fetch {f}")
168
+ # Download from URL
169
+ resp_dl = requests.get(url, stream=True)
170
+ try:
171
+ resp_dl.raise_for_status()
172
+ except Exception as e:
173
+ raise_error(f"Failed to download {f} from {url}: {e}")
174
+ with open(out_path, "wb") as f:
175
+ for chunk in resp_dl.iter_content(chunk_size=8192):
176
+ f.write(chunk)
177
+ repo.git.add(out_path)
178
+ else:
179
+ raise_error("Could not fetch import info from Calkit Cloud")
180
+ # Add to datasets in calkit.yaml
181
+ typer.echo("Adding dataset to calkit.yaml")
182
+ new_ds = calkit.models.ImportedDataset(
183
+ path=ds_dest_path,
184
+ title=resp.get("title"),
185
+ description=resp.get("description"),
186
+ stage=None,
187
+ imported_from=calkit.models._ImportedFromProject(
188
+ project=f"{owner_name}/{project_name}",
189
+ path=path,
190
+ git_rev=None, # TODO?
191
+ filter_paths=filter_paths,
192
+ ),
193
+ )
194
+ datasets.append(new_ds.model_dump())
195
+ ck_info["datasets"] = datasets
196
+ with open("calkit.yaml", "w") as f:
197
+ calkit.ryaml.dump(ck_info, f)
198
+ repo.git.add("calkit.yaml")
199
+ if not no_commit:
200
+ # Commit any necessary changes
201
+ typer.echo("Committing changes")
202
+ repo.git.commit(["-m", f"Import dataset {src_path}"])
203
+ if not no_dvc_pull and dvc_import is not None:
204
+ # Run dvc pull
205
+ typer.echo("Running dvc pull")
206
+ subprocess.call(["dvc", "pull", dvc_fpath])
207
+
208
+
209
+ @import_app.command(name="environment")
210
+ def import_environment(
211
+ src_path: Annotated[
212
+ str,
213
+ typer.Argument(
214
+ help=(
215
+ "Environment location and name, e.g., "
216
+ "someone/some-project:env-name. If not present, the Calkit "
217
+ "Cloud will be queried."
218
+ )
219
+ ),
220
+ ],
221
+ dest_path: Annotated[
222
+ str,
223
+ typer.Option("--path", help="Output path at which to save."),
224
+ ] = None,
225
+ dest_name: Annotated[
226
+ str,
227
+ typer.Option(
228
+ "--name", "-n", help="Name to use in the destination project."
229
+ ),
230
+ ] = None,
231
+ overwrite: Annotated[
232
+ bool,
233
+ typer.Option(
234
+ "--overwrite",
235
+ "-f",
236
+ help="Force adding the dataset even if it already exists.",
237
+ ),
238
+ ] = False,
239
+ ) -> None:
240
+ project, env_name = src_path.split(":")
241
+ if os.path.isdir(project):
242
+ cloud = False
243
+ typer.echo("Importing from local project directory")
244
+ else:
245
+ cloud = True
246
+ typer.echo("Importing from Cloud project")
247
+ raise_error("Not yet implemented") # TODO