craft-application 4.2.6__tar.gz → 4.2.7__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 (194) hide show
  1. {craft_application-4.2.6/craft_application.egg-info → craft_application-4.2.7}/PKG-INFO +2 -2
  2. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/_version.py +2 -2
  3. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/application.py +1 -0
  4. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/lifecycle.py +1 -88
  5. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/__init__.py +2 -0
  6. craft_application-4.2.7/craft_application/util/system.py +105 -0
  7. {craft_application-4.2.6 → craft_application-4.2.7/craft_application.egg-info}/PKG-INFO +2 -2
  8. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application.egg-info/SOURCES.txt +2 -0
  9. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application.egg-info/requires.txt +1 -1
  10. {craft_application-4.2.6 → craft_application-4.2.7}/docs/reference/changelog.rst +14 -0
  11. {craft_application-4.2.6 → craft_application-4.2.7}/pyproject.toml +2 -2
  12. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/environment/testcraft.yaml +3 -2
  13. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/test_application.py +5 -0
  14. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_lifecycle.py +1 -155
  15. craft_application-4.2.7/tests/unit/util/test_system.py +174 -0
  16. {craft_application-4.2.6 → craft_application-4.2.7}/.editorconfig +0 -0
  17. {craft_application-4.2.6 → craft_application-4.2.7}/.github/.jira_sync_config.yaml +0 -0
  18. {craft_application-4.2.6 → craft_application-4.2.7}/.github/ISSUE_TEMPLATE/bug.yaml +0 -0
  19. {craft_application-4.2.6 → craft_application-4.2.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  20. {craft_application-4.2.6 → craft_application-4.2.7}/.github/ISSUE_TEMPLATE/task.yaml +0 -0
  21. {craft_application-4.2.6 → craft_application-4.2.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  22. {craft_application-4.2.6 → craft_application-4.2.7}/.github/release-drafter.yaml +0 -0
  23. {craft_application-4.2.6 → craft_application-4.2.7}/.github/release-drafter.yml +0 -0
  24. {craft_application-4.2.6 → craft_application-4.2.7}/.github/renovate.json5 +0 -0
  25. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/check-renovate.yaml +0 -0
  26. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/cla-check.yaml +0 -0
  27. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/docs.yaml +0 -0
  28. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/release-drafter.yaml +0 -0
  29. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/release-publish.yaml +0 -0
  30. {craft_application-4.2.6 → craft_application-4.2.7}/.github/workflows/tests.yaml +0 -0
  31. {craft_application-4.2.6 → craft_application-4.2.7}/.gitignore +0 -0
  32. {craft_application-4.2.6 → craft_application-4.2.7}/.pre-commit-config.yaml +0 -0
  33. {craft_application-4.2.6 → craft_application-4.2.7}/.readthedocs.yaml +0 -0
  34. {craft_application-4.2.6 → craft_application-4.2.7}/.yamllint.yaml +0 -0
  35. {craft_application-4.2.6 → craft_application-4.2.7}/HACKING.rst +0 -0
  36. {craft_application-4.2.6 → craft_application-4.2.7}/LICENSE +0 -0
  37. {craft_application-4.2.6 → craft_application-4.2.7}/README.rst +0 -0
  38. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/__init__.py +0 -0
  39. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/_config.py +0 -0
  40. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/commands/__init__.py +0 -0
  41. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/commands/base.py +0 -0
  42. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/commands/lifecycle.py +0 -0
  43. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/commands/other.py +0 -0
  44. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/errors.py +0 -0
  45. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/git/__init__.py +0 -0
  46. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/git/_errors.py +0 -0
  47. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/git/_git_repo.py +0 -0
  48. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/git/_models.py +0 -0
  49. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/grammar.py +0 -0
  50. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/__init__.py +0 -0
  51. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/errors.py +0 -0
  52. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/launchpad.py +0 -0
  53. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/__init__.py +0 -0
  54. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/base.py +0 -0
  55. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/build.py +0 -0
  56. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/code.py +0 -0
  57. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/distro.py +0 -0
  58. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/project.py +0 -0
  59. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/models/recipe.py +0 -0
  60. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/launchpad/util.py +0 -0
  61. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/misc/instance_bashrc +0 -0
  62. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/__init__.py +0 -0
  63. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/base.py +0 -0
  64. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/constraints.py +0 -0
  65. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/grammar.py +0 -0
  66. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/metadata.py +0 -0
  67. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/models/project.py +0 -0
  68. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/py.typed +0 -0
  69. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/remote/__init__.py +0 -0
  70. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/remote/errors.py +0 -0
  71. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/remote/git.py +0 -0
  72. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/remote/utils.py +0 -0
  73. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/remote/worktree.py +0 -0
  74. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/secrets.py +0 -0
  75. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/__init__.py +0 -0
  76. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/base.py +0 -0
  77. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/config.py +0 -0
  78. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/package.py +0 -0
  79. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/provider.py +0 -0
  80. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/remotebuild.py +0 -0
  81. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/request.py +0 -0
  82. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/services/service_factory.py +0 -0
  83. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/callbacks.py +0 -0
  84. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/docs.py +0 -0
  85. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/error_formatting.py +0 -0
  86. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/logging.py +0 -0
  87. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/paths.py +0 -0
  88. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/platforms.py +0 -0
  89. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/repositories.py +0 -0
  90. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/retry.py +0 -0
  91. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/snap_config.py +0 -0
  92. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/string.py +0 -0
  93. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application/util/yaml.py +0 -0
  94. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application.egg-info/dependency_links.txt +0 -0
  95. {craft_application-4.2.6 → craft_application-4.2.7}/craft_application.egg-info/top_level.txt +0 -0
  96. {craft_application-4.2.6 → craft_application-4.2.7}/docs/conf.py +0 -0
  97. {craft_application-4.2.6 → craft_application-4.2.7}/docs/explanation/build-plans.rst +0 -0
  98. {craft_application-4.2.6 → craft_application-4.2.7}/docs/explanation/index.rst +0 -0
  99. {craft_application-4.2.6 → craft_application-4.2.7}/docs/howto/index.rst +0 -0
  100. {craft_application-4.2.6 → craft_application-4.2.7}/docs/howto/partitions.rst +0 -0
  101. {craft_application-4.2.6 → craft_application-4.2.7}/docs/index.rst +0 -0
  102. {craft_application-4.2.6 → craft_application-4.2.7}/docs/reference/environment-variables.rst +0 -0
  103. {craft_application-4.2.6 → craft_application-4.2.7}/docs/reference/index.rst +0 -0
  104. {craft_application-4.2.6 → craft_application-4.2.7}/docs/reference/platforms.rst +0 -0
  105. {craft_application-4.2.6 → craft_application-4.2.7}/docs/tutorials/index.rst +0 -0
  106. {craft_application-4.2.6 → craft_application-4.2.7}/setup.cfg +0 -0
  107. {craft_application-4.2.6 → craft_application-4.2.7}/tests/__init__.py +0 -0
  108. {craft_application-4.2.6 → craft_application-4.2.7}/tests/conftest.py +0 -0
  109. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/__init__.py +0 -0
  110. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/conftest.py +0 -0
  111. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/build-secrets/secret-source-folder/source-file.txt +0 -0
  112. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/build-secrets/testcraft.yaml +0 -0
  113. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/invalid_projects/build-error/testcraft.yaml +0 -0
  114. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/adoption/stderr +0 -0
  115. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/adoption/testcraft.yaml +0 -0
  116. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/basic/stderr +0 -0
  117. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/basic/testcraft.yaml +0 -0
  118. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/build-for-all/stderr +0 -0
  119. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/build-for-all/testcraft.yaml +0 -0
  120. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/environment/stderr +0 -0
  121. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/grammar/src/on-amd64-to-amd64/hello.txt +0 -0
  122. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/grammar/src/on-amd64-to-arm64/hello.txt +0 -0
  123. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/grammar/stderr +0 -0
  124. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/data/valid_projects/grammar/testcraft.yaml +0 -0
  125. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/launchpad/__init__.py +0 -0
  126. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/launchpad/conftest.py +0 -0
  127. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/launchpad/test_anonymous_access.py +0 -0
  128. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/__init__.py +0 -0
  129. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/test_lifecycle.py +0 -0
  130. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/test_provider.py +0 -0
  131. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/test_remotebuild.py +0 -0
  132. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/test_request.py +0 -0
  133. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/services/test_service_factory.py +0 -0
  134. {craft_application-4.2.6 → craft_application-4.2.7}/tests/integration/test_version.py +0 -0
  135. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/__init__.py +0 -0
  136. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/commands/__init__.py +0 -0
  137. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/commands/test_base.py +0 -0
  138. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/commands/test_lifecycle.py +0 -0
  139. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/commands/test_other.py +0 -0
  140. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/conftest.py +0 -0
  141. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/git/__init__.py +0 -0
  142. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/git/test_errors.py +0 -0
  143. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/git/test_git.py +0 -0
  144. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/__init__.py +0 -0
  145. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/conftest.py +0 -0
  146. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/models/__init__.py +0 -0
  147. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/models/test_base.py +0 -0
  148. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/models/test_code.py +0 -0
  149. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/test_launchpad.py +0 -0
  150. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/launchpad/test_util.py +0 -0
  151. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/__init__.py +0 -0
  152. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/project_models/basic_project.yaml +0 -0
  153. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/project_models/full_project.yaml +0 -0
  154. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/project_models/invalid_project.yaml +0 -0
  155. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/test_base.py +0 -0
  156. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/test_constraints.py +0 -0
  157. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/test_grammar.py +0 -0
  158. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/models/test_project.py +0 -0
  159. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/__init__.py +0 -0
  160. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/conftest.py +0 -0
  161. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/test_errors.py +0 -0
  162. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/test_git.py +0 -0
  163. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/test_utils.py +0 -0
  164. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/remote/test_worktree.py +0 -0
  165. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/__init__.py +0 -0
  166. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/conftest.py +0 -0
  167. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_config.py +0 -0
  168. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_package.py +0 -0
  169. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_provider.py +0 -0
  170. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_remotebuild.py +0 -0
  171. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_repositories.py +0 -0
  172. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_request.py +0 -0
  173. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/services/test_service_factory.py +0 -0
  174. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/test_application.py +0 -0
  175. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/test_errors.py +0 -0
  176. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/test_grammar.py +0 -0
  177. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/test_nothing.py +0 -0
  178. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/test_secrets.py +0 -0
  179. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/__init__.py +0 -0
  180. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/invalid_yaml/_README +0 -0
  181. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/invalid_yaml/duplicate_second_level.yaml-invalid +0 -0
  182. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/invalid_yaml/duplicate_top_level.yaml-invalid +0 -0
  183. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/invalid_yaml/unhashable.yaml-invalid +0 -0
  184. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_docs.py +0 -0
  185. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_error_formatting.py +0 -0
  186. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_logging.py +0 -0
  187. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_paths.py +0 -0
  188. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_platforms.py +0 -0
  189. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_retry.py +0 -0
  190. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_snap_config.py +0 -0
  191. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_string.py +0 -0
  192. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/test_yaml.py +0 -0
  193. {craft_application-4.2.6 → craft_application-4.2.7}/tests/unit/util/valid_yaml/empty.yaml +0 -0
  194. {craft_application-4.2.6 → craft_application-4.2.7}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: craft-application
3
- Version: 4.2.6
3
+ Version: 4.2.7
4
4
  Summary: A framework for *craft applications.
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -26,7 +26,7 @@ Requires-Dist: pydantic~=2.0
26
26
  Requires-Dist: license-expression>=30.0.0
27
27
  Requires-Dist: pygit2<1.15.0,>=1.13.0
28
28
  Requires-Dist: PyYaml>=6.0
29
- Requires-Dist: requests~=2.32
29
+ Requires-Dist: requests
30
30
  Requires-Dist: typing_extensions>=4.4.0
31
31
  Provides-Extra: remote
32
32
  Requires-Dist: launchpadlib>=1.10.16; extra == "remote"
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '4.2.6'
16
- __version_tuple__ = version_tuple = (4, 2, 6)
15
+ __version__ = version = '4.2.7'
16
+ __version_tuple__ = version_tuple = (4, 2, 7)
@@ -682,6 +682,7 @@ class Application:
682
682
  application_name=self.app.name, # not used in environment expansion
683
683
  cache_dir=pathlib.Path(), # not used in environment expansion
684
684
  arch=build_for_arch,
685
+ parallel_build_count=util.get_parallel_build_count(self.app.name),
685
686
  project_name=yaml_data.get("name", ""),
686
687
  project_dirs=project_dirs,
687
688
  project_vars=environment_vars,
@@ -17,7 +17,6 @@
17
17
  from __future__ import annotations
18
18
 
19
19
  import contextlib
20
- import os
21
20
  import types
22
21
  from typing import TYPE_CHECKING, Any
23
22
 
@@ -200,7 +199,7 @@ class LifecycleService(base.ProjectService):
200
199
  cache_dir=self._cache_dir,
201
200
  work_dir=self._work_dir,
202
201
  ignore_local_sources=self._app.source_ignore_patterns,
203
- parallel_build_count=self._get_parallel_build_count(),
202
+ parallel_build_count=util.get_parallel_build_count(self._app.name),
204
203
  project_vars_part_name=self._project.adopt_info,
205
204
  project_vars=self._project_vars,
206
205
  track_stage_packages=True,
@@ -324,92 +323,6 @@ class LifecycleService(base.ProjectService):
324
323
  f"{work_dir=}, {cache_dir=}, {plan=}, **{self._manager_kwargs!r})"
325
324
  )
326
325
 
327
- def _verify_parallel_build_count(
328
- self, env_name: str, parallel_build_count: int | str
329
- ) -> int:
330
- """Verify the parallel build count is valid.
331
-
332
- :param env_name: The name of the environment variable being checked.
333
- :param parallel_build_count: The value of the variable.
334
- :return: The parallel build count as an integer.
335
- """
336
- try:
337
- parallel_build_count = int(parallel_build_count)
338
- except ValueError as err:
339
- raise errors.InvalidParameterError(
340
- env_name, str(os.environ[env_name])
341
- ) from err
342
-
343
- # Ensure the value is valid positive integer
344
- if parallel_build_count < 1:
345
- raise errors.InvalidParameterError(env_name, str(parallel_build_count))
346
-
347
- return parallel_build_count
348
-
349
- def _get_parallel_build_count(self) -> int:
350
- """Get the number of parallel builds to run.
351
-
352
- The parallel build count is determined by the first available of the
353
- following environment variables in the order:
354
-
355
- - <APP_NAME>_PARALLEL_BUILD_COUNT
356
- - CRAFT_PARALLEL_BUILD_COUNT
357
- - <APP_NAME>_MAX_PARALLEL_BUILD_COUNT
358
- - CRAFT_MAX_PARALLEL_BUILD_COUNT
359
-
360
- where the MAX_PARALLEL_BUILD_COUNT variables are dynamically compared to
361
- the number of CPUs, and the smaller of the two is used.
362
-
363
- If no environment variable is set, the CPU count is used.
364
- If the CPU count is not available for some reason, 1 is used as a fallback.
365
- """
366
- parallel_build_count = None
367
-
368
- # fixed parallel build count environment variable
369
- for env_name in [
370
- (self._app.name + "_PARALLEL_BUILD_COUNT").upper(),
371
- "CRAFT_PARALLEL_BUILD_COUNT",
372
- ]:
373
- if os.environ.get(env_name):
374
- parallel_build_count = self._verify_parallel_build_count(
375
- env_name, os.environ[env_name]
376
- )
377
- emit.debug(
378
- f"Using parallel build count of {parallel_build_count} "
379
- f"from environment variable {env_name!r}"
380
- )
381
- break
382
-
383
- # CPU count related max parallel build count environment variable
384
- if parallel_build_count is None:
385
- cpu_count = os.cpu_count() or 1
386
- for env_name in [
387
- (self._app.name + "_MAX_PARALLEL_BUILD_COUNT").upper(),
388
- "CRAFT_MAX_PARALLEL_BUILD_COUNT",
389
- ]:
390
- if os.environ.get(env_name):
391
- parallel_build_count = min(
392
- cpu_count,
393
- self._verify_parallel_build_count(
394
- env_name, os.environ[env_name]
395
- ),
396
- )
397
- emit.debug(
398
- f"Using parallel build count of {parallel_build_count} "
399
- f"from environment variable {env_name!r}"
400
- )
401
- break
402
-
403
- # Default to CPU count if no max environment variable is set
404
- if parallel_build_count is None:
405
- parallel_build_count = cpu_count
406
- emit.debug(
407
- f"Using parallel build count of {parallel_build_count} "
408
- "from CPU count"
409
- )
410
-
411
- return parallel_build_count
412
-
413
326
  def _get_local_keys_path(self) -> Path | None:
414
327
  """Return a directory with public keys for package-repositories.
415
328
 
@@ -32,6 +32,7 @@ from craft_application.util.snap_config import (
32
32
  is_running_from_snap,
33
33
  )
34
34
  from craft_application.util.string import humanize_list, strtobool
35
+ from craft_application.util.system import get_parallel_build_count
35
36
  from craft_application.util.yaml import dump_yaml, safe_yaml_load
36
37
 
37
38
  __all__ = [
@@ -52,4 +53,5 @@ __all__ = [
52
53
  "dump_yaml",
53
54
  "safe_yaml_load",
54
55
  "retry",
56
+ "get_parallel_build_count",
55
57
  ]
@@ -0,0 +1,105 @@
1
+ # This file is part of craft-application.
2
+ #
3
+ # Copyright 2024 Canonical Ltd.
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License version 3, as
7
+ # published by the Free Software Foundation.
8
+ #
9
+ # This program is distributed in the hope that it will be useful, but WITHOUT
10
+ # ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
11
+ # SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
12
+ # See the GNU Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public License along
15
+ # with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ """System-level util functions."""
17
+ from __future__ import annotations
18
+
19
+ import os
20
+
21
+ from craft_cli import emit
22
+
23
+ from craft_application.errors import InvalidParameterError
24
+
25
+
26
+ def _verify_parallel_build_count(env_name: str, parallel_build_count: int | str) -> int:
27
+ """Verify the parallel build count is valid.
28
+
29
+ :param env_name: The name of the environment variable being checked.
30
+ :param parallel_build_count: The value of the variable.
31
+ :return: The parallel build count as an integer.
32
+ """
33
+ try:
34
+ parallel_build_count = int(parallel_build_count)
35
+ except ValueError as err:
36
+ raise InvalidParameterError(env_name, str(os.environ[env_name])) from err
37
+
38
+ # Ensure the value is valid positive integer
39
+ if parallel_build_count < 1:
40
+ raise InvalidParameterError(env_name, str(parallel_build_count))
41
+
42
+ return parallel_build_count
43
+
44
+
45
+ def get_parallel_build_count(app_name: str) -> int:
46
+ """Get the number of parallel builds to run.
47
+
48
+ The parallel build count is determined by the first available of the
49
+ following environment variables in the order:
50
+
51
+ - <APP_NAME>_PARALLEL_BUILD_COUNT
52
+ - CRAFT_PARALLEL_BUILD_COUNT
53
+ - <APP_NAME>_MAX_PARALLEL_BUILD_COUNT
54
+ - CRAFT_MAX_PARALLEL_BUILD_COUNT
55
+
56
+ where the MAX_PARALLEL_BUILD_COUNT variables are dynamically compared to
57
+ the number of CPUs, and the smaller of the two is used.
58
+
59
+ If no environment variable is set, the CPU count is used.
60
+ If the CPU count is not available for some reason, 1 is used as a fallback.
61
+ """
62
+ parallel_build_count = None
63
+
64
+ # fixed parallel build count environment variable
65
+ for env_name in [
66
+ (app_name + "_PARALLEL_BUILD_COUNT").upper(),
67
+ "CRAFT_PARALLEL_BUILD_COUNT",
68
+ ]:
69
+ if os.environ.get(env_name):
70
+ parallel_build_count = _verify_parallel_build_count(
71
+ env_name, os.environ[env_name]
72
+ )
73
+ emit.debug(
74
+ f"Using parallel build count of {parallel_build_count} "
75
+ f"from environment variable {env_name!r}"
76
+ )
77
+ break
78
+
79
+ # CPU count related max parallel build count environment variable
80
+ if parallel_build_count is None:
81
+ cpu_count = os.cpu_count() or 1
82
+ for env_name in [
83
+ (app_name + "_MAX_PARALLEL_BUILD_COUNT").upper(),
84
+ "CRAFT_MAX_PARALLEL_BUILD_COUNT",
85
+ ]:
86
+ if os.environ.get(env_name):
87
+ parallel_build_count = min(
88
+ cpu_count,
89
+ _verify_parallel_build_count(env_name, os.environ[env_name]),
90
+ )
91
+ emit.debug(
92
+ f"Using parallel build count of {parallel_build_count} "
93
+ f"from environment variable {env_name!r}"
94
+ )
95
+ break
96
+
97
+ # Default to CPU count if no max environment variable is set
98
+ if parallel_build_count is None:
99
+ parallel_build_count = cpu_count
100
+ emit.debug(
101
+ f"Using parallel build count of {parallel_build_count} "
102
+ "from CPU count"
103
+ )
104
+
105
+ return parallel_build_count
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: craft-application
3
- Version: 4.2.6
3
+ Version: 4.2.7
4
4
  Summary: A framework for *craft applications.
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -26,7 +26,7 @@ Requires-Dist: pydantic~=2.0
26
26
  Requires-Dist: license-expression>=30.0.0
27
27
  Requires-Dist: pygit2<1.15.0,>=1.13.0
28
28
  Requires-Dist: PyYaml>=6.0
29
- Requires-Dist: requests~=2.32
29
+ Requires-Dist: requests
30
30
  Requires-Dist: typing_extensions>=4.4.0
31
31
  Provides-Extra: remote
32
32
  Requires-Dist: launchpadlib>=1.10.16; extra == "remote"
@@ -86,6 +86,7 @@ craft_application/util/repositories.py
86
86
  craft_application/util/retry.py
87
87
  craft_application/util/snap_config.py
88
88
  craft_application/util/string.py
89
+ craft_application/util/system.py
89
90
  craft_application/util/yaml.py
90
91
  docs/conf.py
91
92
  docs/index.rst
@@ -182,6 +183,7 @@ tests/unit/util/test_platforms.py
182
183
  tests/unit/util/test_retry.py
183
184
  tests/unit/util/test_snap_config.py
184
185
  tests/unit/util/test_string.py
186
+ tests/unit/util/test_system.py
185
187
  tests/unit/util/test_yaml.py
186
188
  tests/unit/util/invalid_yaml/_README
187
189
  tests/unit/util/invalid_yaml/duplicate_second_level.yaml-invalid
@@ -9,7 +9,7 @@ pydantic~=2.0
9
9
  license-expression>=30.0.0
10
10
  pygit2<1.15.0,>=1.13.0
11
11
  PyYaml>=6.0
12
- requests~=2.32
12
+ requests
13
13
  typing_extensions>=4.4.0
14
14
 
15
15
  [apt]
@@ -1,12 +1,24 @@
1
+ :tocdepth: 2
2
+
1
3
  *********
2
4
  Changelog
3
5
  *********
4
6
 
7
+ 4.2.7 (2024-Oct-08)
8
+ -------------------
9
+
10
+ - Don't depend on requests >= 2.32.0.
11
+ - Fix: set CRAFT_PARALLEL_BUILD_COUNT correctly in ``override-`` scripts.
12
+
13
+ For a complete list of commits, check out the `4.2.7`_ release on GitHub.
14
+
5
15
  4.2.6 (2024-Oct-04)
6
16
  -------------------
7
17
 
8
18
  - Remove the ``requests<2.32.0`` constraint to resolve CVE-2024-35195.
9
19
 
20
+ For a complete list of commits, check out the `4.2.6`_ release on GitHub.
21
+
10
22
  4.2.5 (2024-Oct-04)
11
23
  -------------------
12
24
 
@@ -305,3 +317,5 @@ For a complete list of commits, check out the `2.7.0`_ release on GitHub.
305
317
  .. _4.2.3: https://github.com/canonical/craft-application/releases/tag/4.2.3
306
318
  .. _4.2.4: https://github.com/canonical/craft-application/releases/tag/4.2.4
307
319
  .. _4.2.5: https://github.com/canonical/craft-application/releases/tag/4.2.5
320
+ .. _4.2.6: https://github.com/canonical/craft-application/releases/tag/4.2.6
321
+ .. _4.2.7: https://github.com/canonical/craft-application/releases/tag/4.2.7
@@ -22,7 +22,7 @@ dependencies = [
22
22
  # Pygit2 changelog: https://github.com/libgit2/pygit2/blob/master/CHANGELOG.md
23
23
  "pygit2>=1.13.0,<1.15.0",
24
24
  "PyYaml>=6.0",
25
- "requests~=2.32",
25
+ "requests",
26
26
  "typing_extensions>=4.4.0",
27
27
  ]
28
28
  classifiers = [
@@ -77,7 +77,7 @@ docs = [
77
77
  "sphinx-lint==0.9.1",
78
78
  ]
79
79
  apt = [
80
- "python-apt>=2.4.0;sys_platform=='linux'"
80
+ "python-apt>=2.4.0;sys_platform=='linux'",
81
81
  ]
82
82
 
83
83
  [build-system]
@@ -23,5 +23,6 @@ parts:
23
23
  echo "project_version: \"${CRAFT_PROJECT_VERSION}\"" >> $target_file
24
24
  echo "arch_build_for: \"${CRAFT_ARCH_BUILD_FOR}\"" >> $target_file
25
25
  echo "arch_triplet_build_for: \"${CRAFT_ARCH_TRIPLET_BUILD_FOR}\"" >> $target_file
26
- echo "arch_build_on: \"${CRAFT_ARCH_BUILD_ON}\"" >> $target_file
27
- echo "arch_triplet_build_on: \"${CRAFT_ARCH_TRIPLET_BUILD_ON}\"" >> $target_file
26
+ echo "arch_build_on: \"${CRAFT_ARCH_BUILD_ON}\"" >> $target_file
27
+ echo "arch_triplet_build_on: \"${CRAFT_ARCH_TRIPLET_BUILD_ON}\"" >> $target_file
28
+ echo "parallel_build_count: \"${CRAFT_PARALLEL_BUILD_COUNT}\"" >> $target_file
@@ -304,6 +304,10 @@ def test_global_environment(
304
304
  ],
305
305
  )
306
306
 
307
+ # Check that this odd value makes its way through to the yaml build script
308
+ build_count = "5"
309
+ mocker.patch.dict("os.environ", {"TESTCRAFT_PARALLEL_BUILD_COUNT": build_count})
310
+
307
311
  # Run in destructive mode
308
312
  monkeypatch.setattr(
309
313
  "sys.argv", ["testcraft", "prime", "--destructive-mode", *arguments]
@@ -328,6 +332,7 @@ def test_global_environment(
328
332
  assert variables["arch_triplet_build_on"].startswith(
329
333
  util.convert_architecture_deb_to_platform(util.get_host_architecture())
330
334
  )
335
+ assert variables["parallel_build_count"] == build_count
331
336
 
332
337
 
333
338
  @pytest.fixture
@@ -26,7 +26,7 @@ import craft_parts.callbacks
26
26
  import pytest
27
27
  import pytest_check
28
28
  from craft_application import errors, models, util
29
- from craft_application.errors import InvalidParameterError, PartsLifecycleError
29
+ from craft_application.errors import PartsLifecycleError
30
30
  from craft_application.models.project import BuildInfo
31
31
  from craft_application.services import lifecycle
32
32
  from craft_application.util import repositories
@@ -611,160 +611,6 @@ def test_lifecycle_package_repositories(
611
611
  mock_callback.assert_called_once_with(repositories.install_overlay_repositories)
612
612
 
613
613
 
614
- # endregion
615
-
616
- # region parallel build count tests
617
-
618
-
619
- @pytest.mark.parametrize(
620
- ("env_dict", "cpu_count", "expected"),
621
- [
622
- (
623
- {},
624
- None,
625
- 1,
626
- ),
627
- (
628
- {},
629
- 100,
630
- 100,
631
- ),
632
- (
633
- {"TESTCRAFT_PARALLEL_BUILD_COUNT": "100"},
634
- 1,
635
- 100,
636
- ),
637
- (
638
- {"CRAFT_PARALLEL_BUILD_COUNT": "200"},
639
- 1,
640
- 200,
641
- ),
642
- (
643
- {
644
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "100",
645
- },
646
- 50,
647
- 50,
648
- ),
649
- (
650
- {
651
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "100",
652
- },
653
- 80,
654
- 80,
655
- ),
656
- (
657
- {
658
- "TESTCRAFT_PARALLEL_BUILD_COUNT": "100",
659
- "CRAFT_PARALLEL_BUILD_COUNT": "200",
660
- },
661
- 1,
662
- 100,
663
- ),
664
- (
665
- {
666
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "100",
667
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "200",
668
- },
669
- 150,
670
- 100,
671
- ),
672
- (
673
- {
674
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "100",
675
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "200",
676
- },
677
- None,
678
- 1,
679
- ),
680
- (
681
- {
682
- "TESTCRAFT_PARALLEL_BUILD_COUNT": "100",
683
- "CRAFT_PARALLEL_BUILD_COUNT": "200",
684
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "300",
685
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "400",
686
- },
687
- 150,
688
- 100,
689
- ),
690
- ],
691
- )
692
- def test_get_parallel_build_count(
693
- monkeypatch, mocker, fake_parts_lifecycle, env_dict, cpu_count, expected
694
- ):
695
- mocker.patch("os.cpu_count", return_value=cpu_count)
696
- for env_dict_key, env_dict_value in env_dict.items():
697
- monkeypatch.setenv(env_dict_key, env_dict_value)
698
-
699
- assert fake_parts_lifecycle._get_parallel_build_count() == expected
700
-
701
-
702
- @pytest.mark.parametrize(
703
- ("env_dict", "cpu_count"),
704
- [
705
- (
706
- {
707
- "TESTCRAFT_PARALLEL_BUILD_COUNT": "abc",
708
- },
709
- 1,
710
- ),
711
- (
712
- {
713
- "CRAFT_PARALLEL_BUILD_COUNT": "-",
714
- },
715
- 1,
716
- ),
717
- (
718
- {
719
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "*",
720
- },
721
- 1,
722
- ),
723
- (
724
- {
725
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "$COUNT",
726
- },
727
- 1,
728
- ),
729
- (
730
- {
731
- "TESTCRAFT_PARALLEL_BUILD_COUNT": "0",
732
- },
733
- 1,
734
- ),
735
- (
736
- {
737
- "CRAFT_PARALLEL_BUILD_COUNT": "-1",
738
- },
739
- 1,
740
- ),
741
- (
742
- {
743
- "TESTCRAFT_MAX_PARALLEL_BUILD_COUNT": "5.6",
744
- },
745
- 1,
746
- ),
747
- (
748
- {
749
- "CRAFT_MAX_PARALLEL_BUILD_COUNT": "inf",
750
- },
751
- 1,
752
- ),
753
- ],
754
- )
755
- def test_get_parallel_build_count_error(
756
- monkeypatch, mocker, fake_parts_lifecycle, env_dict, cpu_count
757
- ):
758
- mocker.patch("os.cpu_count", return_value=cpu_count)
759
- for env_dict_key, env_dict_value in env_dict.items():
760
- monkeypatch.setenv(env_dict_key, env_dict_value)
761
-
762
- with pytest.raises(
763
- InvalidParameterError, match=r"^Value '.*' is invalid for parameter '.*'.$"
764
- ):
765
- fake_parts_lifecycle._get_parallel_build_count()
766
-
767
-
768
614
  # endregion
769
615
 
770
616
  # region project variables