bitexoft-verify 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/.gitignore +2 -0
  2. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/PKG-INFO +9 -3
  3. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/README.md +8 -2
  4. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/__init__.py +1 -1
  5. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/checks/a1.py +11 -0
  6. bitexoft_verify-0.3.0/src/bitexoft_verify/checks/a2.py +602 -0
  7. bitexoft_verify-0.3.0/src/bitexoft_verify/checks/a2_design.py +157 -0
  8. bitexoft_verify-0.3.0/src/bitexoft_verify/checks/assertions.py +129 -0
  9. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/checks/common.py +99 -18
  10. bitexoft_verify-0.3.0/src/bitexoft_verify/checks/execution.py +199 -0
  11. bitexoft_verify-0.3.0/src/bitexoft_verify/checks/isolated.py +138 -0
  12. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/cli.py +35 -8
  13. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/codes.py +6 -0
  14. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/data/README.md +3 -0
  15. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/data/issue-codes.json +19 -0
  16. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/report.py +57 -7
  17. bitexoft_verify-0.3.0/src/bitexoft_verify/runner.py +137 -0
  18. bitexoft_verify-0.3.0/src/bitexoft_verify/seeds.py +43 -0
  19. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/test_a1.py +90 -1
  20. bitexoft_verify-0.3.0/tests/test_a1_benign.py +309 -0
  21. bitexoft_verify-0.3.0/tests/test_a2.py +521 -0
  22. bitexoft_verify-0.3.0/tests/test_assertions.py +96 -0
  23. bitexoft_verify-0.3.0/tests/test_check_errors.py +70 -0
  24. bitexoft_verify-0.3.0/tests/test_execution.py +86 -0
  25. bitexoft_verify-0.3.0/tests/test_isolated.py +145 -0
  26. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/test_issues.py +11 -2
  27. bitexoft_verify-0.3.0/tests/test_parity.py +106 -0
  28. bitexoft_verify-0.3.0/tests/test_projects.py +119 -0
  29. bitexoft_verify-0.3.0/tests/test_report_v4.py +98 -0
  30. bitexoft_verify-0.3.0/tests/test_sample_files.py +61 -0
  31. bitexoft_verify-0.3.0/tests/test_seeds.py +107 -0
  32. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tools/make_fixtures.py +2 -0
  33. bitexoft_verify-0.2.0/src/bitexoft_verify/runner.py +0 -101
  34. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/pyproject.toml +0 -0
  35. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/__main__.py +0 -0
  36. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/checks/__init__.py +0 -0
  37. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/data/a1_impossible_sample.csv +0 -0
  38. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/data/a1_match_sample.csv +0 -0
  39. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/data/a2_isolated_sample.csv +0 -0
  40. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/src/bitexoft_verify/manifest.py +0 -0
  41. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/conftest.py +0 -0
  42. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/golden/a1_checks.json +0 -0
  43. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/test_equivalence.py +0 -0
  44. {bitexoft_verify-0.2.0 → bitexoft_verify-0.3.0}/tests/test_version.py +0 -0
@@ -11,12 +11,14 @@ __pycache__/
11
11
 
12
12
  # generated
13
13
  app/dist/
14
+ app/shots/
14
15
  dist/
15
16
  build/
16
17
  app/src/content/catalog.json
17
18
  app/src/content/briefs.json
18
19
  app/src/content/glossary-detail.json
19
20
  app/src/content/check-feedback.json
21
+ app/public/media/
20
22
  verify-report.json
21
23
  coverage/
22
24
  htmlcov/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: bitexoft-verify
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Verifica las entregas de los proyectos de Bitexoft: la misma herramienta en tu máquina y en CI.
5
5
  Author: Bitexoft
6
6
  License: Proprietary
@@ -128,12 +128,18 @@ First release, by hand on pypi.org:
128
128
  repository `sports-lab-v1`, workflow `release-verify.yml`, environment `pypi`.
129
129
  2. In the repository settings, create the environment `pypi`.
130
130
 
131
- Each release:
131
+ Each release (`<version>` is `__version__`; 0.3.0 is the first that knows A2, and the workflow pin `0.3.*` waits for it):
132
132
 
133
133
  ```bash
134
- git tag verify-v0.2.0 && git push origin verify-v0.2.0
134
+ git tag verify-v<version> && git push origin verify-v<version>
135
135
  ```
136
136
 
137
137
  The workflow runs `pytest` on 3.10 and 3.12, refuses a tag that differs from `__version__`, builds
138
138
  with `python -m build` and publishes with trusted publishing (no tokens). Check it in a clean
139
139
  environment: `pipx run --spec bitexoft-verify bitexoft-verify deliveries`.
140
+
141
+ After the release, in this order (the workflow pins `==0.3.*`, so publishing it before the version exists on PyPI breaks every learner's CI):
142
+
143
+ 1. Check PyPI from a clean environment: `pipx run --spec "bitexoft-verify==<version>" bitexoft-verify deliveries` lists the deliveries the version can verify.
144
+ 2. Publish the reusable workflow and move its `v1` tag: `scripts/publish-verify-workflow.sh` (it asks before moving the tag).
145
+ 3. Run the whole path once as a learner: a repository made from the template, `delivery: A2` in its workflow, CI green on a correct solution.
@@ -105,12 +105,18 @@ First release, by hand on pypi.org:
105
105
  repository `sports-lab-v1`, workflow `release-verify.yml`, environment `pypi`.
106
106
  2. In the repository settings, create the environment `pypi`.
107
107
 
108
- Each release:
108
+ Each release (`<version>` is `__version__`; 0.3.0 is the first that knows A2, and the workflow pin `0.3.*` waits for it):
109
109
 
110
110
  ```bash
111
- git tag verify-v0.2.0 && git push origin verify-v0.2.0
111
+ git tag verify-v<version> && git push origin verify-v<version>
112
112
  ```
113
113
 
114
114
  The workflow runs `pytest` on 3.10 and 3.12, refuses a tag that differs from `__version__`, builds
115
115
  with `python -m build` and publishes with trusted publishing (no tokens). Check it in a clean
116
116
  environment: `pipx run --spec bitexoft-verify bitexoft-verify deliveries`.
117
+
118
+ After the release, in this order (the workflow pins `==0.3.*`, so publishing it before the version exists on PyPI breaks every learner's CI):
119
+
120
+ 1. Check PyPI from a clean environment: `pipx run --spec "bitexoft-verify==<version>" bitexoft-verify deliveries` lists the deliveries the version can verify.
121
+ 2. Publish the reusable workflow and move its `v1` tag: `scripts/publish-verify-workflow.sh` (it asks before moving the tag).
122
+ 3. Run the whole path once as a learner: a repository made from the template, `delivery: A2` in its workflow, CI green on a correct solution.
@@ -1,3 +1,3 @@
1
1
  """bitexoft-verify: the platform's only definition of "correct"."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.3.0"
@@ -24,6 +24,7 @@ from .common import (
24
24
  check_symbol,
25
25
  check_tests_cover_invariants,
26
26
  check_tests_pass,
27
+ guarded,
27
28
  import_symbol,
28
29
  )
29
30
 
@@ -51,6 +52,7 @@ def _domain_error(ctx: Context):
51
52
  return _domain(ctx, "<layers.domain>.errors:DomainError")
52
53
 
53
54
 
55
+ @guarded("position_invariants", "Position refuses coordinates off the pitch")
54
56
  def check_position_rejects_impossible(ctx: Context) -> Check:
55
57
  title = "Position refuses coordinates off the pitch"
56
58
  try:
@@ -94,6 +96,7 @@ def check_position_rejects_impossible(ctx: Context) -> Check:
94
96
  return Check("position_invariants", title, "pass")
95
97
 
96
98
 
99
+ @guarded("frame_invariants", "Frame refuses impossible instants")
97
100
  def check_frame_rejects_impossible(ctx: Context) -> Check:
98
101
  title = "Frame refuses impossible instants"
99
102
  try:
@@ -125,6 +128,7 @@ def check_frame_rejects_impossible(ctx: Context) -> Check:
125
128
  return Check("frame_invariants", title, "pass")
126
129
 
127
130
 
131
+ @guarded("value_semantics", "Compared by value, hashable and immutable")
128
132
  def check_value_semantics(ctx: Context) -> Check:
129
133
  title = "Compared by value, hashable and immutable"
130
134
  try:
@@ -195,6 +199,7 @@ def _line_frame(ctx: Context, step: float):
195
199
  return Frame(t=0.0, players=players, ball=Position(x=cx, y=cy))
196
200
 
197
201
 
202
+ @guarded("geometry", "The centroid and the spread are right")
198
203
  def check_geometry(ctx: Context) -> Check:
199
204
  title = "The centroid and the spread are right"
200
205
  try:
@@ -207,6 +212,8 @@ def check_geometry(ctx: Context) -> Check:
207
212
  centre = getattr(square, "centroid", None)
208
213
  if centre is None:
209
214
  problems.append("Frame has no centroid")
215
+ elif callable(centre):
216
+ problems.append("Frame.centroid is a method; the contract asks for a property (add @property)")
210
217
  elif abs(centre.x - PITCH_LENGTH_M / 2) > 1e-6 or abs(centre.y - PITCH_WIDTH_M / 2) > 1e-6:
211
218
  problems.append(f"the centroid of a centred square is not the centre ({centre.x}, {centre.y})")
212
219
 
@@ -229,6 +236,7 @@ def check_geometry(ctx: Context) -> Check:
229
236
  return Check("geometry", title, "pass")
230
237
 
231
238
 
239
+ @guarded("classification", "Classification is monotonic and reaches all three states")
232
240
  def check_classification(ctx: Context) -> Check:
233
241
  title = "Classification is monotonic and reaches all three states"
234
242
  try:
@@ -265,6 +273,7 @@ def check_classification(ctx: Context) -> Check:
265
273
  return Check("classification", title, "pass")
266
274
 
267
275
 
276
+ @guarded("thresholds", "BlockCompactness refuses thresholds that make no sense")
268
277
  def check_thresholds_are_validated(ctx: Context) -> Check:
269
278
  title = "BlockCompactness refuses thresholds that make no sense"
270
279
  try:
@@ -283,6 +292,7 @@ def check_thresholds_are_validated(ctx: Context) -> Check:
283
292
  )
284
293
 
285
294
 
295
+ @guarded("cli_analyze", "The program analyses the sample file")
286
296
  def check_cli_analyses_fixture(ctx: Context) -> Check:
287
297
  title = "The program analyses the sample file"
288
298
  try:
@@ -303,6 +313,7 @@ def check_cli_analyses_fixture(ctx: Context) -> Check:
303
313
  return Check("cli_analyze", title, "pass")
304
314
 
305
315
 
316
+ @guarded("cli_bad_input", "With impossible data it fails cleanly, without a traceback")
306
317
  def check_cli_fails_cleanly(ctx: Context) -> Check:
307
318
  title = "With impossible data it fails cleanly, without a traceback"
308
319
  try: