modsmith 0.1.0__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 (163) hide show
  1. modsmith-0.1.0/.editorconfig +15 -0
  2. modsmith-0.1.0/.gitattributes +4 -0
  3. modsmith-0.1.0/.github/ISSUE_TEMPLATE/bug_report.md +23 -0
  4. modsmith-0.1.0/.github/ISSUE_TEMPLATE/feature_request.md +13 -0
  5. modsmith-0.1.0/.github/dependabot.yml +18 -0
  6. modsmith-0.1.0/.github/pull_request_template.md +7 -0
  7. modsmith-0.1.0/.github/workflows/ci.yml +123 -0
  8. modsmith-0.1.0/.github/workflows/docs.yml +45 -0
  9. modsmith-0.1.0/.github/workflows/live.yml +33 -0
  10. modsmith-0.1.0/.github/workflows/release.yml +64 -0
  11. modsmith-0.1.0/.gitignore +34 -0
  12. modsmith-0.1.0/.pre-commit-config.yaml +22 -0
  13. modsmith-0.1.0/.python-version +1 -0
  14. modsmith-0.1.0/CHANGELOG.md +34 -0
  15. modsmith-0.1.0/CONTRIBUTING.md +117 -0
  16. modsmith-0.1.0/LICENSE +21 -0
  17. modsmith-0.1.0/PKG-INFO +285 -0
  18. modsmith-0.1.0/README.md +269 -0
  19. modsmith-0.1.0/README_ZH.md +269 -0
  20. modsmith-0.1.0/docs/_templates/404.html +19 -0
  21. modsmith-0.1.0/docs/_templates/autosummary/base.rst +7 -0
  22. modsmith-0.1.0/docs/_templates/autosummary/class.rst +6 -0
  23. modsmith-0.1.0/docs/_theme/modsmith/layout.html +104 -0
  24. modsmith-0.1.0/docs/_theme/modsmith/static/chakra-petch-400.woff2 +0 -0
  25. modsmith-0.1.0/docs/_theme/modsmith/static/chakra-petch-600.woff2 +0 -0
  26. modsmith-0.1.0/docs/_theme/modsmith/static/chakra-petch-700.woff2 +0 -0
  27. modsmith-0.1.0/docs/_theme/modsmith/static/chakra-petch-LICENSE.txt +93 -0
  28. modsmith-0.1.0/docs/_theme/modsmith/static/fira-code-LICENSE.txt +93 -0
  29. modsmith-0.1.0/docs/_theme/modsmith/static/fira-code.woff2 +0 -0
  30. modsmith-0.1.0/docs/_theme/modsmith/static/modsmith.css +1972 -0
  31. modsmith-0.1.0/docs/_theme/modsmith/static/modsmith.js +151 -0
  32. modsmith-0.1.0/docs/_theme/modsmith/theme.toml +8 -0
  33. modsmith-0.1.0/docs/assets/banner.svg +12 -0
  34. modsmith-0.1.0/docs/assets/hero-small.svg +12 -0
  35. modsmith-0.1.0/docs/assets/hero.svg +12 -0
  36. modsmith-0.1.0/docs/assets/logo.svg +1 -0
  37. modsmith-0.1.0/docs/assets/pixel/LICENSE.txt +21 -0
  38. modsmith-0.1.0/docs/assets/pixel/alert.svg +3 -0
  39. modsmith-0.1.0/docs/assets/pixel/block.svg +4 -0
  40. modsmith-0.1.0/docs/assets/pixel/bulb.svg +3 -0
  41. modsmith-0.1.0/docs/assets/pixel/check.svg +3 -0
  42. modsmith-0.1.0/docs/assets/pixel/clock.svg +3 -0
  43. modsmith-0.1.0/docs/assets/pixel/cup.svg +3 -0
  44. modsmith-0.1.0/docs/assets/pixel/download.svg +5 -0
  45. modsmith-0.1.0/docs/assets/pixel/flag.svg +4 -0
  46. modsmith-0.1.0/docs/assets/pixel/globe.svg +4 -0
  47. modsmith-0.1.0/docs/assets/pixel/heart.svg +3 -0
  48. modsmith-0.1.0/docs/assets/pixel/info.svg +1 -0
  49. modsmith-0.1.0/docs/assets/pixel/key.svg +1 -0
  50. modsmith-0.1.0/docs/assets/pixel/layers.svg +1 -0
  51. modsmith-0.1.0/docs/assets/pixel/link.svg +3 -0
  52. modsmith-0.1.0/docs/assets/pixel/list.svg +3 -0
  53. modsmith-0.1.0/docs/assets/pixel/package.svg +4 -0
  54. modsmith-0.1.0/docs/assets/pixel/play.svg +3 -0
  55. modsmith-0.1.0/docs/assets/pixel/puzzle.svg +4 -0
  56. modsmith-0.1.0/docs/assets/pixel/question.svg +1 -0
  57. modsmith-0.1.0/docs/assets/pixel/refresh.svg +1 -0
  58. modsmith-0.1.0/docs/assets/pixel/search.svg +3 -0
  59. modsmith-0.1.0/docs/assets/pixel/shield.svg +3 -0
  60. modsmith-0.1.0/docs/assets/pixel/wrench.svg +3 -0
  61. modsmith-0.1.0/docs/concepts/index.md +27 -0
  62. modsmith-0.1.0/docs/concepts/loaders.md +38 -0
  63. modsmith-0.1.0/docs/concepts/platforms.md +37 -0
  64. modsmith-0.1.0/docs/concepts/sync.md +61 -0
  65. modsmith-0.1.0/docs/conf.py +254 -0
  66. modsmith-0.1.0/docs/get-started/concepts.md +50 -0
  67. modsmith-0.1.0/docs/get-started/index.md +27 -0
  68. modsmith-0.1.0/docs/get-started/installation.md +37 -0
  69. modsmith-0.1.0/docs/get-started/quickstart.md +80 -0
  70. modsmith-0.1.0/docs/guides/curseforge.md +60 -0
  71. modsmith-0.1.0/docs/guides/errors.md +84 -0
  72. modsmith-0.1.0/docs/guides/extending.md +99 -0
  73. modsmith-0.1.0/docs/guides/index.md +62 -0
  74. modsmith-0.1.0/docs/guides/instances.md +74 -0
  75. modsmith-0.1.0/docs/guides/java.md +49 -0
  76. modsmith-0.1.0/docs/guides/launcher.md +61 -0
  77. modsmith-0.1.0/docs/guides/loaders.md +76 -0
  78. modsmith-0.1.0/docs/guides/modpacks.md +74 -0
  79. modsmith-0.1.0/docs/guides/platforms.md +103 -0
  80. modsmith-0.1.0/docs/guides/progress.md +72 -0
  81. modsmith-0.1.0/docs/help/changelog.md +2 -0
  82. modsmith-0.1.0/docs/help/compatibility.md +27 -0
  83. modsmith-0.1.0/docs/help/contributing.md +2 -0
  84. modsmith-0.1.0/docs/help/faq.md +53 -0
  85. modsmith-0.1.0/docs/help/index.md +37 -0
  86. modsmith-0.1.0/docs/help/troubleshooting.md +87 -0
  87. modsmith-0.1.0/docs/index.md +176 -0
  88. modsmith-0.1.0/docs/reference/errors.md +7 -0
  89. modsmith-0.1.0/docs/reference/index.md +62 -0
  90. modsmith-0.1.0/docs/reference/instances.md +19 -0
  91. modsmith-0.1.0/docs/reference/java.md +32 -0
  92. modsmith-0.1.0/docs/reference/launcher.md +29 -0
  93. modsmith-0.1.0/docs/reference/loaders.md +57 -0
  94. modsmith-0.1.0/docs/reference/minecraft.md +41 -0
  95. modsmith-0.1.0/docs/reference/net.md +29 -0
  96. modsmith-0.1.0/docs/reference/packs.md +54 -0
  97. modsmith-0.1.0/docs/reference/platforms.md +52 -0
  98. modsmith-0.1.0/docs/reference/progress.md +20 -0
  99. modsmith-0.1.0/modsmith/__init__.py +36 -0
  100. modsmith-0.1.0/modsmith/_support.py +81 -0
  101. modsmith-0.1.0/modsmith/errors.py +115 -0
  102. modsmith-0.1.0/modsmith/instances.py +524 -0
  103. modsmith-0.1.0/modsmith/java.py +294 -0
  104. modsmith-0.1.0/modsmith/launcher.py +256 -0
  105. modsmith-0.1.0/modsmith/loaders/__init__.py +23 -0
  106. modsmith-0.1.0/modsmith/loaders/_base.py +157 -0
  107. modsmith-0.1.0/modsmith/loaders/_fabric.py +166 -0
  108. modsmith-0.1.0/modsmith/loaders/_forge.py +312 -0
  109. modsmith-0.1.0/modsmith/loaders/_install_profile.py +359 -0
  110. modsmith-0.1.0/modsmith/loaders/_processors.py +223 -0
  111. modsmith-0.1.0/modsmith/minecraft/__init__.py +15 -0
  112. modsmith-0.1.0/modsmith/minecraft/_game_dir.py +168 -0
  113. modsmith-0.1.0/modsmith/minecraft/_maven.py +75 -0
  114. modsmith-0.1.0/modsmith/minecraft/_remote.py +115 -0
  115. modsmith-0.1.0/modsmith/net/__init__.py +7 -0
  116. modsmith-0.1.0/modsmith/net/_download.py +243 -0
  117. modsmith-0.1.0/modsmith/net/_resource.py +118 -0
  118. modsmith-0.1.0/modsmith/net/_session.py +241 -0
  119. modsmith-0.1.0/modsmith/packs/__init__.py +18 -0
  120. modsmith-0.1.0/modsmith/packs/_formats.py +262 -0
  121. modsmith-0.1.0/modsmith/packs/_model.py +247 -0
  122. modsmith-0.1.0/modsmith/platforms/__init__.py +25 -0
  123. modsmith-0.1.0/modsmith/platforms/_base.py +312 -0
  124. modsmith-0.1.0/modsmith/platforms/_curseforge.py +390 -0
  125. modsmith-0.1.0/modsmith/platforms/_modrinth.py +261 -0
  126. modsmith-0.1.0/modsmith/progress.py +78 -0
  127. modsmith-0.1.0/modsmith/py.typed +0 -0
  128. modsmith-0.1.0/pyproject.toml +131 -0
  129. modsmith-0.1.0/tests/__init__.py +0 -0
  130. modsmith-0.1.0/tests/conftest.py +55 -0
  131. modsmith-0.1.0/tests/data/install_profiles/forge-1.13.2.json +429 -0
  132. modsmith-0.1.0/tests/data/install_profiles/forge-1.16.5.json +603 -0
  133. modsmith-0.1.0/tests/data/install_profiles/forge-1.20.1.json +728 -0
  134. modsmith-0.1.0/tests/data/install_profiles/forge-1.21.1.json +501 -0
  135. modsmith-0.1.0/tests/data/install_profiles/neoforge-1.20.1.json +827 -0
  136. modsmith-0.1.0/tests/data/install_profiles/neoforge-21.1.json +1140 -0
  137. modsmith-0.1.0/tests/data/processor/Helper.java +9 -0
  138. modsmith-0.1.0/tests/data/processor/Tool.java +54 -0
  139. modsmith-0.1.0/tests/functional/test_docs.py +47 -0
  140. modsmith-0.1.0/tests/functional/test_download.py +274 -0
  141. modsmith-0.1.0/tests/functional/test_instances.py +452 -0
  142. modsmith-0.1.0/tests/functional/test_java.py +120 -0
  143. modsmith-0.1.0/tests/functional/test_loaders.py +376 -0
  144. modsmith-0.1.0/tests/functional/test_minecraft.py +69 -0
  145. modsmith-0.1.0/tests/functional/test_processors.py +157 -0
  146. modsmith-0.1.0/tests/functional/test_session.py +91 -0
  147. modsmith-0.1.0/tests/lib/__init__.py +0 -0
  148. modsmith-0.1.0/tests/lib/builders.py +119 -0
  149. modsmith-0.1.0/tests/lib/docs.py +42 -0
  150. modsmith-0.1.0/tests/lib/server.py +117 -0
  151. modsmith-0.1.0/tests/live/test_curseforge.py +139 -0
  152. modsmith-0.1.0/tests/live/test_docs.py +28 -0
  153. modsmith-0.1.0/tests/live/test_game_files.py +64 -0
  154. modsmith-0.1.0/tests/live/test_modrinth.py +100 -0
  155. modsmith-0.1.0/tests/unit/test_game_dir.py +70 -0
  156. modsmith-0.1.0/tests/unit/test_install_profile.py +79 -0
  157. modsmith-0.1.0/tests/unit/test_launcher.py +127 -0
  158. modsmith-0.1.0/tests/unit/test_loader_registry.py +77 -0
  159. modsmith-0.1.0/tests/unit/test_maven.py +28 -0
  160. modsmith-0.1.0/tests/unit/test_packs.py +187 -0
  161. modsmith-0.1.0/tests/unit/test_public_api.py +46 -0
  162. modsmith-0.1.0/tests/unit/test_support.py +61 -0
  163. modsmith-0.1.0/uv.lock +1090 -0
@@ -0,0 +1,15 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = space
7
+ indent_size = 4
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.{json,toml,yaml,yml}]
12
+ indent_size = 2
13
+
14
+ [*.md]
15
+ trim_trailing_whitespace = false
@@ -0,0 +1,4 @@
1
+ * text=auto eol=lf
2
+ *.jar binary
3
+ *.zip binary
4
+ *.mrpack binary
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: Bug report
3
+ about: Something does not work as documented
4
+ labels: bug
5
+ ---
6
+
7
+ **What happened?**
8
+
9
+ **What did you expect?**
10
+
11
+ **Code to reproduce it**
12
+
13
+ ```python
14
+
15
+ ```
16
+
17
+ **Environment**
18
+
19
+ - Modsmith version:
20
+ - Python version:
21
+ - Operating system:
22
+ - Launcher (standalone or Microsoft Store):
23
+ - Minecraft version and mod loader:
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest something Modsmith should do
4
+ labels: enhancement
5
+ ---
6
+
7
+ **What do you want to do?**
8
+
9
+ **How would you expect the API to look?**
10
+
11
+ ```python
12
+
13
+ ```
@@ -0,0 +1,18 @@
1
+ version: 2
2
+
3
+ updates:
4
+ - package-ecosystem: github-actions
5
+ directory: /
6
+ schedule:
7
+ interval: weekly
8
+ groups:
9
+ actions:
10
+ patterns: ["*"]
11
+
12
+ - package-ecosystem: uv
13
+ directory: /
14
+ schedule:
15
+ interval: weekly
16
+ groups:
17
+ dependencies:
18
+ patterns: ["*"]
@@ -0,0 +1,7 @@
1
+ ## What changed and why
2
+
3
+ ## How it was tested
4
+
5
+ - [ ] `uv run pytest`
6
+ - [ ] `uv run pytest tests/live`, if platform or loader code changed
7
+ - [ ] `CHANGELOG.md` updated, if users will notice this change
@@ -0,0 +1,123 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ workflow_call:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
16
+
17
+ jobs:
18
+ lint:
19
+ name: Lint and type check
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 10
22
+ steps:
23
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
+ with:
25
+ persist-credentials: false
26
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
27
+ - name: Check the lockfile
28
+ run: uv lock --check
29
+ - run: uv sync --locked
30
+ - name: Run pre-commit hooks
31
+ run: uv run --no-sync pre-commit run --all-files --show-diff-on-failure
32
+ - name: Type check
33
+ run: uv run --no-sync pyright
34
+
35
+ test:
36
+ name: Test (${{ matrix.os }}, Python ${{ matrix.python }})
37
+ runs-on: ${{ matrix.os }}
38
+ timeout-minutes: 20
39
+ strategy:
40
+ fail-fast: false
41
+ matrix:
42
+ os: [ubuntu-latest, windows-latest, macos-latest]
43
+ python: ["3.12", "3.13", "3.14"]
44
+ steps:
45
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
46
+ with:
47
+ persist-credentials: false
48
+ - uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
49
+ with:
50
+ distribution: temurin
51
+ java-version: "21"
52
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
53
+ with:
54
+ python-version: ${{ matrix.python }}
55
+ - run: uv sync --locked --no-default-groups --group test
56
+ - name: Run tests
57
+ run: uv run --no-sync pytest --cov
58
+ - name: Summarize coverage
59
+ shell: bash
60
+ run: uv run --no-sync coverage report --format=markdown >> "$GITHUB_STEP_SUMMARY"
61
+
62
+ minimum-dependencies:
63
+ name: Test (lowest dependencies)
64
+ runs-on: ubuntu-latest
65
+ timeout-minutes: 20
66
+ steps:
67
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
68
+ with:
69
+ persist-credentials: false
70
+ - uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
71
+ with:
72
+ distribution: temurin
73
+ java-version: "21"
74
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
75
+ - name: Run tests
76
+ run: uv run --isolated --resolution lowest-direct --group test pytest
77
+
78
+ docs:
79
+ name: Build documentation
80
+ runs-on: ubuntu-latest
81
+ timeout-minutes: 10
82
+ steps:
83
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
84
+ with:
85
+ persist-credentials: false
86
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
87
+ - run: uv sync --locked --no-default-groups --group docs
88
+ - name: Build the site
89
+ run: uv run --no-sync sphinx-build -W -n -b dirhtml docs docs/_build/html
90
+ - name: Run the examples
91
+ run: uv run --no-sync sphinx-build -W -b doctest docs docs/_build/doctest
92
+
93
+ build:
94
+ name: Build distributions
95
+ runs-on: ubuntu-latest
96
+ timeout-minutes: 10
97
+ steps:
98
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
99
+ with:
100
+ persist-credentials: false
101
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
102
+ - run: uv build
103
+ - name: Check package metadata
104
+ run: uvx twine check --strict dist/*
105
+ - name: Import the built wheel
106
+ run: uv run --isolated --no-project --with dist/*.whl python -c "import modsmith; print(modsmith.__version__)"
107
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
108
+ with:
109
+ name: dist
110
+ path: dist/
111
+ if-no-files-found: error
112
+
113
+ all-checks:
114
+ name: All checks
115
+ if: always()
116
+ needs: [lint, test, minimum-dependencies, docs, build]
117
+ runs-on: ubuntu-latest
118
+ timeout-minutes: 5
119
+ steps:
120
+ - name: Require every job to pass
121
+ env:
122
+ PASSED: ${{ !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') && !contains(needs.*.result, 'skipped') }}
123
+ run: test "$PASSED" = "true"
@@ -0,0 +1,45 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: pages
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ build:
17
+ name: Build the site
18
+ runs-on: ubuntu-latest
19
+ timeout-minutes: 10
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ with:
23
+ persist-credentials: false
24
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
25
+ - run: uv sync --locked --no-default-groups --group docs
26
+ - name: Build the site
27
+ run: uv run --no-sync sphinx-build -W -n -b dirhtml docs docs/_build/html
28
+ - uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
29
+ with:
30
+ path: docs/_build/html
31
+
32
+ deploy:
33
+ name: Deploy to GitHub Pages
34
+ needs: build
35
+ runs-on: ubuntu-latest
36
+ timeout-minutes: 10
37
+ permissions:
38
+ pages: write
39
+ id-token: write
40
+ environment:
41
+ name: github-pages
42
+ url: ${{ steps.deployment.outputs.page_url }}
43
+ steps:
44
+ - id: deployment
45
+ uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
@@ -0,0 +1,33 @@
1
+ name: Live tests
2
+
3
+ on:
4
+ schedule:
5
+ - cron: "17 3 * * 1"
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: ${{ github.workflow }}
13
+ cancel-in-progress: false
14
+
15
+ jobs:
16
+ live:
17
+ name: Live (${{ matrix.os }})
18
+ runs-on: ${{ matrix.os }}
19
+ timeout-minutes: 60
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ os: [ubuntu-latest, windows-latest, macos-latest]
24
+ steps:
25
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
26
+ with:
27
+ persist-credentials: false
28
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
29
+ - run: uv sync --locked --no-default-groups --group test
30
+ - name: Run live tests
31
+ env:
32
+ CURSEFORGE_API_KEY: ${{ secrets.CURSEFORGE_API_KEY }}
33
+ run: uv run --no-sync pytest tests/live
@@ -0,0 +1,64 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ check-version:
12
+ name: Check the tag
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 5
15
+ steps:
16
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17
+ with:
18
+ persist-credentials: false
19
+ - uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
20
+ - name: Compare the tag with the project version
21
+ env:
22
+ TAG: ${{ github.ref_name }}
23
+ run: test "v$(uv version --short)" = "$TAG"
24
+
25
+ ci:
26
+ name: CI
27
+ needs: check-version
28
+ uses: ./.github/workflows/ci.yml
29
+
30
+ pypi:
31
+ name: Publish to PyPI
32
+ needs: ci
33
+ runs-on: ubuntu-latest
34
+ timeout-minutes: 10
35
+ environment:
36
+ name: pypi
37
+ url: https://pypi.org/project/modsmith/
38
+ permissions:
39
+ id-token: write
40
+ steps:
41
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
42
+ with:
43
+ name: dist
44
+ path: dist/
45
+ - uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
46
+
47
+ github-release:
48
+ name: Create the GitHub release
49
+ needs: pypi
50
+ runs-on: ubuntu-latest
51
+ timeout-minutes: 5
52
+ permissions:
53
+ contents: write
54
+ steps:
55
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
56
+ with:
57
+ name: dist
58
+ path: dist/
59
+ - name: Create the release
60
+ env:
61
+ GH_TOKEN: ${{ github.token }}
62
+ GH_REPO: ${{ github.repository }}
63
+ TAG: ${{ github.ref_name }}
64
+ run: gh release create "$TAG" dist/* --verify-tag --generate-notes
@@ -0,0 +1,34 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ wheels/
8
+
9
+ # Environments
10
+ .venv/
11
+ .env
12
+
13
+ # Tool caches
14
+ .cache/
15
+ .coverage
16
+ .coverage.*
17
+ .pyright/
18
+ .pytest_cache/
19
+ .ruff_cache/
20
+ htmlcov/
21
+
22
+ # Editors and systems
23
+ .idea/
24
+ .vscode/
25
+ .DS_Store
26
+ Thumbs.db
27
+
28
+ # Local game files and logs
29
+ *.log
30
+ .minecraft/
31
+
32
+ # Documentation
33
+ docs/_build/
34
+ docs/reference/*/
@@ -0,0 +1,22 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: check-merge-conflict
6
+ - id: check-toml
7
+ - id: check-yaml
8
+ - id: end-of-file-fixer
9
+ - id: trailing-whitespace
10
+
11
+ - repo: local
12
+ hooks:
13
+ - id: ruff-check
14
+ name: ruff check
15
+ entry: uv run --no-sync ruff check --fix --force-exclude
16
+ language: system
17
+ types_or: [python, pyi]
18
+ - id: ruff-format
19
+ name: ruff format
20
+ entry: uv run --no-sync ruff format --force-exclude
21
+ language: system
22
+ types_or: [python, pyi]
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file. The format is
4
+ based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
5
+ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-11-03
10
+
11
+ ### Added
12
+
13
+ - `modsmith.platforms`: search and fetch from Modrinth and CurseForge.
14
+ - `modsmith.packs`: read mrpack and CurseForge modpacks without network access.
15
+ - `modsmith.loaders`: install Forge, NeoForge, Fabric and Quilt.
16
+ - `modsmith.instances`: `Instance.diff()` and `Instance.sync()` for installing
17
+ and updating game directories while keeping user changes.
18
+ - `modsmith.minecraft`, `modsmith.java`, `modsmith.launcher` and `modsmith.net`.
19
+
20
+ - `Instance.sync` stages new files and rolls back if it cannot finish, so a
21
+ failed update leaves the instance as it was.
22
+ - `Platform.iter_releases` reads releases page by page, so finding the latest
23
+ one takes a single request.
24
+ - Modpack overrides are streamed, so large packs no longer load into memory.
25
+ - `Instance` remembers file hashes, so a sync with nothing to do is faster.
26
+ - `Loader.is_installed` works offline for the built-in loaders.
27
+ - Download progress counts skipped and resumed files, and reaches the total.
28
+ - Forge and NeoForge installs prefer newer Java runtimes, which fixes old
29
+ versions on Windows and Apple Silicon.
30
+ - Requests respect `Retry-After`, and downloads use `If-Range` to resume.
31
+
32
+ ### Changed
33
+
34
+ - The project was renamed from CurseCraft and rebuilt as a developer toolkit.
@@ -0,0 +1,117 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ You need [uv](https://docs.astral.sh/uv/) and a JDK, because the functional
6
+ tests compile and run a small processor jar.
7
+
8
+ ```bash
9
+ uv sync
10
+ ```
11
+
12
+ ```bash
13
+ uv run pre-commit install
14
+ ```
15
+
16
+ ## Checks
17
+
18
+ Run these before you open a pull request:
19
+
20
+ ```bash
21
+ uv run ruff format .
22
+ ```
23
+
24
+ ```bash
25
+ uv run ruff check .
26
+ ```
27
+
28
+ ```bash
29
+ uv run pyright
30
+ ```
31
+
32
+ ```bash
33
+ uv run pytest --cov
34
+ ```
35
+
36
+ ## Testing
37
+
38
+ | Layer | Contains | Runs |
39
+ | :--- | :--- | :--- |
40
+ | `tests/unit` | Pure logic and real local files | By default |
41
+ | `tests/functional` | A real local HTTP server and a real JVM; the internet is blocked | By default |
42
+ | `tests/live` | Real platforms and complete loader installs | On request |
43
+
44
+ Run the live tests with:
45
+
46
+ ```bash
47
+ uv run pytest tests/live
48
+ ```
49
+
50
+ CurseForge tests need `CURSEFORGE_API_KEY` and are skipped without it.
51
+
52
+ Tests do not use mocks. Do not use `unittest.mock`, patch internal functions or
53
+ fake a process or an HTTP client. Setting environment variables with
54
+ `monkeypatch` is allowed, because that configures the environment. If code is
55
+ hard to test this way, give it a parameter, such as a URL, instead.
56
+
57
+ Platform behaviour is tested only in `tests/live`, against the real services.
58
+
59
+ ### Known gaps
60
+
61
+ - `replace_file` falls back to copying when a rename fails with `EXDEV`. The
62
+ cross-filesystem test only runs when the working directory and the temp
63
+ directory are on different drives. The MSIX behaviour that needed the
64
+ fallback cannot be reproduced in a normal environment.
65
+ - `is_running()` is checked against the real process table, but no test starts
66
+ the official launcher, and the Microsoft Store launcher's process name is
67
+ unconfirmed.
68
+ - No test starts the game.
69
+
70
+ ## Docstrings
71
+
72
+ Write Google-style docstrings, in English, for every module, class and function.
73
+ Ruff checks that they exist, so also check that they match what the code does.
74
+
75
+ - Describe behaviour. Type annotations already give the types.
76
+ - Add `Args`, `Returns` and `Raises` when a caller needs them.
77
+ - Use single backticks for modsmith objects, which become links in the
78
+ documentation, and double backticks for parameters and literal values.
79
+ - Use a code comment only to explain why something is done.
80
+
81
+ ## Documentation
82
+
83
+ The site is built with Sphinx and MyST, and the API reference comes from the
84
+ docstrings. Warnings and broken references fail the build:
85
+
86
+ ```bash
87
+ uv run sphinx-build -W -n -b dirhtml docs docs/_build/html
88
+ ```
89
+
90
+ Examples in docstrings run as tests:
91
+
92
+ ```bash
93
+ uv run sphinx-build -W -b doctest docs docs/_build/doctest
94
+ ```
95
+
96
+ ## Continuous integration
97
+
98
+ | Workflow | Runs | Does |
99
+ | :--- | :--- | :--- |
100
+ | `ci.yml` | Pull requests and pushes to `main` | Lint, type checks, tests on every OS and Python version, lowest dependencies, documentation, package build |
101
+ | `live.yml` | Every Monday, or by hand | Runs `tests/live` on every OS |
102
+ | `release.yml` | `v*` tags | Runs CI, publishes to PyPI and creates a GitHub release |
103
+
104
+ `ci.yml` ends with an `All checks` job, which is the one to require in branch
105
+ protection. `live.yml` reads `CURSEFORGE_API_KEY` from the repository secrets.
106
+
107
+ ## Releasing
108
+
109
+ 1. Set `version` in `pyproject.toml` and move the `Unreleased` notes in
110
+ `CHANGELOG.md` under the new version.
111
+ 2. Merge that change into `main`.
112
+ 3. Push a tag such as `v0.1.0`. The tag must match the project version.
113
+
114
+ ## Commits
115
+
116
+ Keep the change focused, write the subject in the imperative mood, and add a
117
+ line to `CHANGELOG.md` under `Unreleased` when users will notice the change.
modsmith-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MeNeither
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.