halfedge 0.8.1__tar.gz → 0.11.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 (30) hide show
  1. {halfedge-0.8.1/src/halfedge.egg-info → halfedge-0.11.0}/PKG-INFO +5 -11
  2. halfedge-0.11.0/pyproject.toml +92 -0
  3. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/__init__.py +5 -1
  4. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/half_edge_constructors.py +3 -5
  5. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/half_edge_elements.py +6 -5
  6. halfedge-0.11.0/src/halfedge/py.typed +5 -0
  7. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/type_attrib.py +44 -45
  8. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/validations.py +2 -2
  9. halfedge-0.8.1/.github/workflows/pypi-project.yml +0 -110
  10. halfedge-0.8.1/.gitignore +0 -1
  11. halfedge-0.8.1/.pre-commit-config.yaml +0 -143
  12. halfedge-0.8.1/PKG-INFO +0 -148
  13. halfedge-0.8.1/pyproject.toml +0 -72
  14. halfedge-0.8.1/setup.cfg +0 -4
  15. halfedge-0.8.1/src/halfedge/py.typed +0 -1
  16. halfedge-0.8.1/src/halfedge.egg-info/SOURCES.txt +0 -26
  17. halfedge-0.8.1/src/halfedge.egg-info/dependency_links.txt +0 -1
  18. halfedge-0.8.1/src/halfedge.egg-info/requires.txt +0 -9
  19. halfedge-0.8.1/src/halfedge.egg-info/top_level.txt +0 -1
  20. halfedge-0.8.1/tests/__init__.py +0 -1
  21. halfedge-0.8.1/tests/conftest.py +0 -271
  22. halfedge-0.8.1/tests/test_classes.py +0 -611
  23. halfedge-0.8.1/tests/test_constructors.py +0 -191
  24. halfedge-0.8.1/tests/test_elements.py +0 -76
  25. halfedge-0.8.1/tests/test_object_pickups.py +0 -74
  26. halfedge-0.8.1/tests/test_operations.py +0 -643
  27. halfedge-0.8.1/tests/test_validations.py +0 -67
  28. {halfedge-0.8.1 → halfedge-0.11.0}/README.md +0 -0
  29. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/half_edge_object.py +0 -0
  30. {halfedge-0.8.1 → halfedge-0.11.0}/src/halfedge/half_edge_querries.py +0 -0
@@ -1,19 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: halfedge
3
- Version: 0.8.1
3
+ Version: 0.11.0
4
4
  Summary: A typical half-edge data structure with some padding
5
+ Author: Shay Hill
5
6
  Author-email: Shay Hill <shay_public@hotmail.com>
6
- License: MIT
7
- Requires-Python: >=3.9
7
+ License-Expression: MIT
8
+ Requires-Dist: paragraphs>=1.0.1
9
+ Requires-Python: >=3.11
8
10
  Description-Content-Type: text/markdown
9
- Requires-Dist: paragraphs
10
- Provides-Extra: dev
11
- Requires-Dist: commitizen; extra == "dev"
12
- Requires-Dist: coverage; extra == "dev"
13
- Requires-Dist: pre-commit; extra == "dev"
14
- Requires-Dist: pylint; extra == "dev"
15
- Requires-Dist: pytest; extra == "dev"
16
- Requires-Dist: tox; extra == "dev"
17
11
 
18
12
  # A typical halfedges data structure with some padding
19
13
 
@@ -0,0 +1,92 @@
1
+ [project]
2
+ name = "halfedge"
3
+ version = "0.11.0"
4
+ description = "A typical half-edge data structure with some padding"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [
8
+ { name = "Shay Hill", email = "shay_public@hotmail.com" }
9
+ ]
10
+ requires-python = ">=3.11"
11
+ dependencies = [
12
+ "paragraphs>=1.0.1",
13
+ ]
14
+
15
+ [build-system]
16
+ requires = ["uv_build>=0.9.4,<0.10.0"]
17
+ build-backend = "uv_build"
18
+
19
+ [dependency-groups]
20
+ dev = [
21
+ "commitizen>=4.12.1",
22
+ "pre-commit>=4.5.1",
23
+ "pytest>=9.0.2",
24
+ "ruff>=0.14.14",
25
+ ]
26
+
27
+
28
+ [tool.commitizen]
29
+ kame = "cz_conventional_commits"
30
+ version = "0.11.0"
31
+ tag_format = "$version"
32
+ major-version-zero = true
33
+ version_files = ["pyproject.toml:^version"]
34
+
35
+
36
+ [tool.isort]
37
+ profile = "black"
38
+
39
+
40
+ [tool.pytest.ini_options]
41
+ addopts = "--doctest-modules"
42
+ pythonpath = "tests"
43
+ log_cli = true
44
+ testpaths = ["tests"]
45
+ norecursedirs = ["src", ".git", ".venv", "__pycache__", "*.egg"]
46
+
47
+
48
+ [tool.ruff.lint.pydocstyle]
49
+ convention = "pep257"
50
+
51
+ [tool.ruff.lint.per-file-ignores]
52
+ "tests/*.py" = [
53
+ "S101",
54
+ "D",
55
+ "F401",
56
+ ] # Ignore assertions, docstrings, unused imports in test files
57
+
58
+ [tool.ruff.format]
59
+ docstring-code-line-length = 88
60
+
61
+ [tool.ruff.lint]
62
+
63
+ select = ["ALL"]
64
+
65
+ ignore = [
66
+ "PLR", # magic values
67
+ "COM", # trailing commas
68
+ "ANN", # forbid Any
69
+ "S", # warnings about pickle, random, etc.
70
+ "N", # names
71
+ "B019", # memory leak warning for lru_cache
72
+ ]
73
+
74
+
75
+ [tool.pyright]
76
+ include = ["src"]
77
+ exclude = ["**/__pycache__.py"]
78
+
79
+ pythonVersion = "3.11"
80
+ pythonPlatform = "All"
81
+
82
+ typeCheckingMode = "strict"
83
+ reportCallInDefaultInitializer = true
84
+ reportImplicitStringConcatenation = true
85
+ # reportMissingSuperCall = true
86
+ reportPropertyTypeMismatch = true
87
+ reportUninitializedInstanceVariable = true
88
+ reportUnnecessaryTypeIgnoreComment = true
89
+ reportUnusedCallResult = true
90
+
91
+ venvPath = "."
92
+ venv = "./.venv"
@@ -1,4 +1,8 @@
1
- """Allow modules to be imported from top-level."""
1
+ """Import functions into the package namespace.
2
+
3
+ :author: Shay Hill
4
+ :created: 2026-01-25
5
+ """
2
6
 
3
7
  from halfedge.half_edge_constructors import BlindHalfEdges
4
8
  from halfedge.half_edge_elements import Edge, Face, MeshElementBase, Vert
@@ -23,7 +23,7 @@ then passing that raw data to mesh_from_vr would create a mesh with 6 faces and
23
23
  from __future__ import annotations
24
24
 
25
25
  from contextlib import suppress
26
- from typing import TYPE_CHECKING, Any, TypeVar
26
+ from typing import TYPE_CHECKING, Any, Self, TypeVar
27
27
 
28
28
  from paragraphs import par
29
29
 
@@ -37,8 +37,6 @@ if TYPE_CHECKING:
37
37
 
38
38
  _T = TypeVar("_T")
39
39
 
40
- _TBlindHalfEdges = TypeVar("_TBlindHalfEdges", bound="BlindHalfEdges")
41
-
42
40
 
43
41
  class BlindHalfEdges:
44
42
  """Half-edge structure with no lookups."""
@@ -191,11 +189,11 @@ class BlindHalfEdges:
191
189
 
192
190
  @classmethod
193
191
  def from_vlfi(
194
- cls: type[_TBlindHalfEdges],
192
+ cls,
195
193
  vl: Sequence[Vert],
196
194
  fi: Iterable[tuple[int, ...]],
197
195
  hi: Iterable[tuple[int, ...]] | None = None,
198
- ) -> _TBlindHalfEdges:
196
+ ) -> Self:
199
197
  """Create a set of half edges from a vertex list and face index.
200
198
 
201
199
  :param vl: (vertex list) a seq of vertices
@@ -38,14 +38,15 @@ from __future__ import annotations
38
38
 
39
39
  from contextlib import suppress
40
40
  from itertools import count
41
- from typing import TYPE_CHECKING, Any, Callable, TypeVar
41
+ from typing import TYPE_CHECKING, Any, Self, TypeVar
42
42
 
43
43
  from halfedge.type_attrib import Attrib, ContagionAttrib
44
44
 
45
45
  if TYPE_CHECKING:
46
+ from collections.abc import Callable
47
+
46
48
  from halfedge.half_edge_constructors import BlindHalfEdges
47
49
 
48
- _TMeshElem = TypeVar("_TMeshElem", bound="MeshElementBase")
49
50
 
50
51
  _T = TypeVar("_T")
51
52
 
@@ -141,7 +142,7 @@ class MeshElementBase:
141
142
  except AttributeError:
142
143
  return None
143
144
 
144
- def merge_from(self: _TMeshElem, *elements: _TMeshElem) -> _TMeshElem:
145
+ def merge_from(self, *elements: Self) -> Self:
145
146
  """Fill in missing references from other elements.
146
147
 
147
148
  :param elements: elements to merge from
@@ -165,7 +166,7 @@ class MeshElementBase:
165
166
  self.set_attrib(merged_attrib)
166
167
  return self
167
168
 
168
- def split_from(self: _TMeshElem, element: _TMeshElem) -> _TMeshElem:
169
+ def split_from(self, element: Self) -> Self:
169
170
  """Pass attributes when dividing or altering elements.
170
171
 
171
172
  :param element: element to split from
@@ -182,7 +183,7 @@ class MeshElementBase:
182
183
  self.set_attrib(splitted)
183
184
  return self
184
185
 
185
- def __lt__(self: _TMeshElem, other: _TMeshElem) -> bool:
186
+ def __lt__(self, other: Self) -> bool:
186
187
  """Sort by sn.
187
188
 
188
189
  You'll want to be able to sort Verts at least to make a vlvi (vertex list,
@@ -0,0 +1,5 @@
1
+ """ This file is used to indicate to mypy that the package is typed.
2
+
3
+ Do not delete this comment, because empty files choke
4
+ some cloud drives on sync.
5
+ """
@@ -61,7 +61,7 @@ When assigned to a Vert instance, these will be stored in the Vert instance's
61
61
  from __future__ import annotations
62
62
 
63
63
  from contextlib import suppress
64
- from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
64
+ from typing import TYPE_CHECKING, Any, Generic, Literal, Self, TypeVar
65
65
 
66
66
  from paragraphs import par
67
67
 
@@ -82,10 +82,10 @@ class StaticAttrib(Generic[_T]):
82
82
  __slots__ = ("_mesh", "_value")
83
83
 
84
84
  def __new__(
85
- cls: type[_TStaticAttrib],
85
+ cls,
86
86
  value: _T | None = None,
87
87
  mesh: BlindHalfEdges | None = None,
88
- ) -> _TStaticAttrib:
88
+ ) -> Self:
89
89
  """Raise an exception if the attribute is not subclassed."""
90
90
  del value
91
91
  del mesh
@@ -157,16 +157,16 @@ class StaticAttrib(Generic[_T]):
157
157
  implication here is that calculation *cannot* be deferred till after a
158
158
  merge.
159
159
  * The merged method sums areas of the merged triangles at the first and
160
- subsequent mergers, so further triangle area calculations (which
161
- wouldn't work on the merged shapes anyway) are not required.
160
+ subsequent mergers, so further triangle area calculations (which wouldn't
161
+ work on the merged shapes anyway) are not required.
162
162
 
163
163
  If you infer a value, cache it by setting self._value.
164
164
 
165
- If you do not intend to infer values, raise an exception. This exception
166
- should occur *before* an AttributeError is raised for a potentially missing
167
- mesh attribute. It should be clear that _infer_value failed because there
168
- is no provision for inferring this Attrib.value, *not* because the
169
- user failed to set the Attrib property attribute.
165
+ If you do not intend to infer values, raise an exception. This exception should
166
+ occur *before* an AttributeError is raised for a potentially missing mesh
167
+ attribute. It should be clear that _infer_value failed because there is no
168
+ provision for inferring this Attrib.value, *not* because the user failed to set
169
+ the Attrib property attribute.
170
170
  """
171
171
  msg = par(
172
172
  f"""'{type(self).__name__}' has no provision for inferring a value from
@@ -175,31 +175,26 @@ class StaticAttrib(Generic[_T]):
175
175
  raise AttributeError(msg)
176
176
 
177
177
 
178
- _TStaticAttrib = TypeVar("_TStaticAttrib", bound=StaticAttrib[Any])
179
-
180
-
181
178
  class Attrib(Generic[_T]):
182
179
  """Base class for element attributes.
183
180
 
184
181
  MeshElementBase has methods set_attrib and get_attrib that will store Attrib
185
182
  instances in the MeshElemenBase.attrib dict. The Attrib class defines how these
186
- attributes behave when mesh elements are merged and optionally allows a value
187
- (e.g., edge length) to be inferred from the Attrib.element property when and if
188
- needed, allowing us to cache (and potentially never access) slow attributes.
189
-
190
- Do not overload `__init__` or `value`. For the most part, treat as an ABC with
191
- abstract methods `merge`, `split`, and `_infer_value`--although the base methods
192
- are marginally useful and instructive, so you will not need to overload both in
193
- every case.
183
+ attributes behave when mesh elements are merged and optionally allows a value (e.g.,
184
+ edge length) to be inferred from the Attrib.element property when and if needed,
185
+ allowing us to cache (and potentially never access) slow attributes.
186
+
187
+ Do not overload `__init__` or `value`. Subclasses can override `merge`, `split`,
188
+ and `_infer_value` to customize behavior while inheriting all other functionality.
194
189
  """
195
190
 
196
191
  __slots__ = ("_element", "_value")
197
192
 
198
193
  def __new__(
199
- cls: type[_TAttrib],
194
+ cls,
200
195
  value: _T | None = None,
201
196
  element: MeshElementBase | None = None,
202
- ) -> _TAttrib:
197
+ ) -> Self:
203
198
  """Raise an exception if the attribute is not subclassed."""
204
199
  del value
205
200
  del element
@@ -268,14 +263,15 @@ class Attrib(Generic[_T]):
268
263
  Attrib attributes are assumed None if not defined and are never defined
269
264
  if their value is None.
270
265
 
271
- This base method will not merge attributes, which is desirable in some cases.
266
+ Override this method in subclasses to customize merge behavior. Default
267
+ implementation returns None (no merge), which is desirable in some cases.
272
268
  For example, a triangle circumcenter that will be meaningless when the
273
269
  triangle is merged.
274
270
  """
275
271
  _ = merge_from
276
272
  return None
277
273
 
278
- def split(self: _TAttrib) -> _TAttrib | None:
274
+ def split(self) -> Self | None:
279
275
  """Define how attribute will be passed when dividing self.element.
280
276
 
281
277
  :return: Attrib instance or None
@@ -293,7 +289,9 @@ class Attrib(Generic[_T]):
293
289
  attribute is lazy (e.g., edge norm), you might want to unset _value for each
294
290
  piece of a split edge.
295
291
 
296
- This base method will not pass an attribute when dividing or altering.
292
+ Override this method in subclasses to customize split behavior. Default
293
+ implementation returns None (no split), meaning the attribute will not be
294
+ passed when dividing or altering elements.
297
295
  """
298
296
  return None
299
297
 
@@ -320,11 +318,12 @@ class Attrib(Generic[_T]):
320
318
 
321
319
  If you infer a value, cache it by setting self._value.
322
320
 
323
- If you do not intend to infer values, raise an exception. This exception
324
- should occur *before* an AttributeError is raised for a potentially missing
325
- element attribute. It should be clear that _infer_value failed because there
326
- is no provision for inferring this Attrib.value, *not* because the
327
- user failed to set the Attrib property attribute.
321
+ Override this method in subclasses to customize value inference. If you do
322
+ not intend to infer values, raise an exception. This exception should occur
323
+ *before* an AttributeError is raised for a potentially missing element
324
+ attribute. It should be clear that _infer_value failed because there is no
325
+ provision for inferring this Attrib.value, *not* because the user failed to
326
+ set the Attrib property attribute.
328
327
  """
329
328
  msg = par(
330
329
  f"""'{type(self).__name__}' has no provision for inferring a value from
@@ -348,10 +347,10 @@ class ContagionAttrib(Attrib[Literal[True]]):
348
347
  """
349
348
 
350
349
  def __new__(
351
- cls: type[_TAttrib],
350
+ cls,
352
351
  value: Literal[True] | None = None,
353
352
  element: MeshElementBase | None = None,
354
- ) -> _TAttrib:
353
+ ) -> Self:
355
354
  """Raise an exception if the attribute is not subclassed."""
356
355
  del value
357
356
  del element
@@ -381,7 +380,7 @@ class ContagionAttrib(Attrib[Literal[True]]):
381
380
  return attribs[0]
382
381
  return None
383
382
 
384
- def split(self: _TAttrib) -> _TAttrib | None:
383
+ def split(self) -> Self | None:
385
384
  """Copy attribute to splits.
386
385
 
387
386
  :return: self
@@ -400,10 +399,10 @@ class IncompatibleAttrib(Attrib[_T]):
400
399
  """
401
400
 
402
401
  def __new__(
403
- cls: type[_TAttrib],
402
+ cls,
404
403
  value: _T | None = None,
405
404
  element: MeshElementBase | None = None,
406
- ) -> _TAttrib:
405
+ ) -> Self:
407
406
  """Raise an exception if the attribute is not subclassed."""
408
407
  del value
409
408
  del element
@@ -431,7 +430,7 @@ class IncompatibleAttrib(Attrib[_T]):
431
430
  return None
432
431
  return merge_from[0]
433
432
 
434
- def split(self: _TAttrib) -> _TAttrib | None:
433
+ def split(self) -> Self | None:
435
434
  """Pass the value on.
436
435
 
437
436
  :return: self
@@ -443,10 +442,10 @@ class NumericAttrib(Attrib[_T]):
443
442
  """Average merge_from values."""
444
443
 
445
444
  def __new__(
446
- cls: type[_TAttrib],
445
+ cls,
447
446
  value: _T | None = None,
448
447
  element: MeshElementBase | None = None,
449
- ) -> _TAttrib:
448
+ ) -> Self:
450
449
  """Raise an exception if the attribute is not subclassed."""
451
450
  del value
452
451
  del element
@@ -473,10 +472,10 @@ class Vector2Attrib(Attrib[tuple[float, float]]):
473
472
  """Average merge_from values as xy tuples."""
474
473
 
475
474
  def __new__(
476
- cls: type[_TAttrib],
475
+ cls,
477
476
  value: tuple[float, float] | None = None,
478
477
  element: MeshElementBase | None = None,
479
- ) -> _TAttrib:
478
+ ) -> Self:
480
479
  """Raise an exception if the attribute is not subclassed."""
481
480
  del value
482
481
  del element
@@ -496,7 +495,7 @@ class Vector2Attrib(Attrib[tuple[float, float]]):
496
495
  if not have_values:
497
496
  return None
498
497
  values = [x.value for x in have_values]
499
- sum_x, sum_y = (sum(xs) for xs in zip(*values))
498
+ sum_x, sum_y = (sum(xs) for xs in zip(*values, strict=True))
500
499
  num = len(values)
501
500
  return type(have_values[0])((sum_x / num, sum_y / num))
502
501
 
@@ -505,10 +504,10 @@ class Vector3Attrib(Attrib[tuple[float, float, float]]):
505
504
  """Average merge_from values as xyz tuples."""
506
505
 
507
506
  def __new__(
508
- cls: type[_TAttrib],
507
+ cls,
509
508
  value: tuple[float, float, float] | None = None,
510
509
  element: MeshElementBase | None = None,
511
- ) -> _TAttrib:
510
+ ) -> Self:
512
511
  """Raise an exception if the attribute is not subclassed."""
513
512
  del value
514
513
  del element
@@ -528,6 +527,6 @@ class Vector3Attrib(Attrib[tuple[float, float, float]]):
528
527
  if not have_values:
529
528
  return None
530
529
  values = [x.value for x in have_values]
531
- sum_x, sum_y, sum_z = (sum(xs) for xs in zip(*values))
530
+ sum_x, sum_y, sum_z = (sum(xs) for xs in zip(*values, strict=True))
532
531
  num = len(values)
533
532
  return type(have_values[0])((sum_x / num, sum_y / num, sum_z / num))
@@ -10,12 +10,12 @@ created: 181127
10
10
  from __future__ import annotations
11
11
 
12
12
  from itertools import chain
13
- from typing import TYPE_CHECKING, Any, Callable, TypeVar
13
+ from typing import TYPE_CHECKING, Any, TypeVar
14
14
 
15
15
  from halfedge.half_edge_elements import Edge, Face, ManifoldMeshError
16
16
 
17
17
  if TYPE_CHECKING:
18
- from collections.abc import Iterator
18
+ from collections.abc import Callable, Iterator
19
19
 
20
20
  from halfedge.half_edge_querries import StaticHalfEdges
21
21
 
@@ -1,110 +0,0 @@
1
- # Run tests then upload to Pypi on version bumps.
2
- # Run tests on each push.
3
- # Try to bump version
4
- # If version is bumped, upload to pypi or test.pypi depending on branch name.
5
-
6
- name: pypi project
7
-
8
- on:
9
- push:
10
- branches: [dev, main]
11
- pull_request:
12
- branches: [main]
13
-
14
- jobs:
15
- tests:
16
- runs-on: ubuntu-latest
17
- strategy:
18
- fail-fast: false
19
- matrix:
20
- python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
21
- os: [ubuntu-latest, macos-latest, windows-latest]
22
- # if: startsWith(github.event.head_commit.message, 'bump:') == false
23
- steps:
24
- - uses: actions/checkout@v4
25
- - name: Set up Python ${{ matrix.python-version }}
26
- uses: actions/setup-python@v5
27
- with:
28
- python-version: ${{ matrix.python-version }}
29
- - name: Install dependencies
30
- run: |
31
- python -m pip install --upgrade pip
32
- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
33
- python -m pip install pytest
34
- python -m pip install commitizen
35
- python -m pip install .
36
-
37
- - name: Test with pytest
38
- run: |
39
- pytest
40
-
41
- # # If the tests pass, try to bump the version number. If no bump is warranted,
42
- # # pass silently.
43
- # bump_version:
44
- # runs-on: ubuntu-latest
45
- # name: "Bump version and create changelog with commitizen"
46
- # continue-on-error: true
47
- # needs: [tests]
48
- # if: github.ref == 'refs/heads/dev'
49
- # steps:
50
- # - name: Check out
51
- # uses: actions/checkout@v4
52
- # with:
53
- # fetch-depth: 0
54
- # token: "${{ secrets.COMMITIZEN_BUMP }}"
55
- # - id: cz
56
- # name: Create bump and changelog
57
- # uses: commitizen-tools/commitizen-action@master
58
- # with:
59
- # github_token: ${{ secrets.COMMITIZEN_BUMP }}
60
- # - name: Print Version
61
- # run: echo "Bumped to version ${{ steps.cz.outputs.version }}"
62
-
63
- # Deploy on test.pypi when branch is dev and commit message starts with 'bump'
64
- deploy-on-testpypi:
65
- runs-on: ubuntu-latest
66
- continue-on-error: true
67
- needs: [tests]
68
- if: github.ref_name == 'dev' && startsWith(github.event.head_commit.message, 'bump:')
69
- steps:
70
- - uses: actions/checkout@v4
71
- - name: Set up Python
72
- uses: actions/setup-python@v5
73
- with:
74
- python-version: '3.x'
75
- - name: Install dependencies
76
- run: |
77
- python -m pip install --upgrade pip
78
- pip install build
79
- - name: Build package
80
- run: python -m build
81
- - name: Publish package
82
- uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
83
- with:
84
- repository_url: https://test.pypi.org/legacy/
85
- user: __token__
86
- password: ${{ secrets.TEST_PYPI_API_TOKEN }}
87
-
88
- # Deploy on pypi when branch is main and commit message starts with 'bump'
89
- deploy-on-pypi:
90
- runs-on: ubuntu-latest
91
- continue-on-error: true
92
- needs: [tests]
93
- if: github.ref_name == 'main' && startsWith(github.event.head_commit.message, 'bump:')
94
- steps:
95
- - uses: actions/checkout@v4
96
- - name: Set up Python
97
- uses: actions/setup-python@v5
98
- with:
99
- python-version: '3.x'
100
- - name: Install dependencies
101
- run: |
102
- python -m pip install --upgrade pip
103
- pip install build
104
- - name: Build package
105
- run: python -m build
106
- - name: Publish package
107
- uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
108
- with:
109
- user: __token__
110
- password: ${{ secrets.PYPI_API_TOKEN }}
halfedge-0.8.1/.gitignore DELETED
@@ -1 +0,0 @@
1
- Update-PythonVenv.ps1