corio 2.3.0__tar.gz → 2.3.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 (171) hide show
  1. {corio-2.3.0 → corio-2.3.2}/PKG-INFO +5 -1
  2. {corio-2.3.0 → corio-2.3.2}/corio/infra/api.py +1 -2
  3. {corio-2.3.0 → corio-2.3.2}/corio/infra/releaser.py +72 -27
  4. {corio-2.3.0 → corio-2.3.2}/corio/infra/repository.py +34 -0
  5. {corio-2.3.0 → corio-2.3.2}/corio/pyproject.package.toml +27 -27
  6. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_infra.py +118 -1
  7. corio-2.3.2/corio/version/__init__.py +14 -0
  8. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/PKG-INFO +5 -1
  9. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/requires.txt +4 -0
  10. {corio-2.3.0 → corio-2.3.2}/pyproject.toml +27 -27
  11. corio-2.3.0/corio/version/__init__.py +0 -7
  12. {corio-2.3.0 → corio-2.3.2}/LICENSE +0 -0
  13. {corio-2.3.0 → corio-2.3.2}/README.md +0 -0
  14. {corio-2.3.0 → corio-2.3.2}/corio/__init__.py +0 -0
  15. {corio-2.3.0 → corio-2.3.2}/corio/ai/__init__.py +0 -0
  16. {corio-2.3.0 → corio-2.3.2}/corio/ai/agentic.py +0 -0
  17. {corio-2.3.0 → corio-2.3.2}/corio/ai/infer.py +0 -0
  18. {corio-2.3.0 → corio-2.3.2}/corio/aio.py +0 -0
  19. {corio-2.3.0 → corio-2.3.2}/corio/api.py +0 -0
  20. {corio-2.3.0 → corio-2.3.2}/corio/augmentation.py +0 -0
  21. {corio-2.3.0 → corio-2.3.2}/corio/av.py +0 -0
  22. {corio-2.3.0 → corio-2.3.2}/corio/caching.py +0 -0
  23. {corio-2.3.0 → corio-2.3.2}/corio/constants.py +0 -0
  24. {corio-2.3.0 → corio-2.3.2}/corio/context.py +0 -0
  25. {corio-2.3.0 → corio-2.3.2}/corio/dataclass.py +0 -0
  26. {corio-2.3.0 → corio-2.3.2}/corio/datatype.py +0 -0
  27. {corio-2.3.0 → corio-2.3.2}/corio/db/__init__.py +0 -0
  28. {corio-2.3.0 → corio-2.3.2}/corio/db/document.py +0 -0
  29. {corio-2.3.0 → corio-2.3.2}/corio/debug.py +0 -0
  30. {corio-2.3.0 → corio-2.3.2}/corio/dm.py +0 -0
  31. {corio-2.3.0 → corio-2.3.2}/corio/dns/__init__.py +0 -0
  32. {corio-2.3.0 → corio-2.3.2}/corio/dns/client.py +0 -0
  33. {corio-2.3.0 → corio-2.3.2}/corio/dns/dm.py +0 -0
  34. {corio-2.3.0 → corio-2.3.2}/corio/dns/proxy.py +0 -0
  35. {corio-2.3.0 → corio-2.3.2}/corio/dns/server.py +0 -0
  36. {corio-2.3.0 → corio-2.3.2}/corio/docker/__init__.py +0 -0
  37. {corio-2.3.0 → corio-2.3.2}/corio/dt.py +0 -0
  38. {corio-2.3.0 → corio-2.3.2}/corio/encrypt.py +0 -0
  39. {corio-2.3.0 → corio-2.3.2}/corio/entrypoint.py +0 -0
  40. {corio-2.3.0 → corio-2.3.2}/corio/env.py +0 -0
  41. {corio-2.3.0 → corio-2.3.2}/corio/function.py +0 -0
  42. {corio-2.3.0 → corio-2.3.2}/corio/google_api.py +0 -0
  43. {corio-2.3.0 → corio-2.3.2}/corio/ha/__init__.py +0 -0
  44. {corio-2.3.0 → corio-2.3.2}/corio/ha/constants.py +0 -0
  45. {corio-2.3.0 → corio-2.3.2}/corio/ha/core.py +0 -0
  46. {corio-2.3.0 → corio-2.3.2}/corio/ha/supervisor.py +0 -0
  47. {corio-2.3.0 → corio-2.3.2}/corio/ha/utils.py +0 -0
  48. {corio-2.3.0 → corio-2.3.2}/corio/hash.py +0 -0
  49. {corio-2.3.0 → corio-2.3.2}/corio/hfh.py +0 -0
  50. {corio-2.3.0 → corio-2.3.2}/corio/hook.py +0 -0
  51. {corio-2.3.0 → corio-2.3.2}/corio/https.py +0 -0
  52. {corio-2.3.0 → corio-2.3.2}/corio/infra/__init__.py +0 -0
  53. {corio-2.3.0 → corio-2.3.2}/corio/infra/incrementor_pyproject.py +0 -0
  54. {corio-2.3.0 → corio-2.3.2}/corio/infra/project.py +0 -0
  55. {corio-2.3.0 → corio-2.3.2}/corio/infra/stack.py +0 -0
  56. {corio-2.3.0 → corio-2.3.2}/corio/inherit.py +0 -0
  57. {corio-2.3.0 → corio-2.3.2}/corio/inspection.py +0 -0
  58. {corio-2.3.0 → corio-2.3.2}/corio/interface/__init__.py +0 -0
  59. {corio-2.3.0 → corio-2.3.2}/corio/interface/context.py +0 -0
  60. {corio-2.3.0 → corio-2.3.2}/corio/interface/controls.py +0 -0
  61. {corio-2.3.0 → corio-2.3.2}/corio/interface/interface.py +0 -0
  62. {corio-2.3.0 → corio-2.3.2}/corio/iterator.py +0 -0
  63. {corio-2.3.0 → corio-2.3.2}/corio/jsn.py +0 -0
  64. {corio-2.3.0 → corio-2.3.2}/corio/json_fix.py +0 -0
  65. {corio-2.3.0 → corio-2.3.2}/corio/logs.py +0 -0
  66. {corio-2.3.0 → corio-2.3.2}/corio/markup.py +0 -0
  67. {corio-2.3.0 → corio-2.3.2}/corio/merging.py +0 -0
  68. {corio-2.3.0 → corio-2.3.2}/corio/metric.py +0 -0
  69. {corio-2.3.0 → corio-2.3.2}/corio/mqtt.py +0 -0
  70. {corio-2.3.0 → corio-2.3.2}/corio/name.py +0 -0
  71. {corio-2.3.0 → corio-2.3.2}/corio/net.py +0 -0
  72. {corio-2.3.0 → corio-2.3.2}/corio/netrc.py +0 -0
  73. {corio-2.3.0 → corio-2.3.2}/corio/openai.py +0 -0
  74. {corio-2.3.0 → corio-2.3.2}/corio/parallel.py +0 -0
  75. {corio-2.3.0 → corio-2.3.2}/corio/path/__init__.py +0 -0
  76. {corio-2.3.0 → corio-2.3.2}/corio/path/app.py +0 -0
  77. {corio-2.3.0 → corio-2.3.2}/corio/path/path.py +0 -0
  78. {corio-2.3.0 → corio-2.3.2}/corio/path/type.py +0 -0
  79. {corio-2.3.0 → corio-2.3.2}/corio/paths.py +0 -0
  80. {corio-2.3.0 → corio-2.3.2}/corio/patterns.py +0 -0
  81. {corio-2.3.0 → corio-2.3.2}/corio/pdf.py +0 -0
  82. {corio-2.3.0 → corio-2.3.2}/corio/plat.py +0 -0
  83. {corio-2.3.0 → corio-2.3.2}/corio/process.py +0 -0
  84. {corio-2.3.0 → corio-2.3.2}/corio/profiling.py +0 -0
  85. {corio-2.3.0 → corio-2.3.2}/corio/rand.py +0 -0
  86. {corio-2.3.0 → corio-2.3.2}/corio/sec.py +0 -0
  87. {corio-2.3.0 → corio-2.3.2}/corio/semantic.py +0 -0
  88. {corio-2.3.0 → corio-2.3.2}/corio/sets.py +0 -0
  89. {corio-2.3.0 → corio-2.3.2}/corio/setup/__init__.py +0 -0
  90. {corio-2.3.0 → corio-2.3.2}/corio/spaces.py +0 -0
  91. {corio-2.3.0 → corio-2.3.2}/corio/strings.py +0 -0
  92. {corio-2.3.0 → corio-2.3.2}/corio/tabular.py +0 -0
  93. {corio-2.3.0 → corio-2.3.2}/corio/tests/__init__.py +0 -0
  94. {corio-2.3.0 → corio-2.3.2}/corio/tests/conftest.py +0 -0
  95. {corio-2.3.0 → corio-2.3.2}/corio/tests/helpers.py +0 -0
  96. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_caching.py +0 -0
  97. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_datatype.py +0 -0
  98. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_dns.py +0 -0
  99. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_dt.py +0 -0
  100. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_encrypt.py +0 -0
  101. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_env.py +0 -0
  102. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_hash.py +0 -0
  103. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_hook.py +0 -0
  104. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_iterator.py +0 -0
  105. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_jsn.py +0 -0
  106. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_name.py +0 -0
  107. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_path.py +0 -0
  108. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_patterns.py +0 -0
  109. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_rand.py +0 -0
  110. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_strings.py +0 -0
  111. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_toml.py +0 -0
  112. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_tools.py +0 -0
  113. {corio-2.3.0 → corio-2.3.2}/corio/tests/test_yml.py +0 -0
  114. {corio-2.3.0 → corio-2.3.2}/corio/tokenization.py +0 -0
  115. {corio-2.3.0 → corio-2.3.2}/corio/toml.py +0 -0
  116. {corio-2.3.0 → corio-2.3.2}/corio/tools.py +0 -0
  117. {corio-2.3.0 → corio-2.3.2}/corio/unicode.py +0 -0
  118. {corio-2.3.0 → corio-2.3.2}/corio/version/version.py +0 -0
  119. {corio-2.3.0 → corio-2.3.2}/corio/webhook.py +0 -0
  120. {corio-2.3.0 → corio-2.3.2}/corio/yml.py +0 -0
  121. {corio-2.3.0 → corio-2.3.2}/corio/youtube.py +0 -0
  122. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/SOURCES.txt +0 -0
  123. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/dependency_links.txt +0 -0
  124. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/entry_points.txt +0 -0
  125. {corio-2.3.0 → corio-2.3.2}/corio.egg-info/top_level.txt +0 -0
  126. {corio-2.3.0 → corio-2.3.2}/scripts/add-service +0 -0
  127. {corio-2.3.0 → corio-2.3.2}/scripts/add-user-path +0 -0
  128. {corio-2.3.0 → corio-2.3.2}/scripts/add-ve-shell +0 -0
  129. {corio-2.3.0 → corio-2.3.2}/scripts/apt-essentials +0 -0
  130. {corio-2.3.0 → corio-2.3.2}/scripts/apt-headless +0 -0
  131. {corio-2.3.0 → corio-2.3.2}/scripts/auth-token +0 -0
  132. {corio-2.3.0 → corio-2.3.2}/scripts/compose-update +0 -0
  133. {corio-2.3.0 → corio-2.3.2}/scripts/compress-dir +0 -0
  134. {corio-2.3.0 → corio-2.3.2}/scripts/cru +0 -0
  135. {corio-2.3.0 → corio-2.3.2}/scripts/docker-build-bases +0 -0
  136. {corio-2.3.0 → corio-2.3.2}/scripts/docker-build-bases-dev +0 -0
  137. {corio-2.3.0 → corio-2.3.2}/scripts/docker-install-deps +0 -0
  138. {corio-2.3.0 → corio-2.3.2}/scripts/docker-install-prod +0 -0
  139. {corio-2.3.0 → corio-2.3.2}/scripts/docker-prune +0 -0
  140. {corio-2.3.0 → corio-2.3.2}/scripts/docker-sandbox +0 -0
  141. {corio-2.3.0 → corio-2.3.2}/scripts/docker-sandbox-init +0 -0
  142. {corio-2.3.0 → corio-2.3.2}/scripts/docs-deploy +0 -0
  143. {corio-2.3.0 → corio-2.3.2}/scripts/download +0 -0
  144. {corio-2.3.0 → corio-2.3.2}/scripts/encrypt-secrets +0 -0
  145. {corio-2.3.0 → corio-2.3.2}/scripts/fmtr-test-script +0 -0
  146. {corio-2.3.0 → corio-2.3.2}/scripts/git-clone +0 -0
  147. {corio-2.3.0 → corio-2.3.2}/scripts/ha-addon-launch +0 -0
  148. {corio-2.3.0 → corio-2.3.2}/scripts/infra +0 -0
  149. {corio-2.3.0 → corio-2.3.2}/scripts/install-browser +0 -0
  150. {corio-2.3.0 → corio-2.3.2}/scripts/install-docker +0 -0
  151. {corio-2.3.0 → corio-2.3.2}/scripts/install-ts +0 -0
  152. {corio-2.3.0 → corio-2.3.2}/scripts/install-ys +0 -0
  153. {corio-2.3.0 → corio-2.3.2}/scripts/mirror-dir +0 -0
  154. {corio-2.3.0 → corio-2.3.2}/scripts/opt-dev-init +0 -0
  155. {corio-2.3.0 → corio-2.3.2}/scripts/parse-args +0 -0
  156. {corio-2.3.0 → corio-2.3.2}/scripts/pypi-check +0 -0
  157. {corio-2.3.0 → corio-2.3.2}/scripts/pypi-reserve +0 -0
  158. {corio-2.3.0 → corio-2.3.2}/scripts/run-script +0 -0
  159. {corio-2.3.0 → corio-2.3.2}/scripts/run-tests +0 -0
  160. {corio-2.3.0 → corio-2.3.2}/scripts/set-password +0 -0
  161. {corio-2.3.0 → corio-2.3.2}/scripts/set-secure-path +0 -0
  162. {corio-2.3.0 → corio-2.3.2}/scripts/set-user-sudo +0 -0
  163. {corio-2.3.0 → corio-2.3.2}/scripts/snips-install +0 -0
  164. {corio-2.3.0 → corio-2.3.2}/scripts/ssh-auth +0 -0
  165. {corio-2.3.0 → corio-2.3.2}/scripts/ssh-serve +0 -0
  166. {corio-2.3.0 → corio-2.3.2}/scripts/tasmota-config +0 -0
  167. {corio-2.3.0 → corio-2.3.2}/scripts/tasmota-flash +0 -0
  168. {corio-2.3.0 → corio-2.3.2}/scripts/tasmota-terminal +0 -0
  169. {corio-2.3.0 → corio-2.3.2}/scripts/vlc-tn +0 -0
  170. {corio-2.3.0 → corio-2.3.2}/scripts/vm-launch +0 -0
  171. {corio-2.3.0 → corio-2.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: corio
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
5
5
  Author-email: Frontmatter AI <innovative.fowler@mask.pro.fmtr.dev>
6
6
  License-Expression: Apache-2.0
@@ -41,9 +41,11 @@ Requires-Dist: pyrage; extra == "dev"
41
41
  Requires-Dist: dotenv; extra == "dev"
42
42
  Requires-Dist: pytest; extra == "dev"
43
43
  Requires-Dist: pytest-cov; extra == "dev"
44
+ Requires-Dist: pytest-asyncio; extra == "dev"
44
45
  Provides-Extra: test
45
46
  Requires-Dist: pytest; extra == "test"
46
47
  Requires-Dist: pytest-cov; extra == "test"
48
+ Requires-Dist: pytest-asyncio; extra == "test"
47
49
  Provides-Extra: yml
48
50
  Requires-Dist: yamlscript; extra == "yml"
49
51
  Requires-Dist: pyyaml; extra == "yml"
@@ -268,6 +270,7 @@ Requires-Dist: pyrage; extra == "infra"
268
270
  Requires-Dist: dotenv; extra == "infra"
269
271
  Requires-Dist: pytest; extra == "infra"
270
272
  Requires-Dist: pytest-cov; extra == "infra"
273
+ Requires-Dist: pytest-asyncio; extra == "infra"
271
274
  Provides-Extra: vcs
272
275
  Requires-Dist: pygit2; extra == "vcs"
273
276
  Provides-Extra: tasmota
@@ -328,6 +331,7 @@ Requires-Dist: pyrage; extra == "all"
328
331
  Requires-Dist: dotenv; extra == "all"
329
332
  Requires-Dist: pytest; extra == "all"
330
333
  Requires-Dist: pytest-cov; extra == "all"
334
+ Requires-Dist: pytest-asyncio; extra == "all"
331
335
  Requires-Dist: dask[bag]; extra == "all"
332
336
  Requires-Dist: distributed; extra == "all"
333
337
  Requires-Dist: bokeh; extra == "all"
@@ -39,11 +39,10 @@ class Api(api.Base):
39
39
  self,
40
40
  name: str,
41
41
  pinned: str = None,
42
- increment: bool = True,
43
42
  build: bool = False,
44
43
  release: bool = True,
45
44
  cache: bool = True,
46
45
  ):
47
46
  project = Project(name, pinned=pinned)
48
47
 
49
- project.releaser.run(increment=increment, build=build, release=release, cache=cache)
48
+ project.releaser.run(build=build, release=release, cache=cache)
@@ -40,13 +40,12 @@ class Releaser(Inherit[Project]):
40
40
  """
41
41
 
42
42
  @logger.instrument("Releasing {self.paths.name_ns}...")
43
- def run(self, increment: bool = True, build: bool = False, release: bool = True, cache: bool = True):
43
+ def run(self, build: bool = False, release: bool = True, cache: bool = True):
44
44
 
45
45
  from corio.infra.stack import ProductionPrivate, ProductionPublic
46
46
 
47
- if increment:
48
- self.repo.fetch()
49
- self.increment()
47
+ self.repo.fetch()
48
+ self.increment()
50
49
 
51
50
  is_passed = self.tester.run()
52
51
  if not is_passed:
@@ -55,9 +54,9 @@ class Releaser(Inherit[Project]):
55
54
  else:
56
55
  raise RuntimeError("Tests failed. Aborting release.")
57
56
 
58
- if increment:
59
- self.repo.push()
60
- self.repo.fetch()
57
+ self.commit()
58
+ self.repo.push()
59
+ self.repo.fetch()
61
60
 
62
61
  stack_types = []
63
62
  if build:
@@ -78,22 +77,28 @@ class Releaser(Inherit[Project]):
78
77
  def message(self):
79
78
  return f"Release version {self.version}"
80
79
 
81
- @logger.instrument("Incrementing version numbers {self.repo.origin.url}...")
82
- def increment(self):
83
- """
84
-
85
- Increment version numbers in project files, create a new commit, and rebase the release branch.
86
-
87
- """
88
- repo = self.repo
80
+ @cached_property
81
+ def main_ref(self):
82
+ return self.repo.lookup_reference("refs/heads/main")
89
83
 
90
- main_ref = repo.lookup_reference("refs/heads/main") # todo raise if not main?
91
- parent = main_ref.peel(vcs.Commit)
84
+ @cached_property
85
+ def parent_commit(self):
86
+ return self.main_ref.peel(vcs.Commit)
92
87
 
88
+ @cached_property
89
+ def index(self):
90
+ index = self.repo.index
93
91
  # Make sure we're building on main's HEAD (not whatever HEAD currently is).
94
- index = repo.index
95
- index.read_tree(parent.tree)
92
+ index.read_tree(self.parent_commit.tree)
93
+ return index
94
+
95
+ @logger.instrument("Applying version incrementors {self.repo.origin.url}...")
96
+ def increment(self):
97
+ """
96
98
 
99
+ Apply incrementors and stage changed files.
100
+
101
+ """
97
102
  # Apply incrementors (they edit files in the working tree), then stage results.
98
103
  for incrementor in self.incrementors:
99
104
  paths = incrementor.apply()
@@ -104,18 +109,22 @@ class Releaser(Inherit[Project]):
104
109
 
105
110
  for path in paths:
106
111
  rel = str(Path(path).relative_to(self.paths.repo))
107
- index.add(rel)
112
+ self.index.add(rel)
108
113
 
109
- index.write()
110
- tree = index.write_tree(repo)
114
+ self.index.write()
115
+
116
+ @logger.instrument("Committing release changes {self.repo.origin.url}...")
117
+ def commit(self):
118
+ repo = self.repo
119
+ tree = self.index.write_tree(repo)
111
120
 
112
121
  commit_id = repo.create_commit(
113
- main_ref.name,
122
+ self.main_ref.name,
114
123
  repo.default_signature,
115
124
  repo.default_signature,
116
125
  self.message,
117
126
  tree,
118
- [parent.id],
127
+ [self.parent_commit.id],
119
128
  )
120
129
 
121
130
  try:
@@ -218,8 +227,28 @@ class IncrementorVersion(Incrementor):
218
227
  @logger.instrument('Incrementing release version in-memory for "{self.paths.name_ns}"...')
219
228
  def apply(self) -> Path | list[Path] | None:
220
229
  old = self.versions.old
230
+
231
+ old_tag = f"v{old}"
232
+ has_old_tag = old_tag in self.repo.tags.all
233
+
221
234
  if self.versions.pinned:
222
235
  new = self.versions.pinned
236
+ if not has_old_tag and new != old:
237
+ logger.warning(
238
+ f'Current version tag "{old_tag}" was not found. '
239
+ f'Using pinned version "{new}" and continuing.'
240
+ )
241
+ elif not has_old_tag:
242
+ logger.warning(
243
+ f'Current version tag "{old_tag}" was not found. '
244
+ f'Assuming previous release failed and reusing version "{new}".'
245
+ )
246
+ elif not has_old_tag:
247
+ logger.warning(
248
+ f'Current version tag "{old_tag}" was not found. '
249
+ f'Assuming previous release failed and reusing version "{old}".'
250
+ )
251
+ new = old
223
252
  elif old.prerelease:
224
253
  new = old.bump_prerelease()
225
254
  else:
@@ -370,17 +399,33 @@ class ReleaseGithub(Release):
370
399
 
371
400
  """
372
401
 
402
+ @cached_property
403
+ def previous_version(self):
404
+ return self.repo.get_most_recent_release_tag(
405
+ include_pre=self.versions.is_pre,
406
+ before=self.version,
407
+ )
408
+
409
+ @property
410
+ def previous_tag(self):
411
+ if not self.previous_version:
412
+ return None
413
+ return self.previous_version.tag
414
+
373
415
  @property
374
416
  def url(self):
375
- return f"{self.repo_url}/compare/v{self.versions.old}...v{self.versions.new}"
417
+ if not self.previous_tag:
418
+ return None
419
+ return f"{self.repo_url}/compare/{self.previous_tag}...{self.tag}"
376
420
 
377
421
  @property
378
422
  def body(self):
379
423
  path_changelog = self.incrementors.cls[IncrementorChangelog].dest
380
424
  if path_changelog.exists():
381
425
  return path_changelog.read_text()
382
- else:
383
- return f'**Full Changelog**: [{self.versions.old} {Constants.ARROW_RIGHT} {self.versions.new}]({self.url})'
426
+ if not self.previous_version:
427
+ return None
428
+ return f'**Full Changelog**: [{self.previous_tag} {Constants.ARROW_RIGHT} {self.tag}]({self.url})'
384
429
 
385
430
  def release(self):
386
431
  url = f"{self.repo_api_url}/releases"
@@ -2,6 +2,7 @@ import pygit2 as vcs
2
2
  from functools import cached_property
3
3
  from typing import Any
4
4
 
5
+ from corio import version
5
6
  from corio.inherit import Inherit
6
7
  from corio.logs import logger
7
8
  from corio.path import Path
@@ -61,6 +62,39 @@ class Repository(vcs.Repository):
61
62
 
62
63
  return self.origin.push(specs, callbacks=self.callbacks)
63
64
 
65
+ def get_most_recent_release_tag(self, include_pre: bool = True, before=None):
66
+ before_version = None
67
+ if before is not None:
68
+ if isinstance(before, str):
69
+ before = before.removeprefix("v")
70
+ before_version = version.parse(before)
71
+ else:
72
+ before_version = before
73
+
74
+ candidates = []
75
+ for tag in self.tags.all:
76
+ if not tag.startswith("v"):
77
+ continue
78
+ text = tag.removeprefix("v")
79
+ try:
80
+ parsed = version.parse(text)
81
+ except ValueError:
82
+ continue
83
+
84
+ if before_version is not None and parsed >= before_version:
85
+ continue
86
+
87
+ if not include_pre and parsed.prerelease:
88
+ continue
89
+
90
+ candidates.append(parsed)
91
+
92
+ if not candidates:
93
+ return None
94
+
95
+ candidates.sort(reverse=True)
96
+ return candidates[0]
97
+
64
98
 
65
99
 
66
100
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "corio"
3
- version = "2.3.0"
3
+ version = "2.3.2"
4
4
  description = "Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML"
5
5
  readme = "README.md"
6
6
  dependencies = []
@@ -9,8 +9,8 @@ license-files = ["LICENSE"]
9
9
  keywords = []
10
10
 
11
11
  [project.optional-dependencies]
12
- dev = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov"]
13
- test = ["pytest", "pytest-cov"]
12
+ dev = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov", "pytest-asyncio"]
13
+ test = ["pytest", "pytest-cov", "pytest-asyncio"]
14
14
  yml = ["yamlscript", "pyyaml"]
15
15
  yaml = ["yamlscript", "pyyaml"]
16
16
  logging = ["logfire"]
@@ -64,13 +64,13 @@ ha = ["dotenv"]
64
64
  "ha.api" = ["dotenv", "homeassistant_api", "aiohasupervisor"]
65
65
  doc = ["mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav"]
66
66
  youtube = ["pytubefix"]
67
- infra = ["semver", "logfire", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov"]
67
+ infra = ["semver", "logfire", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov", "pytest-asyncio"]
68
68
  vcs = ["pygit2"]
69
69
  tasmota = ["decode-config", "esptool"]
70
70
  encrypt = ["pyrage"]
71
71
  secrets = ["pyrage", "dotenv", "yamlscript", "pyyaml", "logfire", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "pygit2"]
72
72
  cli = ["pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "logfire"]
73
- all = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov", "dask[bag]", "distributed", "bokeh", "tokenizers", "faker", "sre_yield", "contexttimer", "Unidecode", "tinynetrc", "huggingface_hub", "peft", "transformers[sentencepiece]", "torchvision", "torchaudio", "cuda-bindings==13.2.0", "cuda-pathfinder==1.5.4", "cuda-toolkit==13.0.2", "nvidia-cublas==13.1.0.3", "nvidia-cuda-cupti==13.0.85", "nvidia-cuda-nvrtc==13.0.88", "nvidia-cuda-runtime==13.0.96", "nvidia-cudnn-cu13==9.19.0.56", "nvidia-cufft==12.0.0.61", "nvidia-cufile==1.15.1.6", "nvidia-curand==10.4.0.35", "nvidia-cusolver==12.0.4.66", "nvidia-cusparse==12.6.3.3", "nvidia-cusparselt-cu13==0.8.0", "nvidia-nccl-cu13==2.28.9", "nvidia-nvjitlink==13.0.88", "nvidia-nvshmem-cu13==3.4.5", "nvidia-nvtx==13.0.85", "torch==2.11.0", "triton==3.6.0", "openai", "pydantic-ai-slim[logfire,openai]", "ollama", "json_repair", "sentence_transformers", "pandas", "tabulate", "openpyxl", "odfpy", "deepdiff", "html2text", "flet[all] <0.80.0", "flet-video", "flet-webview", "google-auth", "google-auth-oauthlib", "google-auth-httplib2", "google-api-python-client", "diskcache", "cachetools", "pymupdf", "pymupdf4llm", "appdirs", "filetype", "dnspython[doh]", "regex", "playwright", "aiomqtt", "av", "homeassistant_api", "aiohasupervisor", "pytubefix", "decode-config", "esptool"]
73
+ all = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov", "pytest-asyncio", "dask[bag]", "distributed", "bokeh", "tokenizers", "faker", "sre_yield", "contexttimer", "Unidecode", "tinynetrc", "huggingface_hub", "peft", "transformers[sentencepiece]", "torchvision", "torchaudio", "cuda-bindings==13.2.0", "cuda-pathfinder==1.5.4", "cuda-toolkit==13.0.2", "nvidia-cublas==13.1.0.3", "nvidia-cuda-cupti==13.0.85", "nvidia-cuda-nvrtc==13.0.88", "nvidia-cuda-runtime==13.0.96", "nvidia-cudnn-cu13==9.19.0.56", "nvidia-cufft==12.0.0.61", "nvidia-cufile==1.15.1.6", "nvidia-curand==10.4.0.35", "nvidia-cusolver==12.0.4.66", "nvidia-cusparse==12.6.3.3", "nvidia-cusparselt-cu13==0.8.0", "nvidia-nccl-cu13==2.28.9", "nvidia-nvjitlink==13.0.88", "nvidia-nvshmem-cu13==3.4.5", "nvidia-nvtx==13.0.85", "torch==2.11.0", "triton==3.6.0", "openai", "pydantic-ai-slim[logfire,openai]", "ollama", "json_repair", "sentence_transformers", "pandas", "tabulate", "openpyxl", "odfpy", "deepdiff", "html2text", "flet[all] <0.80.0", "flet-video", "flet-webview", "google-auth", "google-auth-oauthlib", "google-auth-httplib2", "google-api-python-client", "diskcache", "cachetools", "pymupdf", "pymupdf4llm", "appdirs", "filetype", "dnspython[doh]", "regex", "playwright", "aiomqtt", "av", "homeassistant_api", "aiohasupervisor", "pytubefix", "decode-config", "esptool"]
74
74
 
75
75
  [[project.authors]]
76
76
  name = "Frontmatter AI"
@@ -83,7 +83,7 @@ Homepage = "https://github.com/fmtr/corio"
83
83
  corio = "corio.entrypoint:main"
84
84
 
85
85
  [tool.corio.metadata]
86
- version = "2.3.0"
86
+ version = "2.3.2"
87
87
  port = 0
88
88
  base = "python"
89
89
  description = "Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML"
@@ -103,7 +103,7 @@ test_envs = true
103
103
  [tool.corio.dependencies]
104
104
  dev = ["logging", "version.dev", "debug", "sets", "yaml", "db.document", "infra"]
105
105
  install = []
106
- test = ["pytest", "pytest-cov"]
106
+ test = ["pytest", "pytest-cov", "pytest-asyncio"]
107
107
  yml = ["yamlscript", "pyyaml"]
108
108
  yaml = ["yml"]
109
109
  logging = ["logfire", "version"]
@@ -181,97 +181,97 @@ env_list = ["caching", "datatype", "dns", "dt", "encrypt", "env", "hash", "hook"
181
181
 
182
182
  [tool.tox.env.caching]
183
183
  description = "Run caching tests."
184
- deps = ["cachetools", "diskcache", "pytest", "pytest-cov"]
184
+ deps = ["cachetools", "diskcache", "pytest", "pytest-asyncio", "pytest-cov"]
185
185
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_caching.py"]]
186
186
 
187
187
  [tool.tox.env.datatype]
188
188
  description = "Run datatype tests."
189
- deps = ["pytest", "pytest-cov"]
189
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
190
190
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_datatype.py"]]
191
191
 
192
192
  [tool.tox.env.dns]
193
193
  description = "Run dns tests."
194
- deps = ["cachetools", "diskcache", "dnspython[doh]", "httpx", "httpx_retries", "logfire", "logfire[httpx]", "pytest", "pytest-cov"]
194
+ deps = ["cachetools", "diskcache", "dnspython[doh]", "httpx", "httpx_retries", "logfire", "logfire[httpx]", "pytest", "pytest-asyncio", "pytest-cov"]
195
195
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_dns.py"]]
196
196
 
197
197
  [tool.tox.env.dt]
198
198
  description = "Run dt tests."
199
- deps = ["pytest", "pytest-cov"]
199
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
200
200
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_dt.py"]]
201
201
 
202
202
  [tool.tox.env.encrypt]
203
203
  description = "Run encrypt tests."
204
- deps = ["pyrage", "pytest", "pytest-cov"]
204
+ deps = ["pyrage", "pytest", "pytest-asyncio", "pytest-cov"]
205
205
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_encrypt.py"]]
206
206
 
207
207
  [tool.tox.env.env]
208
208
  description = "Run env tests."
209
- deps = ["dotenv", "pytest", "pytest-cov"]
209
+ deps = ["dotenv", "pytest", "pytest-asyncio", "pytest-cov"]
210
210
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_env.py"]]
211
211
 
212
212
  [tool.tox.env.hash]
213
213
  description = "Run hash tests."
214
- deps = ["pytest", "pytest-cov"]
214
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
215
215
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_hash.py"]]
216
216
 
217
217
  [tool.tox.env.hook]
218
218
  description = "Run hook tests."
219
- deps = ["pytest", "pytest-cov"]
219
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
220
220
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_hook.py"]]
221
221
 
222
222
  [tool.tox.env.infra]
223
223
  description = "Run infra tests."
224
- deps = ["build", "deepmerge", "dotenv", "fastapi", "httpx", "httpx_retries", "logfire", "logfire[fastapi]", "logfire[httpx]", "mike", "mkdocs", "mkdocs-include-dir-to-nav", "mkdocs-material", "mkdocstrings[python]", "packaging", "pycountry", "pydantic", "pydantic-extra-types", "pydantic-settings", "pygit2", "pyrage", "pytest", "pytest-cov", "python-on-whales", "pyyaml", "semver", "setuptools", "tomlkit", "twine", "uvicorn[standard]", "yamlscript"]
224
+ deps = ["build", "deepmerge", "dotenv", "fastapi", "httpx", "httpx_retries", "logfire", "logfire[fastapi]", "logfire[httpx]", "mike", "mkdocs", "mkdocs-include-dir-to-nav", "mkdocs-material", "mkdocstrings[python]", "packaging", "pycountry", "pydantic", "pydantic-extra-types", "pydantic-settings", "pygit2", "pyrage", "pytest", "pytest-asyncio", "pytest-cov", "python-on-whales", "pyyaml", "semver", "setuptools", "tomlkit", "twine", "uvicorn[standard]", "yamlscript"]
225
225
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_infra.py"]]
226
226
 
227
227
  [tool.tox.env.iterator]
228
228
  description = "Run iterator tests."
229
- deps = ["pytest", "pytest-cov"]
229
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
230
230
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_iterator.py"]]
231
231
 
232
232
  [tool.tox.env.jsn]
233
233
  description = "Run jsn tests."
234
- deps = ["pytest", "pytest-cov"]
234
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
235
235
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_jsn.py"]]
236
236
 
237
237
  [tool.tox.env.name]
238
238
  description = "Run name tests."
239
- deps = ["pytest", "pytest-cov"]
239
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
240
240
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_name.py"]]
241
241
 
242
242
  [tool.tox.env.path]
243
243
  description = "Run path tests."
244
- deps = ["appdirs", "filetype", "pytest", "pytest-cov"]
244
+ deps = ["appdirs", "filetype", "pytest", "pytest-asyncio", "pytest-cov"]
245
245
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_path.py"]]
246
246
 
247
247
  [tool.tox.env.patterns]
248
248
  description = "Run patterns tests."
249
- deps = ["pytest", "pytest-cov", "regex"]
249
+ deps = ["pytest", "pytest-asyncio", "pytest-cov", "regex"]
250
250
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_patterns.py"]]
251
251
 
252
252
  [tool.tox.env.rand]
253
253
  description = "Run rand tests."
254
- deps = ["pytest", "pytest-cov"]
254
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
255
255
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_rand.py"]]
256
256
 
257
257
  [tool.tox.env.strings]
258
258
  description = "Run strings tests."
259
- deps = ["pytest", "pytest-cov"]
259
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
260
260
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_strings.py"]]
261
261
 
262
262
  [tool.tox.env.toml]
263
263
  description = "Run toml tests."
264
- deps = ["pytest", "pytest-cov", "tomlkit"]
264
+ deps = ["pytest", "pytest-asyncio", "pytest-cov", "tomlkit"]
265
265
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_toml.py"]]
266
266
 
267
267
  [tool.tox.env.tools]
268
268
  description = "Run tools tests."
269
- deps = ["pytest", "pytest-cov"]
269
+ deps = ["pytest", "pytest-asyncio", "pytest-cov"]
270
270
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_tools.py"]]
271
271
 
272
272
  [tool.tox.env.yml]
273
273
  description = "Run yml tests."
274
- deps = ["pytest", "pytest-cov", "pyyaml", "yamlscript"]
274
+ deps = ["pytest", "pytest-asyncio", "pytest-cov", "pyyaml", "yamlscript"]
275
275
  commands = [["python", "-m", "pytest", "-q", "corio/tests/test_yml.py"]]
276
276
 
277
277
  [build-system]
@@ -279,4 +279,4 @@ requires = ["setuptools>=82", "wheel"]
279
279
  build-backend = "setuptools.build_meta"
280
280
 
281
281
  [dependency-groups]
282
- dev = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov"]
282
+ dev = ["logfire", "semver", "pydevd-pycharm~=251.25410.159", "pydantic-settings", "pydantic", "pydantic-extra-types", "pycountry", "yamlscript", "pyyaml", "beanie", "setuptools", "mkdocs", "mkdocs-material", "mkdocstrings[python]", "mike", "mkdocs-include-dir-to-nav", "build", "twine", "packaging", "pygit2", "python-on-whales", "deepmerge", "httpx", "httpx_retries", "logfire[httpx]", "fastapi", "uvicorn[standard]", "logfire[fastapi]", "tomlkit", "pyrage", "dotenv", "pytest", "pytest-cov", "pytest-asyncio"]
@@ -2,8 +2,10 @@ from types import SimpleNamespace
2
2
 
3
3
  from packaging.requirements import Requirement
4
4
 
5
+ from corio import version
5
6
  from corio.infra.incrementor_pyproject import IncrementorPyproject, GeneratorTestEnvs
6
- from corio.infra.releaser import Tester as ReleaserTester
7
+ from corio.infra.releaser import Releaser, IncrementorVersion, Tester as ReleaserTester
8
+ from corio.infra.repository import Repository
7
9
  from corio.path import Path
8
10
 
9
11
 
@@ -319,3 +321,118 @@ def test_tester_run_returns_false_when_subprocess_fails(tmp_path, monkeypatch):
319
321
  monkeypatch.setattr(ReleaserTester, "run_subprocess", lambda self: 1)
320
322
 
321
323
  assert tester.run() is False
324
+
325
+
326
+ def test_repository_get_most_recent_release_tag_filters_and_orders():
327
+ repo = SimpleNamespace(tags=SimpleNamespace(all={
328
+ "v1.2.1",
329
+ "v1.2.2-rc.1",
330
+ "v1.2.2",
331
+ "v1.3.0-rc.1",
332
+ "junk",
333
+ }))
334
+
335
+ any_tag = Repository.get_most_recent_release_tag(repo, include_pre=True)
336
+ stable_tag = Repository.get_most_recent_release_tag(repo, include_pre=False)
337
+ previous_stable = Repository.get_most_recent_release_tag(
338
+ repo, include_pre=False, before=version.parse("1.2.2"),
339
+ )
340
+ previous_any = Repository.get_most_recent_release_tag(
341
+ repo, include_pre=True, before=version.parse("1.2.2"),
342
+ )
343
+
344
+ assert any_tag == version.parse("1.3.0-rc.1")
345
+ assert stable_tag == version.parse("1.2.2")
346
+ assert previous_stable == version.parse("1.2.1")
347
+ assert previous_any == version.parse("1.2.2-rc.1")
348
+ assert stable_tag.tag == "v1.2.2"
349
+
350
+
351
+ def _make_version_incrementor(*, old: str, pinned: str | None, tags: set[str]):
352
+ metadata = SimpleNamespace(version=old)
353
+ parent = SimpleNamespace(
354
+ paths=SimpleNamespace(name_ns="corio", metadata=metadata),
355
+ versions=SimpleNamespace(old=version.parse(old), pinned=version.parse(pinned) if pinned else None),
356
+ repo=SimpleNamespace(tags=SimpleNamespace(all=tags)),
357
+ )
358
+ return IncrementorVersion(parent), metadata
359
+
360
+
361
+ def test_incrementor_version_does_not_increment_when_old_tag_missing():
362
+ incrementor, metadata = _make_version_incrementor(
363
+ old="1.2.3",
364
+ pinned=None,
365
+ tags={"v1.2.2"},
366
+ )
367
+
368
+ incrementor.apply()
369
+
370
+ assert metadata.version == "1.2.3"
371
+
372
+
373
+ def test_incrementor_version_uses_pinned_even_when_old_tag_missing():
374
+ incrementor, metadata = _make_version_incrementor(
375
+ old="1.2.3",
376
+ pinned="2.0.0",
377
+ tags={"v1.2.2"},
378
+ )
379
+
380
+ incrementor.apply()
381
+
382
+ assert metadata.version == "2.0.0"
383
+
384
+
385
+ def test_releaser_run_commits_only_after_tests_pass(monkeypatch):
386
+ events = []
387
+
388
+ class _Repo:
389
+ def fetch(self):
390
+ events.append("fetch")
391
+
392
+ def push(self):
393
+ events.append("push")
394
+
395
+ releaser = Releaser(SimpleNamespace(
396
+ name="corio",
397
+ paths=SimpleNamespace(name_ns="corio", metadata=SimpleNamespace(is_dockerhub=False, is_pypi=False)),
398
+ ))
399
+ releaser.repo = _Repo()
400
+ releaser.tester = SimpleNamespace(run=lambda: events.append("tests") or True)
401
+
402
+ monkeypatch.setattr(Releaser, "increment", lambda self: events.append("increment"))
403
+ monkeypatch.setattr(Releaser, "commit", lambda self: events.append("commit"))
404
+
405
+ releaser.run(build=False, release=False)
406
+
407
+ assert events == ["fetch", "increment", "tests", "commit", "push", "fetch"]
408
+
409
+
410
+ def test_releaser_run_continues_when_pre_tests_fail(monkeypatch):
411
+ events = []
412
+
413
+ class _Repo:
414
+ def fetch(self):
415
+ events.append("fetch")
416
+
417
+ def push(self):
418
+ events.append("push")
419
+
420
+ releaser = Releaser(SimpleNamespace(
421
+ name="corio",
422
+ version=version.parse("1.2.3-rc.1"),
423
+ versions=SimpleNamespace(is_pre=True),
424
+ paths=SimpleNamespace(name_ns="corio", metadata=SimpleNamespace(is_dockerhub=False, is_pypi=False)),
425
+ ))
426
+ releaser.repo = _Repo()
427
+ releaser.tester = SimpleNamespace(run=lambda: events.append("tests") or False)
428
+
429
+ monkeypatch.setattr(Releaser, "increment", lambda self: events.append("increment"))
430
+ monkeypatch.setattr(Releaser, "commit", lambda self: events.append("commit"))
431
+
432
+ releaser.run(build=False, release=False)
433
+
434
+ assert events == ["fetch", "increment", "tests", "commit", "push", "fetch"]
435
+
436
+
437
+ # def test_intentional_failure_for_testing():
438
+ # assert False, "Intentional failing test for test-pipeline verification."
@@ -0,0 +1,14 @@
1
+ from corio.version.version import read, read_path, get
2
+
3
+ import semver
4
+
5
+ semver = semver
6
+
7
+
8
+ class Version(semver.Version):
9
+ @property
10
+ def tag(self) -> str:
11
+ return f"v{self}"
12
+
13
+
14
+ parse = Version.parse
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: corio
3
- Version: 2.3.0
3
+ Version: 2.3.2
4
4
  Summary: Collection of high-level tools to simplify everyday development tasks, with a focus on AI/ML
5
5
  Author-email: Frontmatter AI <innovative.fowler@mask.pro.fmtr.dev>
6
6
  License-Expression: Apache-2.0
@@ -41,9 +41,11 @@ Requires-Dist: pyrage; extra == "dev"
41
41
  Requires-Dist: dotenv; extra == "dev"
42
42
  Requires-Dist: pytest; extra == "dev"
43
43
  Requires-Dist: pytest-cov; extra == "dev"
44
+ Requires-Dist: pytest-asyncio; extra == "dev"
44
45
  Provides-Extra: test
45
46
  Requires-Dist: pytest; extra == "test"
46
47
  Requires-Dist: pytest-cov; extra == "test"
48
+ Requires-Dist: pytest-asyncio; extra == "test"
47
49
  Provides-Extra: yml
48
50
  Requires-Dist: yamlscript; extra == "yml"
49
51
  Requires-Dist: pyyaml; extra == "yml"
@@ -268,6 +270,7 @@ Requires-Dist: pyrage; extra == "infra"
268
270
  Requires-Dist: dotenv; extra == "infra"
269
271
  Requires-Dist: pytest; extra == "infra"
270
272
  Requires-Dist: pytest-cov; extra == "infra"
273
+ Requires-Dist: pytest-asyncio; extra == "infra"
271
274
  Provides-Extra: vcs
272
275
  Requires-Dist: pygit2; extra == "vcs"
273
276
  Provides-Extra: tasmota
@@ -328,6 +331,7 @@ Requires-Dist: pyrage; extra == "all"
328
331
  Requires-Dist: dotenv; extra == "all"
329
332
  Requires-Dist: pytest; extra == "all"
330
333
  Requires-Dist: pytest-cov; extra == "all"
334
+ Requires-Dist: pytest-asyncio; extra == "all"
331
335
  Requires-Dist: dask[bag]; extra == "all"
332
336
  Requires-Dist: distributed; extra == "all"
333
337
  Requires-Dist: bokeh; extra == "all"
@@ -73,6 +73,7 @@ pyrage
73
73
  dotenv
74
74
  pytest
75
75
  pytest-cov
76
+ pytest-asyncio
76
77
  dask[bag]
77
78
  distributed
78
79
  bokeh
@@ -216,6 +217,7 @@ pyrage
216
217
  dotenv
217
218
  pytest
218
219
  pytest-cov
220
+ pytest-asyncio
219
221
 
220
222
  [dm]
221
223
  pydantic
@@ -307,6 +309,7 @@ pyrage
307
309
  dotenv
308
310
  pytest
309
311
  pytest-cov
312
+ pytest-asyncio
310
313
 
311
314
  [interface]
312
315
  flet[all]<0.80.0
@@ -413,6 +416,7 @@ esptool
413
416
  [test]
414
417
  pytest
415
418
  pytest-cov
419
+ pytest-asyncio
416
420
 
417
421
  [tokenization]
418
422
  tokenizers