ops 2.22.0__tar.gz → 2.23.0.dev0__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 (104) hide show
  1. ops-2.23.0.dev0/CONTRIBUTING.md +130 -0
  2. {ops-2.22.0 → ops-2.23.0.dev0}/HACKING.md +43 -150
  3. {ops-2.22.0 → ops-2.23.0.dev0}/PKG-INFO +40 -52
  4. {ops-2.22.0 → ops-2.23.0.dev0}/README.md +37 -35
  5. {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/_main.py +28 -7
  6. {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/harness.py +0 -7
  7. {ops-2.22.0 → ops-2.23.0.dev0}/ops/charm.py +218 -10
  8. {ops-2.22.0 → ops-2.23.0.dev0}/ops/jujucontext.py +5 -1
  9. {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/model.py +215 -18
  10. {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/pebble.py +47 -11
  11. {ops-2.22.0 → ops-2.23.0.dev0}/ops/testing.py +2 -0
  12. {ops-2.22.0/test/charms/test_main/lib → ops-2.23.0.dev0}/ops/version.py +1 -1
  13. {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/PKG-INFO +40 -52
  14. {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/SOURCES.txt +6 -0
  15. ops-2.23.0.dev0/ops.egg-info/requires.txt +12 -0
  16. {ops-2.22.0 → ops-2.23.0.dev0}/pyproject.toml +62 -10
  17. {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/_main.py +28 -7
  18. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/harness.py +0 -7
  19. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/charm.py +218 -10
  20. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/jujucontext.py +5 -1
  21. {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/model.py +215 -18
  22. {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/pebble.py +47 -11
  23. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/testing.py +2 -0
  24. {ops-2.22.0 → ops-2.23.0.dev0/test/charms/test_main/lib}/ops/version.py +1 -1
  25. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/src/charm.py +9 -0
  26. ops-2.23.0.dev0/test/charms/test_relation/charmcraft.yaml +32 -0
  27. ops-2.23.0.dev0/test/charms/test_relation/src/charm.py +54 -0
  28. ops-2.23.0.dev0/test/charms/test_tracing/.gitignore +3 -0
  29. ops-2.23.0.dev0/test/integration/conftest.py +246 -0
  30. ops-2.23.0.dev0/test/integration/test_relation.py +72 -0
  31. {ops-2.22.0 → ops-2.23.0.dev0}/test/integration/test_tracing.py +16 -16
  32. {ops-2.22.0 → ops-2.23.0.dev0}/test/pebble_cli.py +14 -8
  33. {ops-2.22.0 → ops-2.23.0.dev0}/test/smoke/test_smoke.py +2 -14
  34. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_charm.py +846 -2
  35. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_infra.py +5 -3
  36. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_jujucontext.py +6 -0
  37. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main.py +53 -7
  38. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_model.py +236 -145
  39. ops-2.23.0.dev0/test/test_model_relation_data_class.py +951 -0
  40. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_pebble.py +43 -0
  41. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_real_pebble.py +3 -0
  42. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_testing.py +4 -3
  43. {ops-2.22.0 → ops-2.23.0.dev0}/tox.ini +33 -118
  44. ops-2.22.0/ops.egg-info/requires.txt +0 -27
  45. ops-2.22.0/test/integration/conftest.py +0 -205
  46. {ops-2.22.0 → ops-2.23.0.dev0}/CHANGES.md +0 -0
  47. {ops-2.22.0 → ops-2.23.0.dev0}/CODE_OF_CONDUCT.md +0 -0
  48. {ops-2.22.0 → ops-2.23.0.dev0}/LICENSE.txt +0 -0
  49. {ops-2.22.0 → ops-2.23.0.dev0}/MANIFEST.in +0 -0
  50. {ops-2.22.0 → ops-2.23.0.dev0}/SECURITY.md +0 -0
  51. {ops-2.22.0 → ops-2.23.0.dev0}/STYLE.md +0 -0
  52. {ops-2.22.0 → ops-2.23.0.dev0}/ops/__init__.py +0 -0
  53. {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/__init__.py +0 -0
  54. {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/timeconv.py +0 -0
  55. {ops-2.22.0 → ops-2.23.0.dev0}/ops/_private/yaml.py +0 -0
  56. {ops-2.22.0 → ops-2.23.0.dev0}/ops/framework.py +0 -0
  57. {ops-2.22.0 → ops-2.23.0.dev0}/ops/jujuversion.py +0 -0
  58. {ops-2.22.0 → ops-2.23.0.dev0}/ops/lib/__init__.py +0 -0
  59. {ops-2.22.0 → ops-2.23.0.dev0}/ops/log.py +0 -0
  60. {ops-2.22.0 → ops-2.23.0.dev0}/ops/main.py +0 -0
  61. {ops-2.22.0 → ops-2.23.0.dev0}/ops/py.typed +0 -0
  62. {ops-2.22.0 → ops-2.23.0.dev0}/ops/storage.py +0 -0
  63. {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/dependency_links.txt +0 -0
  64. {ops-2.22.0 → ops-2.23.0.dev0}/ops.egg-info/top_level.txt +0 -0
  65. {ops-2.22.0 → ops-2.23.0.dev0}/setup.cfg +0 -0
  66. {ops-2.22.0 → ops-2.23.0.dev0}/test/__init__.py +0 -0
  67. {ops-2.22.0 → ops-2.23.0.dev0}/test/benchmark/__init__.py +0 -0
  68. {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-ids +0 -0
  69. {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-ids.bat +0 -0
  70. {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-list +0 -0
  71. {ops-2.22.0 → ops-2.23.0.dev0}/test/bin/relation-list.bat +0 -0
  72. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/actions.yaml +0 -0
  73. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/config.yaml +0 -0
  74. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/__init__.py +0 -0
  75. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/__init__.py +0 -0
  76. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/__init__.py +0 -0
  77. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/timeconv.py +0 -0
  78. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/_private/yaml.py +0 -0
  79. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/framework.py +0 -0
  80. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/jujuversion.py +0 -0
  81. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/lib/__init__.py +0 -0
  82. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/log.py +0 -0
  83. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/main.py +0 -0
  84. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/py.typed +0 -0
  85. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/lib/ops/storage.py +0 -0
  86. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_main/metadata.yaml +0 -0
  87. {ops-2.22.0/test/charms/test_tracing → ops-2.23.0.dev0/test/charms/test_relation}/.gitignore +0 -0
  88. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/README.md +0 -0
  89. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/metadata.yaml +0 -0
  90. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_smoke/src/charm.py +0 -0
  91. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_tracing/charmcraft.yaml +0 -0
  92. {ops-2.22.0 → ops-2.23.0.dev0}/test/charms/test_tracing/src/charm.py +0 -0
  93. {ops-2.22.0 → ops-2.23.0.dev0}/test/conftest.py +0 -0
  94. {ops-2.22.0 → ops-2.23.0.dev0}/test/fake_pebble.py +0 -0
  95. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_framework.py +0 -0
  96. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_helpers.py +0 -0
  97. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_jujuversion.py +0 -0
  98. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_lib.py +0 -0
  99. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_log.py +0 -0
  100. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main_invocation.py +0 -0
  101. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_main_type_hint.py +0 -0
  102. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_storage.py +0 -0
  103. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_timeconv.py +0 -0
  104. {ops-2.22.0 → ops-2.23.0.dev0}/test/test_yaml.py +0 -0
@@ -0,0 +1,130 @@
1
+ We welcome contributions to Ops!
2
+
3
+ Before working on changes, please consider [opening an issue](https://github.com/canonical/operator/issues) explaining your use case. If you would like to chat with us about your use cases or proposed implementation, you can reach us at [Matrix](https://matrix.to/#/#charmhub-charmdev:ubuntu.com) or [Discourse](https://discourse.charmhub.io/).
4
+
5
+ For detailed technical information about the development of Ops, see [HACKING.md](./HACKING.md).
6
+
7
+ # Pull requests
8
+
9
+ Changes are proposed as [pull requests on GitHub](https://github.com/canonical/operator/pulls).
10
+
11
+ Pull requests should have a short title that follows the [conventional commit style](https://www.conventionalcommits.org/en/) using one of these types:
12
+
13
+ - chore
14
+ - ci
15
+ - docs
16
+ - feat
17
+ - fix
18
+ - perf
19
+ - refactor
20
+ - revert
21
+ - test
22
+
23
+ Some examples:
24
+
25
+ - feat: add the ability to observe change-updated events
26
+ - fix!: correct the type hinting for config data
27
+ - docs: clarify how to use mounts in ops.testing.Container
28
+ - ci: adjust the workflow that publishes ops-scenario
29
+
30
+ We consider Ops too small a project to use scopes, so we don't use them.
31
+
32
+ Note that the commit messages to the PR's branch do not need to follow the conventional commit format, as these will be squashed into a single commit to `main` using the PR title as the commit message.
33
+
34
+ To help us review your changes, please rebase your pull request onto the `main` branch before you request a review. If you need to bring in the latest changes from `main` after the review has started, please use a merge commit.
35
+
36
+ # Tests
37
+
38
+ Changes should include tests. Where reasonable, prefer to write 'Scenario' tests using [ops.testing](https://ops.readthedocs.io/en/latest/reference/ops-testing.html) instead of legacy [ops.testing.Harness](https://ops.readthedocs.io/en/latest/reference/ops-testing-harness.html) tests.
39
+
40
+ Tests for Ops should go in the test module corresponding to the code. For example, a feature added in `ops/main.py` would go in `test/test_main.py`. However, when adding a large number of logically related tests, consider putting these in their own file, named accordingly. For example, if adding a feature `foo` in `ops/main.py`, the tests might go in `test/test_main_foo.py`.
41
+
42
+ Tests for [`ops-scenario`](https://github.com/canonical/operator/tree/main/testing/tests) and [`ops-tracing`](https://github.com/canonical/operator/tree/main/tracing/test) are arranged differently in places. Try to find the most logical place to add tests, based on the code that is tested.
43
+
44
+ # Coding style
45
+
46
+ We have a team [Python style guide](./STYLE.md), most of which is enforced by CI checks. Please be complete with docstrings and keep them informative for _users_, as the [Ops library reference](https://ops.readthedocs.io/en/latest/reference/index.html) is automatically generated from Python docstrings.
47
+
48
+ # Documentation
49
+
50
+ The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html) are built automatically from [the top-level `docs` directory](./docs). We use [MyST Markdown](https://mystmd.org/) for most pages and arrange the pages according to [Diátaxis](https://diataxis.fr/).
51
+
52
+ To contribute docs:
53
+
54
+ 1. Fork this repo and edit the relevant source files:
55
+ - Tutorials - [`/docs/tutorial`](./docs/tutorial)
56
+ - How-to guides - [`/docs/howto`](./docs/howto)
57
+ - Reference - Automatically generated from Python docstrings
58
+ - Explanation - [`/docs/explanation`](./docs/explanation)
59
+ 2. [Build the documentation locally](#how-to-build-the-documentation-locally), to check that everything looks right
60
+ 3. [Propose your changes using a pull request](#pull-requests)
61
+
62
+ When you create the pull request, GitHub automatically builds a preview of the docs. To find the preview, look for the "docs/readthedocs.org:ops" check near the bottom of the pull request page, then click **Details**. You can use the preview to double check that everything looks right.
63
+
64
+ ## How to write great documentation
65
+
66
+ - Use short sentences, ideally with one or two clauses.
67
+ - Use headings to split the doc into sections. Make sure that the purpose of each section is clear from its heading.
68
+ - Avoid a long introduction. Assume that the reader is only going to scan the first paragraph and the headings.
69
+ - Avoid background context unless it's essential for the reader to understand.
70
+
71
+ Recommended tone:
72
+
73
+ - Use a casual tone, but avoid idioms. Common contractions such as "it's" and "doesn't" are great.
74
+ - Use "we" to include the reader in what you're explaining.
75
+ - Avoid passive descriptions. If you expect the reader to do something, give a direct instruction.
76
+
77
+ ## How to build the documentation locally
78
+
79
+ To build the docs and open them in your browser:
80
+
81
+ ```sh
82
+ tox -e docs
83
+ open docs/_build/html/index.html
84
+ ```
85
+
86
+ Alternatively, to serve the docs locally and automatically refresh them whenever you edit a file:
87
+
88
+ ```sh
89
+ tox -e docs-live
90
+ ```
91
+
92
+ ## How to document version dependencies
93
+
94
+ We don't publish separate documentation for separate versions of Ops. The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html) are always for the in-development (main branch) of Ops, and do not include any notes indicating changes or additions across Ops versions. We encourage all charmers to promptly upgrade to the latest version of Ops, and to refer to the release notes and changelog for learning about changes.
95
+
96
+ We do note when features behave differently when using different versions of Juju.
97
+
98
+ In docstrings:
99
+
100
+ - Use `.. jujuadded:: x.y` to indicate that the feature is only available when using version x.y (or higher) of Juju.
101
+ - Use `.. jujuchanged:: x.y` when the feature's behaviour _in Ops_ changes.
102
+ - Use `.. jujuremoved:: x.y` when the feature will be available in Ops but not in that version (or later) of Juju.
103
+
104
+ Similar directives also work in MyST Markdown. For example:
105
+
106
+ ````markdown
107
+ ```{jujuadded} x.y
108
+ Summary
109
+ ```
110
+ ````
111
+
112
+ Unmarked features are assumed to work and be available in the current LTS version of Juju.
113
+
114
+ # Copyright
115
+
116
+ The format for copyright notices is documented in the [LICENSE.txt](LICENSE.txt). New files should begin with a copyright line with the current year (e.g. Copyright 2024 Canonical Ltd.) and include the full boilerplate (see APPENDIX of [LICENSE.txt](LICENSE.txt)). The copyright information in existing files does not need to be updated when those files are modified -- only the initial creation year is required.
117
+
118
+ # Reviews
119
+
120
+ All changes require review before being merged. Code review typically examines:
121
+
122
+ - Code quality
123
+ - Test coverage
124
+ - User experience
125
+
126
+ When evaluating design decisions, we give priority to the following personas:
127
+
128
+ - Charm authors and maintainers (highest priority)
129
+ - Contributors to the Ops codebase
130
+ - Juju developers
@@ -1,14 +1,38 @@
1
+ We welcome contributions to Ops! Before you start work on a contribution, please also read [CONTRIBUTING.md](./CONTRIBUTING.md).
2
+
1
3
  # Setting up a Dev Environment
2
4
 
3
5
  To work in the framework itself you will need Python >= 3.8. Linting, testing,
4
6
  and docs automation is performed using
5
- [`tox`](https://tox.readthedocs.io/en/latest/), which you should install.
6
- For improved performance on the tests, ensure that you have PyYAML
7
- installed with the correct extensions:
7
+ [`tox`](https://tox.readthedocs.io/en/latest/).
8
+
9
+ First, make sure to install [uv](https://docs.astral.sh/uv/), for example:
10
+
11
+ ```sh
12
+ sudo snap install astral-uv --classic
13
+ ```
14
+
15
+ Then install `tox` with extensions, as well as a range of Python versions:
8
16
 
9
17
  ```sh
10
- apt-get install libyaml-dev
11
- pip install --force-reinstall --no-cache-dir pyyaml
18
+ uv tool install tox --with tox-uv
19
+ uv tool update-shell
20
+ ```
21
+
22
+ You can validate that you have a working installation by running:
23
+
24
+ ```sh
25
+ tox --version
26
+ 4.26.0 from /home/<your-user>/.local/share/uv/tools/tox/lib/python3.13/site-packages/tox/__init__.py
27
+ registered plugins:
28
+ tox-uv-1.26.0 at /home/<your-user>/.local/share/uv/tools/tox/lib/python3.13/site-packages/tox_uv/plugin.py with uv==0.7.12
29
+ ```
30
+
31
+ For improved performance on the tests, install the library that allows
32
+ PyYAML to use C speedups:
33
+
34
+ ```sh
35
+ sudo apt-get install libyaml-dev
12
36
  ```
13
37
 
14
38
  # Testing
@@ -26,9 +50,6 @@ tox -e unit -- test/test_charm.py
26
50
  # Format the code using Ruff
27
51
  tox -e format
28
52
 
29
- # Compile the requirements.txt file for docs
30
- tox -e docs-deps
31
-
32
53
  # Generate a local copy of the Sphinx docs in docs/_build
33
54
  tox -e docs
34
55
 
@@ -36,23 +57,18 @@ tox -e docs
36
57
  tox -e unit -- -k <pattern>
37
58
  ```
38
59
 
39
- For more in depth debugging, you can enter any of `tox`'s created virtualenvs
40
- provided they have been run at least once and do fun things - e.g. run
41
- `pytest` directly:
60
+ For more in depth debugging, you can enter the virtualenv so that you can run
61
+ `pytest` or other tools directly:
42
62
 
43
63
  ```sh
44
- # Enter the linting virtualenv
45
- source .tox/lint/bin/activate
46
-
47
- ...
48
-
49
- # Enter the unit testing virtualenv and run tests
50
- source .tox/unit/bin/activate
64
+ uv sync --all-groups
65
+ source .venv/bin/activate
51
66
  pytest
52
- ...
53
-
54
67
  ```
55
68
 
69
+ Likewise, use this virtualenv to enable Python type hints and language server if
70
+ you use an editor from the console or specify it as interpreter path in an IDE.
71
+
56
72
  ## Pebble Tests
57
73
 
58
74
  The framework has some tests that interact with a real/live Pebble server. To
@@ -160,126 +176,6 @@ your charm to a controller using that version of Juju. For example, with microk8
160
176
  We rely on automation to [update charm pins](.github/actions/update-charm-pins/) of
161
177
  a bunch of charms that use the operator framework. The script can be run locally too.
162
178
 
163
- # Contributing
164
-
165
- Changes are proposed as [pull requests on GitHub](https://github.com/canonical/operator/pulls).
166
-
167
- For coding style, we follow [PEP 8](https://peps.python.org/pep-0008/) as well as a team [Python style guide](./STYLE.md). Please be complete with docstrings and keep them informative for _users_,
168
- as the [ops library reference](https://ops.readthedocs.io/en/latest/reference/index.html)
169
- is automatically generated from Python docstrings.
170
-
171
- For more advice about contributing documentation, see [Contributing documentation](#contributing-documentation).
172
-
173
- Pull requests should have a short title that follows the
174
- [conventional commit style](https://www.conventionalcommits.org/en/) using one of these types:
175
-
176
- * chore
177
- * ci
178
- * docs
179
- * feat
180
- * fix
181
- * perf
182
- * refactor
183
- * revert
184
- * test
185
-
186
- Some examples:
187
-
188
- * feat: add the ability to observe change-updated events
189
- * fix!: correct the type hinting for config data
190
- * docs: clarify how to use mounts in ops.testing.Container
191
- * ci: adjust the workflow that publishes ops-scenario
192
-
193
- Note that the commit messages to the PR's branch do not need to follow the
194
- conventional commit format, as these will be squashed into a single commit to `main`
195
- using the PR title as the commit message.
196
-
197
- We consider Ops too small a project to use scopes, so we don't use them.
198
-
199
- ## Copyright
200
-
201
- The format for copyright notices is documented in the [LICENSE.txt](LICENSE.txt).
202
- New files should begin with a copyright line with the current year (e.g. Copyright 2024 Canonical Ltd.) and include the full boilerplate (see APPENDIX of [LICENSE.txt](LICENSE.txt)).
203
- The copyright information in existing files does not need to be updated when those files are modified -- only the initial creation year is required.
204
-
205
- # Contributing documentation
206
-
207
- The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html)
208
- are built automatically from [the top-level `docs` directory](./docs). We use [MyST Markdown](https://mystmd.org/)
209
- for most pages and arrange the pages according to [Diátaxis](https://diataxis.fr/).
210
-
211
- To contribute docs:
212
-
213
- 1. Fork this repo and edit the relevant source files:
214
- * Tutorials - [`/docs/tutorial`](./docs/tutorial)
215
- * How-to guides - [`/docs/howto`](./docs/howto)
216
- * Reference - Automatically generated from Python docstrings
217
- * Explanation - [`/docs/explanation`](./docs/explanation)
218
- 2. [Build the documentation locally](#how-to-build-the-documentation-locally),
219
- to check that everything looks right
220
- 3. [Propose your changes using a pull request](#contributing)
221
-
222
- When you create the pull request, GitHub automatically builds a preview of the docs.
223
- To find the preview, look for the "docs/readthedocs.org:ops" check near the bottom of
224
- the pull request page, then click **Details**. You can use the preview to double check
225
- that everything looks right.
226
-
227
- ## How to write great documentation
228
-
229
- - Use short sentences, ideally with one or two clauses.
230
- - Use headings to split the doc into sections. Make sure that the purpose of each section is clear from its heading.
231
- - Avoid a long introduction. Assume that the reader is only going to scan the first paragraph and the headings.
232
- - Avoid background context unless it's essential for the reader to understand.
233
-
234
- Recommended tone:
235
- - Use a casual tone, but avoid idioms. Common contractions such as "it's" and "doesn't" are great.
236
- - Use "we" to include the reader in what you're explaining.
237
- - Avoid passive descriptions. If you expect the reader to do something, give a direct instruction.
238
-
239
- ## How to build the documentation locally
240
-
241
- To build the docs and open them in your browser:
242
-
243
- ```sh
244
- tox -e docs
245
- open docs/_build/html/index.html
246
- ```
247
-
248
- Alternatively, to serve the docs locally and automatically refresh them whenever you edit a file:
249
-
250
- ```sh
251
- tox -e docs-live
252
- ```
253
-
254
- ## How to document version dependencies
255
-
256
- We don't publish separate documentation for separate versions of ops.
257
- The published docs at [ops.readthedocs.io](https://ops.readthedocs.io/en/latest/index.html)
258
- are always for the in-development (main branch) of ops, and do not include
259
- any notes indicating changes or additions across ops versions.
260
- We encourage all charmers to promptly upgrade to the latest version of ops,
261
- and to refer to the release notes and changelog for learning about changes.
262
-
263
- We do note when features behave differently when using different versions of Juju.
264
-
265
- In docstrings:
266
-
267
- * Use `.. jujuadded:: x.y` to indicate that the feature is only available
268
- when using version x.y (or higher) of Juju.
269
- * Use `..jujuchanged:: x.y` when the feature's behaviour _in ops_ changes.
270
- * Use `..jujuremoved:: x.y` when the feature will be available in ops
271
- but not in that version (or later) of Juju.
272
-
273
- Similar directives also work in MyST Markdown. For example:
274
-
275
- ````markdown
276
- ```{jujuadded} x.y
277
- Summary
278
- ```
279
- ````
280
-
281
- Unmarked features are assumed to work and be available in the current LTS version of Juju.
282
-
283
179
  # Maintaining the documentation
284
180
 
285
181
  ## How to Pull in Style Changes
@@ -307,7 +203,7 @@ To pull in new dependency changes from the starter pack, change to the starter p
307
203
  make html
308
204
  ```
309
205
 
310
- Then, compare the generated file `.sphinx/requirements.txt`and the `project.optional-dependencies.docs` section of [`pyproject.toml`](./pyproject.toml) and adjust the `pyproject.toml` file accordingly.
206
+ Then, compare the generated file `.sphinx/requirements.txt` and the `docs` declaration in the `dependency-groups` section of [`pyproject.toml`](./pyproject.toml) and adjust the `pyproject.toml` file accordingly.
311
207
 
312
208
  # Dependencies
313
209
 
@@ -368,14 +264,11 @@ To make a release of the `ops` and/or `ops-scenario` packages, do the following:
368
264
  - in [pyroject.toml for `ops`](pyproject.toml), the required versions for `ops-scenario` and `ops-tracing`
369
265
  - in [pyproject.toml for `ops-scenario`](testing/pyproject.toml), the `version` attribute and the required version for `ops`
370
266
  - in [pyproject.toml for `ops-tracing`](tracing/pyproject.toml), the `version` attribute and the required version for `ops`
371
- 11. Run `uvx -p 3.11 tox -e docs-deps` to recompile the `requirements.txt` file
372
- used for docs (in case dependencies have been updated in `pyproject.toml`)
373
- using the same Python version as specified in the `.readthedocs.yaml` file.
374
- 12. Add, commit, and push, and open a PR to get the `CHANGES.md` update, version bumps,
375
- and doc requirement bumps into main (and get it merged).
376
- 13. Wait until the tests pass after the PR is merged. It takes around 10 minutes.
267
+ 11. Add, commit, and push, and open a PR to get the `CHANGES.md` update and version
268
+ bumps into main (and get it merged).
269
+ 12. Wait until the tests pass after the PR is merged. It takes around 10 minutes.
377
270
  If the tests don't pass at the tip of the main branch, do not release.
378
- 14. When you are ready, click "Publish". GitHub will create the additional tag.
271
+ 13. When you are ready, click "Publish". GitHub will create the additional tag.
379
272
 
380
273
  Pushing the tags will trigger automatic builds for the Python packages and
381
274
  publish them to PyPI ([ops](https://pypi.org/project/ops/) and
@@ -388,9 +281,9 @@ To make a release of the `ops` and/or `ops-scenario` packages, do the following:
388
281
  (Note that the versions in the YAML refer to versions of the GitHub actions, not the versions of the ops library.)
389
282
 
390
283
  You can troubleshoot errors on the [Actions Tab](https://github.com/canonical/operator/actions).
391
- 15. Announce the release on [Discourse](https://discourse.charmhub.io/c/framework/42)
284
+ 14. Announce the release on [Discourse](https://discourse.charmhub.io/c/framework/42)
392
285
  and [Matrix](https://matrix.to/#/#charmhub-charmdev:ubuntu.com).
393
- 16. Open a PR to change the version strings to the expected next version, with ".dev0" appended.
286
+ 15. Open a PR to change the version strings to the expected next version, with ".dev0" appended.
394
287
  For example, if 2.90.0 is the next expected `ops` version, use
395
288
  `ops==2.90.0.dev0 ops-tracing==2.90.0.dev0 ops-scenario==7.90.0.dev0`.
396
289
  There will be a total of seven changes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ops
3
- Version: 2.22.0
3
+ Version: 2.23.0.dev0
4
4
  Summary: The Python library behind great charms
5
5
  Author: The Charm Tech team at Canonical Ltd.
6
6
  Project-URL: Homepage, https://ops.readthedocs.io/en/latest/
@@ -22,24 +22,10 @@ Requires-Dist: PyYAML==6.*
22
22
  Requires-Dist: websocket-client==1.*
23
23
  Requires-Dist: opentelemetry-api~=1.0
24
24
  Requires-Dist: importlib-metadata
25
- Provides-Extra: docs
26
- Requires-Dist: canonical-sphinx-extensions; extra == "docs"
27
- Requires-Dist: furo; extra == "docs"
28
- Requires-Dist: linkify-it-py; extra == "docs"
29
- Requires-Dist: myst-parser; extra == "docs"
30
- Requires-Dist: pyspelling; extra == "docs"
31
- Requires-Dist: sphinx~=8.0.0; extra == "docs"
32
- Requires-Dist: sphinx-autobuild; extra == "docs"
33
- Requires-Dist: sphinx-copybutton; extra == "docs"
34
- Requires-Dist: sphinx-design; extra == "docs"
35
- Requires-Dist: sphinx-notfound-page; extra == "docs"
36
- Requires-Dist: sphinx-tabs; extra == "docs"
37
- Requires-Dist: sphinxcontrib-jquery; extra == "docs"
38
- Requires-Dist: sphinxext-opengraph; extra == "docs"
39
25
  Provides-Extra: testing
40
- Requires-Dist: ops-scenario==7.22.0; extra == "testing"
26
+ Requires-Dist: ops-scenario==7.23.0.dev0; extra == "testing"
41
27
  Provides-Extra: tracing
42
- Requires-Dist: ops-tracing==2.22.0; extra == "tracing"
28
+ Requires-Dist: ops-tracing==2.23.0.dev0; extra == "tracing"
43
29
  Provides-Extra: harness
44
30
  Dynamic: license-file
45
31
 
@@ -131,46 +117,48 @@ class OpsExampleCharm(ops.CharmBase):
131
117
  self.unit.status = ops.ActiveStatus()
132
118
  ```
133
119
 
134
- > See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/index.html#ops.PebbleReadyEvent)
120
+ > See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/reference/ops.html#ops.PebbleReadyEvent)
135
121
 
136
- - The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a testing harness:
122
+ - The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a unit test:
137
123
 
138
124
  ```python
139
- import ops.testing
140
-
141
- class TestCharm(unittest.TestCase):
142
- def setUp(self):
143
- self.harness = ops.testing.Harness(OpsExampleCharm)
144
- self.addCleanup(self.harness.cleanup)
145
- self.harness.begin()
146
-
147
- def test_httpbin_pebble_ready(self):
148
- # Expected plan after Pebble ready with default config
149
- expected_plan = {
150
- "services": {
151
- "httpbin": {
152
- "override": "replace",
153
- "summary": "httpbin",
154
- "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
155
- "startup": "enabled",
156
- "environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
157
- }
158
- },
159
- }
160
- # Simulate the container coming up and emission of pebble-ready event
161
- self.harness.container_pebble_ready("httpbin")
162
- # Get the plan now we've run PebbleReady
163
- updated_plan = self.harness.get_container_pebble_plan("httpbin").to_dict()
164
- # Check we've got the plan we expected
165
- self.assertEqual(expected_plan, updated_plan)
166
- # Check the service was started
167
- service = self.harness.model.unit.get_container("httpbin").get_service("httpbin")
168
- self.assertTrue(service.is_running())
169
- # Ensure we set an ActiveStatus with no message
170
- self.assertEqual(self.harness.model.unit.status, ops.ActiveStatus())
125
+ import ops
126
+ from ops import testing
127
+
128
+ from charm import OpsExampleCharm
129
+
130
+
131
+ def test_httpbin_pebble_ready():
132
+ # Arrange:
133
+ ctx = testing.Context(OpsExampleCharm)
134
+ container = testing.Container("httpbin", can_connect=True)
135
+ state_in = testing.State(containers={container})
136
+
137
+ # Act:
138
+ state_out = ctx.run(ctx.on.pebble_ready(container), state_in)
139
+
140
+ # Assert:
141
+ updated_plan = state_out.get_container(container.name).plan
142
+ expected_plan = {
143
+ "services": {
144
+ "httpbin": {
145
+ "override": "replace",
146
+ "summary": "httpbin",
147
+ "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
148
+ "startup": "enabled",
149
+ "environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
150
+ }
151
+ },
152
+ }
153
+ assert expected_plan == updated_plan
154
+ assert (
155
+ state_out.get_container(container.name).service_statuses["httpbin"]
156
+ == ops.pebble.ServiceStatus.ACTIVE
157
+ )
158
+ assert state_out.unit_status == testing.ActiveStatus()
171
159
  ```
172
160
 
173
- > See more: [`ops.testing.Harness`](https://ops.readthedocs.io/en/latest/#ops.testing.Harness)
161
+ > See more: [`ops.testing`](https://ops.readthedocs.io/en/latest/reference/ops-testing.html)
174
162
 
175
163
 
176
164
  Explore further, start editing the files, or skip ahead and pack the charm:
@@ -86,46 +86,48 @@ class OpsExampleCharm(ops.CharmBase):
86
86
  self.unit.status = ops.ActiveStatus()
87
87
  ```
88
88
 
89
- > See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/index.html#ops.PebbleReadyEvent)
89
+ > See more: [`ops.PebbleReadyEvent`](https://ops.readthedocs.io/en/latest/reference/ops.html#ops.PebbleReadyEvent)
90
90
 
91
- - The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a testing harness:
91
+ - The `tests/unit/test_charm.py` file imports `ops.testing` and uses it to set up a unit test:
92
92
 
93
93
  ```python
94
- import ops.testing
95
-
96
- class TestCharm(unittest.TestCase):
97
- def setUp(self):
98
- self.harness = ops.testing.Harness(OpsExampleCharm)
99
- self.addCleanup(self.harness.cleanup)
100
- self.harness.begin()
101
-
102
- def test_httpbin_pebble_ready(self):
103
- # Expected plan after Pebble ready with default config
104
- expected_plan = {
105
- "services": {
106
- "httpbin": {
107
- "override": "replace",
108
- "summary": "httpbin",
109
- "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
110
- "startup": "enabled",
111
- "environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
112
- }
113
- },
114
- }
115
- # Simulate the container coming up and emission of pebble-ready event
116
- self.harness.container_pebble_ready("httpbin")
117
- # Get the plan now we've run PebbleReady
118
- updated_plan = self.harness.get_container_pebble_plan("httpbin").to_dict()
119
- # Check we've got the plan we expected
120
- self.assertEqual(expected_plan, updated_plan)
121
- # Check the service was started
122
- service = self.harness.model.unit.get_container("httpbin").get_service("httpbin")
123
- self.assertTrue(service.is_running())
124
- # Ensure we set an ActiveStatus with no message
125
- self.assertEqual(self.harness.model.unit.status, ops.ActiveStatus())
94
+ import ops
95
+ from ops import testing
96
+
97
+ from charm import OpsExampleCharm
98
+
99
+
100
+ def test_httpbin_pebble_ready():
101
+ # Arrange:
102
+ ctx = testing.Context(OpsExampleCharm)
103
+ container = testing.Container("httpbin", can_connect=True)
104
+ state_in = testing.State(containers={container})
105
+
106
+ # Act:
107
+ state_out = ctx.run(ctx.on.pebble_ready(container), state_in)
108
+
109
+ # Assert:
110
+ updated_plan = state_out.get_container(container.name).plan
111
+ expected_plan = {
112
+ "services": {
113
+ "httpbin": {
114
+ "override": "replace",
115
+ "summary": "httpbin",
116
+ "command": "gunicorn -b 0.0.0.0:80 httpbin:app -k gevent",
117
+ "startup": "enabled",
118
+ "environment": {"GUNICORN_CMD_ARGS": "--log-level info"},
119
+ }
120
+ },
121
+ }
122
+ assert expected_plan == updated_plan
123
+ assert (
124
+ state_out.get_container(container.name).service_statuses["httpbin"]
125
+ == ops.pebble.ServiceStatus.ACTIVE
126
+ )
127
+ assert state_out.unit_status == testing.ActiveStatus()
126
128
  ```
127
129
 
128
- > See more: [`ops.testing.Harness`](https://ops.readthedocs.io/en/latest/#ops.testing.Harness)
130
+ > See more: [`ops.testing`](https://ops.readthedocs.io/en/latest/reference/ops-testing.html)
129
131
 
130
132
 
131
133
  Explore further, start editing the files, or skip ahead and pack the charm: