vector-structure 1.0.0__tar.gz → 2.0.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.
@@ -4,5 +4,6 @@
4
4
  __pycache__/
5
5
 
6
6
  # Distribution / packaging
7
+ dist/
7
8
  build/
8
9
  *.egg-info/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vector-structure
3
- Version: 1.0.0
3
+ Version: 2.0.0
4
4
  Project-URL: Homepage, https://github.com/warggr/vector-structure
5
5
  Project-URL: Issues, https://github.com/warggr/vector-structure/issues
6
6
  Author-email: Pierre Ballif <pierre@ballif.eu>
@@ -11,6 +11,9 @@ Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Requires-Python: >=3.5
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest; extra == 'dev'
16
+ Requires-Dist: ruff; extra == 'dev'
14
17
  Description-Content-Type: text/markdown
15
18
 
16
19
  # vector-structure
@@ -1,10 +1,10 @@
1
1
  [project]
2
2
  name = "vector-structure"
3
- version = "1.0.0"
3
+ version = "2.0.0"
4
4
  description = ""
5
5
  authors = [{ name = "Pierre Ballif", email = "pierre@ballif.eu"}]
6
6
  license = "MIT"
7
- license-files = ["LICENSE"]
7
+ license-files = ["LICENSE"]
8
8
  readme = "README.md"
9
9
  requires-python = ">=3.5"
10
10
  classifiers = [
@@ -15,6 +15,9 @@ classifiers = [
15
15
  keywords = ["vector", "structure", "block", "matrix"]
16
16
  dependencies = []
17
17
 
18
+ [project.optional-dependencies]
19
+ dev = ["pytest", "ruff"]
20
+
18
21
  [project.urls]
19
22
  Homepage = "https://github.com/warggr/vector-structure"
20
23
  Issues = "https://github.com/warggr/vector-structure/issues"
@@ -24,8 +27,13 @@ requires = ["hatchling >= 1.26"]
24
27
  build-backend = "hatchling.build"
25
28
 
26
29
  [tool.hatch.build.targets.sdist]
27
- include = ["/vector_structure/", "/tests"]
30
+ include = ["/vector_structure/"]
31
+
32
+ [tool.pytest.ini_options]
33
+ testpaths = ["tests"]
34
+ pythonpath = ["."]
28
35
 
29
36
  [tool.ruff.lint]
30
37
  select = ["B", "A", "I", "D", "E4", "E7", "E9", "F"]
31
38
  ignore = ["D203", "D213", "D104", "D100", "D105", "D107"]
39
+ per-file-ignores = { "tests/*" = ["D103"] }
@@ -1,33 +1,12 @@
1
- from typing import Sequence
1
+ from typing import Generic, Sequence, TypeVar
2
2
 
3
+ BlockName = TypeVar("BlockName")
3
4
 
4
- class SimpleSlice:
5
- """Represents a contiguous range.
6
5
 
7
- Behaves like a `slice` object.
8
- """
9
-
10
- def __init__(self, start: int, stop: int):
11
- self.start = start
12
- self.stop = stop
13
-
14
- step = 1
15
-
16
- @staticmethod
17
- def from_slice(sl: slice) -> "SimpleSlice":
18
- """Translate a `slice` into a SimpleSlice."""
19
- if sl.step not in (1, None):
20
- raise ValueError()
21
- return SimpleSlice(sl.start, sl.stop)
22
-
23
- def __len__(self):
24
- return self.start - self.stop
25
-
26
-
27
- class VectorStructure:
6
+ class VectorStructure(Generic[BlockName]):
28
7
  """Helper class to describe block vectors and block matrices."""
29
8
 
30
- def __init__(self, sizes: Sequence[tuple[str, int]]):
9
+ def __init__(self, sizes: Sequence[tuple[BlockName, int]]):
31
10
  cuts = {}
32
11
  start = 0
33
12
  for k, v in sizes:
@@ -36,10 +15,14 @@ class VectorStructure:
36
15
  self.size = start
37
16
  self.cuts = cuts
38
17
 
39
- def __getitem__(self, idx: str | Sequence[str] | slice) -> SimpleSlice:
40
- if isinstance(idx, str):
41
- return self.cuts[idx]
42
- elif isinstance(idx, slice):
18
+ def __getitem__(self, idx: BlockName | tuple[BlockName, ...] | slice) -> slice:
19
+ """Get the indices for one or multiple blocks.
20
+
21
+ Note: when indexing by slice, both the start and the stop are included,
22
+ i.e. a["a":"c"] = a["a", "b", "c"].
23
+ This is different from the Python convention, but similar to Pandas.
24
+ """
25
+ if isinstance(idx, slice):
43
26
  if idx.step is not None:
44
27
  raise ValueError("slice step [start:stop:step] not supported")
45
28
  start, stop = None, None
@@ -51,12 +34,12 @@ class VectorStructure:
51
34
  if name == idx.start:
52
35
  start = cut.start
53
36
  if name == idx.stop:
54
- stop = cut.start
37
+ stop = cut.stop
55
38
  break
56
39
  if start is None or stop is None:
57
40
  raise ValueError(f"{idx.start} or {idx.stop} not found")
58
- return SimpleSlice(start, stop)
59
- else:
41
+ return slice(start, stop)
42
+ elif isinstance(idx, tuple):
60
43
  first, *more = idx
61
44
  start = self.cuts[first].start
62
45
  stop = self.cuts[first].stop
@@ -64,4 +47,6 @@ class VectorStructure:
64
47
  next_cut = self.cuts[idx]
65
48
  assert next_cut.start == stop
66
49
  stop = next_cut.stop
67
- return SimpleSlice(start, stop)
50
+ return slice(start, stop)
51
+ else:
52
+ return self.cuts[idx]