craft-application 2.6.0__tar.gz → 2.6.2__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 (168) hide show
  1. {craft_application-2.6 → craft_application-2.6.2}/PKG-INFO +1 -1
  2. {craft_application-2.6 → craft_application-2.6.2}/craft_application/_version.py +2 -2
  3. {craft_application-2.6 → craft_application-2.6.2}/craft_application/grammar.py +26 -9
  4. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/__init__.py +5 -1
  5. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/grammar.py +11 -5
  6. {craft_application-2.6 → craft_application-2.6.2}/craft_application.egg-info/PKG-INFO +1 -1
  7. {craft_application-2.6 → craft_application-2.6.2}/craft_application.egg-info/SOURCES.txt +1 -0
  8. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/grammar/testcraft.yaml +1 -0
  9. craft_application-2.6.2/tests/unit/models/test_grammar.py +55 -0
  10. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/test_application.py +39 -3
  11. {craft_application-2.6 → craft_application-2.6.2}/.editorconfig +0 -0
  12. {craft_application-2.6 → craft_application-2.6.2}/.github/.jira_sync_config.yaml +0 -0
  13. {craft_application-2.6 → craft_application-2.6.2}/.github/ISSUE_TEMPLATE/bug.yaml +0 -0
  14. {craft_application-2.6 → craft_application-2.6.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  15. {craft_application-2.6 → craft_application-2.6.2}/.github/ISSUE_TEMPLATE/task.yaml +0 -0
  16. {craft_application-2.6 → craft_application-2.6.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  17. {craft_application-2.6 → craft_application-2.6.2}/.github/release-drafter.yaml +0 -0
  18. {craft_application-2.6 → craft_application-2.6.2}/.github/release-drafter.yml +0 -0
  19. {craft_application-2.6 → craft_application-2.6.2}/.github/renovate.json5 +0 -0
  20. {craft_application-2.6 → craft_application-2.6.2}/.github/workflows/cla-check.yaml +0 -0
  21. {craft_application-2.6 → craft_application-2.6.2}/.github/workflows/docs.yaml +0 -0
  22. {craft_application-2.6 → craft_application-2.6.2}/.github/workflows/release-drafter.yaml +0 -0
  23. {craft_application-2.6 → craft_application-2.6.2}/.github/workflows/tests.yaml +0 -0
  24. {craft_application-2.6 → craft_application-2.6.2}/.gitignore +0 -0
  25. {craft_application-2.6 → craft_application-2.6.2}/.pre-commit-config.yaml +0 -0
  26. {craft_application-2.6 → craft_application-2.6.2}/.readthedocs.yaml +0 -0
  27. {craft_application-2.6 → craft_application-2.6.2}/.yamllint.yaml +0 -0
  28. {craft_application-2.6 → craft_application-2.6.2}/HACKING.rst +0 -0
  29. {craft_application-2.6 → craft_application-2.6.2}/LICENSE +0 -0
  30. {craft_application-2.6 → craft_application-2.6.2}/README.rst +0 -0
  31. {craft_application-2.6 → craft_application-2.6.2}/craft_application/__init__.py +0 -0
  32. {craft_application-2.6 → craft_application-2.6.2}/craft_application/application.py +0 -0
  33. {craft_application-2.6 → craft_application-2.6.2}/craft_application/commands/__init__.py +0 -0
  34. {craft_application-2.6 → craft_application-2.6.2}/craft_application/commands/base.py +0 -0
  35. {craft_application-2.6 → craft_application-2.6.2}/craft_application/commands/lifecycle.py +0 -0
  36. {craft_application-2.6 → craft_application-2.6.2}/craft_application/commands/other.py +0 -0
  37. {craft_application-2.6 → craft_application-2.6.2}/craft_application/errors.py +0 -0
  38. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/__init__.py +0 -0
  39. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/errors.py +0 -0
  40. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/launchpad.py +0 -0
  41. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/__init__.py +0 -0
  42. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/base.py +0 -0
  43. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/build.py +0 -0
  44. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/code.py +0 -0
  45. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/distro.py +0 -0
  46. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/project.py +0 -0
  47. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/models/recipe.py +0 -0
  48. {craft_application-2.6 → craft_application-2.6.2}/craft_application/launchpad/util.py +0 -0
  49. {craft_application-2.6 → craft_application-2.6.2}/craft_application/misc/instance_bashrc +0 -0
  50. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/base.py +0 -0
  51. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/constraints.py +0 -0
  52. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/metadata.py +0 -0
  53. {craft_application-2.6 → craft_application-2.6.2}/craft_application/models/project.py +0 -0
  54. {craft_application-2.6 → craft_application-2.6.2}/craft_application/py.typed +0 -0
  55. {craft_application-2.6 → craft_application-2.6.2}/craft_application/remote/__init__.py +0 -0
  56. {craft_application-2.6 → craft_application-2.6.2}/craft_application/remote/errors.py +0 -0
  57. {craft_application-2.6 → craft_application-2.6.2}/craft_application/remote/git.py +0 -0
  58. {craft_application-2.6 → craft_application-2.6.2}/craft_application/remote/utils.py +0 -0
  59. {craft_application-2.6 → craft_application-2.6.2}/craft_application/remote/worktree.py +0 -0
  60. {craft_application-2.6 → craft_application-2.6.2}/craft_application/secrets.py +0 -0
  61. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/__init__.py +0 -0
  62. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/base.py +0 -0
  63. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/lifecycle.py +0 -0
  64. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/package.py +0 -0
  65. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/provider.py +0 -0
  66. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/remotebuild.py +0 -0
  67. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/request.py +0 -0
  68. {craft_application-2.6 → craft_application-2.6.2}/craft_application/services/service_factory.py +0 -0
  69. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/__init__.py +0 -0
  70. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/callbacks.py +0 -0
  71. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/error_formatting.py +0 -0
  72. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/logging.py +0 -0
  73. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/paths.py +0 -0
  74. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/platforms.py +0 -0
  75. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/repositories.py +0 -0
  76. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/snap_config.py +0 -0
  77. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/string.py +0 -0
  78. {craft_application-2.6 → craft_application-2.6.2}/craft_application/util/yaml.py +0 -0
  79. {craft_application-2.6 → craft_application-2.6.2}/craft_application.egg-info/dependency_links.txt +0 -0
  80. {craft_application-2.6 → craft_application-2.6.2}/craft_application.egg-info/requires.txt +0 -0
  81. {craft_application-2.6 → craft_application-2.6.2}/craft_application.egg-info/top_level.txt +0 -0
  82. {craft_application-2.6 → craft_application-2.6.2}/docs/_static/css/custom.css +0 -0
  83. {craft_application-2.6 → craft_application-2.6.2}/docs/conf.py +0 -0
  84. {craft_application-2.6 → craft_application-2.6.2}/docs/explanation/index.rst +0 -0
  85. {craft_application-2.6 → craft_application-2.6.2}/docs/howto/index.rst +0 -0
  86. {craft_application-2.6 → craft_application-2.6.2}/docs/index.rst +0 -0
  87. {craft_application-2.6 → craft_application-2.6.2}/docs/reference/index.rst +0 -0
  88. {craft_application-2.6 → craft_application-2.6.2}/docs/tutorials/index.rst +0 -0
  89. {craft_application-2.6 → craft_application-2.6.2}/pyproject.toml +0 -0
  90. {craft_application-2.6 → craft_application-2.6.2}/setup.cfg +0 -0
  91. {craft_application-2.6 → craft_application-2.6.2}/tests/__init__.py +0 -0
  92. {craft_application-2.6 → craft_application-2.6.2}/tests/conftest.py +0 -0
  93. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/__init__.py +0 -0
  94. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/conftest.py +0 -0
  95. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/build-secrets/secret-source-folder/source-file.txt +0 -0
  96. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/build-secrets/testcraft.yaml +0 -0
  97. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/invalid_projects/build-error/testcraft.yaml +0 -0
  98. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/adoption/stderr +0 -0
  99. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/adoption/testcraft.yaml +0 -0
  100. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/basic/stderr +0 -0
  101. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/basic/testcraft.yaml +0 -0
  102. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/environment/stderr +0 -0
  103. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/environment/testcraft.yaml +0 -0
  104. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/grammar/src/on-amd64-to-amd64/hello.txt +0 -0
  105. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/grammar/src/on-amd64-to-arm64/hello.txt +0 -0
  106. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/data/valid_projects/grammar/stderr +0 -0
  107. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/launchpad/__init__.py +0 -0
  108. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/launchpad/conftest.py +0 -0
  109. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/launchpad/test_anonymous_access.py +0 -0
  110. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/__init__.py +0 -0
  111. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/test_lifecycle.py +0 -0
  112. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/test_provider.py +0 -0
  113. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/test_remotebuild.py +0 -0
  114. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/test_request.py +0 -0
  115. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/services/test_service_factory.py +0 -0
  116. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/test_application.py +0 -0
  117. {craft_application-2.6 → craft_application-2.6.2}/tests/integration/test_version.py +0 -0
  118. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/__init__.py +0 -0
  119. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/commands/__init__.py +0 -0
  120. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/commands/test_base.py +0 -0
  121. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/commands/test_lifecycle.py +0 -0
  122. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/commands/test_other.py +0 -0
  123. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/conftest.py +0 -0
  124. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/__init__.py +0 -0
  125. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/conftest.py +0 -0
  126. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/models/__init__.py +0 -0
  127. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/models/test_base.py +0 -0
  128. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/models/test_code.py +0 -0
  129. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/test_launchpad.py +0 -0
  130. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/launchpad/test_util.py +0 -0
  131. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/__init__.py +0 -0
  132. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/project_models/basic_project.yaml +0 -0
  133. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/project_models/full_project.yaml +0 -0
  134. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/project_models/invalid_project.yaml +0 -0
  135. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/test_constraints.py +0 -0
  136. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/models/test_project.py +0 -0
  137. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/__init__.py +0 -0
  138. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/conftest.py +0 -0
  139. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/test_errors.py +0 -0
  140. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/test_git.py +0 -0
  141. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/test_utils.py +0 -0
  142. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/remote/test_worktree.py +0 -0
  143. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/__init__.py +0 -0
  144. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/conftest.py +0 -0
  145. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_lifecycle.py +0 -0
  146. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_package.py +0 -0
  147. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_provider.py +0 -0
  148. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_remotebuild.py +0 -0
  149. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_repositories.py +0 -0
  150. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_request.py +0 -0
  151. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/services/test_service_factory.py +0 -0
  152. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/test_errors.py +0 -0
  153. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/test_grammar.py +0 -0
  154. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/test_nothing.py +0 -0
  155. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/test_secrets.py +0 -0
  156. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/__init__.py +0 -0
  157. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/invalid_yaml/_README +0 -0
  158. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/invalid_yaml/duplicate_second_level.yaml-invalid +0 -0
  159. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/invalid_yaml/duplicate_top_level.yaml-invalid +0 -0
  160. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/invalid_yaml/unhashable.yaml-invalid +0 -0
  161. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_error_formatting.py +0 -0
  162. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_logging.py +0 -0
  163. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_paths.py +0 -0
  164. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_snap_config.py +0 -0
  165. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_string.py +0 -0
  166. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/test_yaml.py +0 -0
  167. {craft_application-2.6 → craft_application-2.6.2}/tests/unit/util/valid_yaml/empty.yaml +0 -0
  168. {craft_application-2.6 → craft_application-2.6.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: craft-application
3
- Version: 2.6.0
3
+ Version: 2.6.2
4
4
  Summary: A framework for *craft applications.
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '2.6.0'
16
- __version_tuple__ = version_tuple = (2, 6, 0)
15
+ __version__ = version = '2.6.2'
16
+ __version_tuple__ = version_tuple = (2, 6, 2)
@@ -22,6 +22,7 @@ from craft_grammar import GrammarProcessor # type: ignore[import-untyped]
22
22
  from craft_grammar.errors import GrammarSyntaxError # type: ignore[import-untyped]
23
23
 
24
24
  from craft_application.errors import CraftValidationError
25
+ from craft_application.models import get_grammar_aware_part_keywords
25
26
 
26
27
  # Values that should return as a single object / list / dict.
27
28
  _NON_SCALAR_VALUES = [
@@ -53,17 +54,33 @@ def process_part(
53
54
  """Process grammar for a given part."""
54
55
  for key in part_yaml_data:
55
56
  unprocessed_grammar = part_yaml_data[key]
56
- craft_cli.emit.debug(f"Processing grammar for {key}: {unprocessed_grammar}")
57
57
 
58
- # grammar aware models can only be a string or list of dict, skip any other type.
58
+ # ignore non-grammar keywords
59
+ if key not in get_grammar_aware_part_keywords():
60
+ craft_cli.emit.debug(
61
+ f"Not processing grammar for non-grammar enabled keyword {key}"
62
+ )
63
+ continue
64
+
65
+ craft_cli.emit.debug(f"Processing grammar for {key}: {unprocessed_grammar}")
66
+ # grammar aware models can be strings or list of dicts and strings
59
67
  if isinstance(unprocessed_grammar, list):
60
- if any(not isinstance(d, dict) for d in unprocessed_grammar): # type: ignore[reportUnknownVariableType]
68
+ # all items in the list must be a dict or a string
69
+ if any(not isinstance(d, dict | str) for d in unprocessed_grammar): # type: ignore[reportUnknownVariableType]
61
70
  continue
62
- if any(not isinstance(k, str) for d in unprocessed_grammar for k in d): # type: ignore[reportUnknownVariableType]
63
- continue
64
- unprocessed_grammar = cast(list[dict[str, Any]], unprocessed_grammar)
71
+
72
+ # all keys in the dictionary must be a string
73
+ for item in unprocessed_grammar: # type: ignore[reportUnknownVariableType]
74
+ if isinstance(item, dict) and any(
75
+ not isinstance(key, str) for key in item # type: ignore[reportUnknownVariableType]
76
+ ):
77
+ continue
78
+
79
+ unprocessed_grammar = cast(list[dict[str, Any] | str], unprocessed_grammar)
80
+ # grammar aware models can be a string
65
81
  elif isinstance(unprocessed_grammar, str):
66
82
  unprocessed_grammar = [unprocessed_grammar]
83
+ # skip all other data types
67
84
  else:
68
85
  continue
69
86
 
@@ -74,9 +91,9 @@ def process_part(
74
91
  f"Invalid grammar syntax while processing '{key}' in '{part_yaml_data}': {e}"
75
92
  ) from e
76
93
 
77
- # special cases
78
- # scalar values should return as a single object, not in a list.
79
- # dict values should return as a dict, not in a list.
94
+ # special cases:
95
+ # - scalar values should return as a single object, not in a list.
96
+ # - dict values should return as a dict, not in a list.
80
97
  if key not in _NON_SCALAR_VALUES or key in _DICT_ONLY_VALUES:
81
98
  processed_grammar = processed_grammar[0] if processed_grammar else None
82
99
 
@@ -23,7 +23,10 @@ from craft_application.models.constraints import (
23
23
  UniqueStrList,
24
24
  VersionStr,
25
25
  )
26
- from craft_application.models.grammar import GrammarAwareProject
26
+ from craft_application.models.grammar import (
27
+ GrammarAwareProject,
28
+ get_grammar_aware_part_keywords,
29
+ )
27
30
  from craft_application.models.metadata import BaseMetadata
28
31
  from craft_application.models.project import BuildInfo, BuildPlanner, Project
29
32
 
@@ -33,6 +36,7 @@ __all__ = [
33
36
  "BuildInfo",
34
37
  "CraftBaseConfig",
35
38
  "CraftBaseModel",
39
+ "get_grammar_aware_part_keywords",
36
40
  "GrammarAwareProject",
37
41
  "Project",
38
42
  "BuildPlanner",
@@ -1,6 +1,6 @@
1
1
  # This file is part of craft_application.
2
2
  #
3
- # Copyright 2023 Canonical Ltd.
3
+ # Copyright 2023-2024 Canonical Ltd.
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify it
6
6
  # under the terms of the GNU Lesser General Public License version 3, as
@@ -61,10 +61,10 @@ class _GrammarAwarePart(_GrammarAwareModel):
61
61
  build_packages: GrammarStrList | None
62
62
  build_environment: GrammarSingleEntryDictList | None
63
63
  build_attributes: GrammarStrList | None
64
- organize_files: GrammarDict | None
65
- overlay_files: GrammarStrList | None
66
- stage_files: GrammarStrList | None
67
- prime_files: GrammarStrList | None
64
+ organize_files: GrammarDict | None = pydantic.Field(alias="organize")
65
+ overlay_files: GrammarStrList | None = pydantic.Field(alias="overlay")
66
+ stage_files: GrammarStrList | None = pydantic.Field(alias="stage")
67
+ prime_files: GrammarStrList | None = pydantic.Field(alias="prime")
68
68
  override_pull: GrammarStr | None
69
69
  overlay_script: GrammarStr | None
70
70
  override_build: GrammarStr | None
@@ -74,6 +74,12 @@ class _GrammarAwarePart(_GrammarAwareModel):
74
74
  parse_info: GrammarStrList | None
75
75
 
76
76
 
77
+ def get_grammar_aware_part_keywords() -> list[str]:
78
+ """Return all supported grammar keywords for a part."""
79
+ keywords: list[str] = [item.alias for item in _GrammarAwarePart.__fields__.values()]
80
+ return keywords
81
+
82
+
77
83
  class GrammarAwareProject(_GrammarAwareModel):
78
84
  """Project definition containing grammar-aware components."""
79
85
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: craft-application
3
- Version: 2.6.0
3
+ Version: 2.6.2
4
4
  Summary: A framework for *craft applications.
5
5
  Classifier: Development Status :: 5 - Production/Stable
6
6
  Classifier: Environment :: Console
@@ -132,6 +132,7 @@ tests/unit/launchpad/models/test_base.py
132
132
  tests/unit/launchpad/models/test_code.py
133
133
  tests/unit/models/__init__.py
134
134
  tests/unit/models/test_constraints.py
135
+ tests/unit/models/test_grammar.py
135
136
  tests/unit/models/test_project.py
136
137
  tests/unit/models/project_models/basic_project.yaml
137
138
  tests/unit/models/project_models/full_project.yaml
@@ -15,6 +15,7 @@ parts:
15
15
  - on amd64 to arm64:
16
16
  hello.txt: hello-arm64.txt
17
17
  build-environment:
18
+ - HELLO: hello
18
19
  - on amd64 to amd64:
19
20
  - MY_VAR: amd64
20
21
  - on amd64 to arm64:
@@ -0,0 +1,55 @@
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. See the GNU
12
+ # 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
+
17
+ """Tests for grammar-aware project models."""
18
+
19
+ from craft_application.models import get_grammar_aware_part_keywords
20
+
21
+
22
+ def test_get_grammar_aware_part_keywords():
23
+ """Test get_grammar_aware_part_keywords."""
24
+ assert get_grammar_aware_part_keywords() == [
25
+ "plugin",
26
+ "source",
27
+ "source-checksum",
28
+ "source-branch",
29
+ "source-commit",
30
+ "source-depth",
31
+ "source-subdir",
32
+ "source-submodules",
33
+ "source-tag",
34
+ "source-type",
35
+ "disable-parallel",
36
+ "after",
37
+ "overlay-packages",
38
+ "stage-snaps",
39
+ "stage-packages",
40
+ "build-snaps",
41
+ "build-packages",
42
+ "build-environment",
43
+ "build-attributes",
44
+ "organize",
45
+ "overlay",
46
+ "stage",
47
+ "prime",
48
+ "override-pull",
49
+ "overlay-script",
50
+ "override-build",
51
+ "override-stage",
52
+ "override-prime",
53
+ "permissions",
54
+ "parse-info",
55
+ ]
@@ -1341,10 +1341,26 @@ def grammar_project_mini(tmp_path):
1341
1341
  version: 1.0
1342
1342
  parts:
1343
1343
  mypart:
1344
- plugin: nil
1344
+ plugin: meson
1345
+
1346
+ # grammar-only string
1345
1347
  source:
1346
1348
  - on amd64 to riscv64: on-amd64-to-riscv64
1347
1349
  - on amd64 to s390x: on-amd64-to-s390x
1350
+ - else: other
1351
+
1352
+ # list of grammar and non-grammar data
1353
+ build-packages:
1354
+ - test-package
1355
+ - on amd64 to riscv64:
1356
+ - on-amd64-to-riscv64
1357
+ - on amd64 to s390x:
1358
+ - on-amd64-to-s390x
1359
+
1360
+ # non-grammar data in a non-grammar keyword
1361
+ meson-parameters:
1362
+ - foo
1363
+ - bar
1348
1364
  """
1349
1365
  )
1350
1366
  project_file = tmp_path / "testcraft.yaml"
@@ -1446,26 +1462,46 @@ def test_process_grammar_build_for(grammar_app_mini):
1446
1462
  """Test that a provided build-for is used to process the grammar."""
1447
1463
  project = grammar_app_mini.get_project(build_for="s390x")
1448
1464
  assert project.parts["mypart"]["source"] == "on-amd64-to-s390x"
1465
+ assert project.parts["mypart"]["build-packages"] == [
1466
+ "test-package",
1467
+ "on-amd64-to-s390x",
1468
+ ]
1449
1469
 
1450
1470
 
1451
1471
  def test_process_grammar_platform(grammar_app_mini):
1452
1472
  """Test that a provided platform is used to process the grammar."""
1453
1473
  project = grammar_app_mini.get_project(platform="platform-riscv64")
1454
1474
  assert project.parts["mypart"]["source"] == "on-amd64-to-riscv64"
1475
+ assert project.parts["mypart"]["build-packages"] == [
1476
+ "test-package",
1477
+ "on-amd64-to-riscv64",
1478
+ ]
1479
+
1480
+
1481
+ def test_process_grammar_non_grammar(grammar_app_mini):
1482
+ """Non-grammar keywords should not be modified."""
1483
+ project = grammar_app_mini.get_project(platform="platform-riscv64")
1484
+
1485
+ assert project.parts["mypart"]["meson-parameters"] == ["foo", "bar"]
1455
1486
 
1456
1487
 
1457
1488
  def test_process_grammar_default(grammar_app_mini):
1458
1489
  """Test that if nothing is provided the first BuildInfo is used by the grammar."""
1459
1490
  project = grammar_app_mini.get_project()
1460
1491
  assert project.parts["mypart"]["source"] == "on-amd64-to-riscv64"
1492
+ assert project.parts["mypart"]["build-packages"] == [
1493
+ "test-package",
1494
+ "on-amd64-to-riscv64",
1495
+ ]
1461
1496
 
1462
1497
 
1463
1498
  def test_process_grammar_no_match(grammar_app_mini, mocker):
1464
1499
  """Test that if the build plan is empty, the grammar uses the host as target arch."""
1465
1500
  mocker.patch("craft_application.util.get_host_architecture", return_value="i386")
1466
1501
  project = grammar_app_mini.get_project()
1467
- # "source" is empty because "i386" doesn't match any of the grammar statements.
1468
- assert project.parts["mypart"]["source"] is None
1502
+
1503
+ assert project.parts["mypart"]["source"] == "other"
1504
+ assert project.parts["mypart"]["build-packages"] == ["test-package"]
1469
1505
 
1470
1506
 
1471
1507
  class FakeApplicationWithYamlTransform(FakeApplication):