flinventory 0.3.2__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.
@@ -8,7 +8,7 @@ import random
8
8
  import argparse
9
9
  import logging
10
10
  import os
11
- from typing import Callable, Sequence, Iterable, Optional, Self, Any, Iterator
11
+ from typing import Callable, Sequence, Iterable, Optional, Self, Iterator, cast
12
12
 
13
13
  from . import constant
14
14
  from .box import BoxedThing
@@ -120,7 +120,6 @@ class Inventory(list[BoxedThing]):
120
120
  Saving schema would be possible with schema.json attribute.
121
121
  todo: maybe save options
122
122
  """
123
- logger = logging.getLogger("save_things")
124
123
  for thing in self:
125
124
  thing.save()
126
125
 
@@ -148,7 +147,7 @@ class Inventory(list[BoxedThing]):
148
147
  return thing
149
148
  raise KeyError(thing_id)
150
149
 
151
- def get_by_key(self, key, value) -> Iterator[BoxedThing]:
150
+ def get_by_key(self, key, value) -> Iterable[BoxedThing]:
152
151
  """Return all boxed things that have this value for this key.
153
152
 
154
153
  For example useful for looking up thing by name: get_by_key(('name', 0), 'Nice thing')
@@ -174,6 +173,71 @@ class Inventory(list[BoxedThing]):
174
173
  """
175
174
  return (box for box in self if box.thing.best(key, backup=None) == value)
176
175
 
176
+ def direct_ancestors(self, thing: BoxedThing, key: str) -> set[BoxedThing]:
177
+ """Convert key (assuming list of ids) into set of things.
178
+
179
+ Intended for key = subclass_of and part_of.
180
+ """
181
+ generalisations = set()
182
+ for thing_id in cast(tuple, thing.get(key, tuple())):
183
+ try:
184
+ generalisations.add(self.get_by_id(thing_id))
185
+ except KeyError:
186
+ logging.getLogger("inventory.direct_generalisations").warning(
187
+ f"id {thing_id} in {self.get_id(thing)} ({thing.best('name', backup="?")}) "
188
+ "subclass_of is not a valid id. Ignore it."
189
+ )
190
+ return generalisations
191
+
192
+ def ancestors(self, thing: BoxedThing, key: str) -> set[BoxedThing]:
193
+ """Get all direct and indirect key of elements as things.
194
+
195
+ Intended for key = subclass_of and part_of.
196
+ """
197
+ generalisations = set()
198
+ unchecked = {thing}
199
+ while unchecked:
200
+ current = unchecked.pop()
201
+ generalisations.add(current)
202
+ unchecked.update(self.direct_ancestors(current, key))
203
+ # to avoid checking something again, avoiding infinite loops:
204
+ unchecked.difference_update(generalisations)
205
+ return generalisations.difference({thing})
206
+
207
+ def super_things(self, thing: BoxedThing) -> set[BoxedThing]:
208
+ """Get all things this thing is a part of. Directly or indirectly.
209
+
210
+ That is: a part_of b & b part_of c ⇒ a part_of c
211
+ and a subclass_of b not⇒ a part_of b but
212
+ a subclass_of b & b part_of c ⇒ a part_of c
213
+
214
+ Infinite loops must be avoided, so simple recursive call might be problematic.
215
+
216
+ Not implemented but maybe necessary: caching result in the thing.
217
+ Cache must be invalidated whenever part_of or subclass_of of any
218
+ included thing changes. Difficult. Better would be cache on the
219
+ direct level.
220
+ """
221
+ supers = set()
222
+ unchecked = {thing}
223
+ generalisations = {thing} # only saved to avoid recursion loop
224
+ unchecked_generalisations = set()
225
+ while unchecked or unchecked_generalisations:
226
+ if unchecked:
227
+ current = unchecked.pop()
228
+ supers.add(current)
229
+ else:
230
+ current = unchecked_generalisations.pop()
231
+ generalisations.add(current)
232
+ unchecked.update(self.direct_ancestors(current, "part_of"))
233
+ unchecked_generalisations.update(
234
+ self.direct_ancestors(current, "subclass_of")
235
+ )
236
+ unchecked.difference_update(supers)
237
+ unchecked_generalisations.difference_update(generalisations)
238
+
239
+ return supers.difference({thing})
240
+
177
241
 
178
242
  def check_filename_types(filetypes: Sequence[str]) -> Callable[[str], str]:
179
243
  """Create function that checks for being a simple file.
@@ -267,7 +331,7 @@ def add_file_args(parser: argparse.ArgumentParser) -> None:
267
331
  "--logfile",
268
332
  "-lf",
269
333
  default="things.log",
270
- help=("Where to write the log file. Relative to the out directory."),
334
+ help="Where to write the log file. Relative to the out directory.",
271
335
  type=check_filename_types([".log"]),
272
336
  )
273
337
 
flinventory/thing.py CHANGED
@@ -39,7 +39,7 @@ class Thing(defaulted_data.DefaultedDict):
39
39
  default=default,
40
40
  non_defaulted=tuple(),
41
41
  translated=("name", "name_alt", "description"),
42
- lists=("name_alt", "part_of"),
42
+ lists=("name_alt", "part_of", "subclass_of"),
43
43
  default_order=("name", "name_alt", "part_of", "category", "url"),
44
44
  options=options,
45
45
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: flinventory
3
- Version: 0.3.2
3
+ Version: 0.4.2
4
4
  Summary: An inventory system for self-help repair shops
5
5
  Author-Email: flukx <flinventory-flukx@612211124.xyz>
6
6
  License: GPL3
@@ -43,7 +43,7 @@ There this inventory should help.
43
43
  3. Each thing can be found by one of its names alphabetically, by several categories, by English or German name, by looking at pictures in the storage. Not a single categorization to be limited to.
44
44
 
45
45
  ## Data
46
- For example data see the directory `sample-data` or [the data repository](https://flugit.hilsky.de/flukx/things-data). (Currently outdated.)
46
+ For example data see the directory `sample-data` or [branch Rad i.O. in the data repository](https://codeberg.org/flukx/flings/src/branch/rad-i-o) or the [private data repository](https://flugit.hilsky.de/flukx/things-data) if you have access.
47
47
  The data format is a specific directory structure with specific file names:
48
48
  - `schema.yaml`: describes how locations in this workshop are defined. See `sample_data` for details.
49
49
  - `preferences.yaml`: general options for this data. See `sample_data` for details.
@@ -1,7 +1,7 @@
1
- flinventory-0.3.2.dist-info/METADATA,sha256=j-huk4wILTl7PYAmUVaKGQzT5c7Nj5bIBS_BlGzaxGM,4439
2
- flinventory-0.3.2.dist-info/WHEEL,sha256=thaaA2w1JzcGC48WYufAs8nrYZjJm8LqNfnXFOFyCC4,90
3
- flinventory-0.3.2.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
- flinventory-0.3.2.dist-info/licenses/LICENSE,sha256=9c-AWlAEeFMmn1aODEfabsw2he-SpQeykurYw-KqSdw,34478
1
+ flinventory-0.4.2.dist-info/METADATA,sha256=ZQjK-O4pZu_8nTuBLmDKJ0iSepizKaVkxaGIRP-cTnc,4542
2
+ flinventory-0.4.2.dist-info/WHEEL,sha256=tSfRZzRHthuv7vxpI4aehrdN9scLjk-dCJkPLzkHxGg,90
3
+ flinventory-0.4.2.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
4
+ flinventory-0.4.2.dist-info/licenses/LICENSE,sha256=9c-AWlAEeFMmn1aODEfabsw2he-SpQeykurYw-KqSdw,34478
5
5
  flinventory/__init__.py,sha256=0HTGxw9J-2KnbxQbzX6HH-Pztkp0BEjiHANhndfbtYM,270
6
6
  flinventory/__main__.py,sha256=YI3dGiBr1i56JpGommQTWYjgfCmhr2JT1pQUdf0lf1w,1228
7
7
  flinventory/box.py,sha256=rk7yrAjVdxcrpvmTMt3jkMVOAoQNJfqoSig9U2S3yJ0,10480
@@ -9,15 +9,15 @@ flinventory/constant.py,sha256=pPNCwScLon_MOKL9_jjD_sxqB7Q2WW6rZqtrBl7SyWk,10283
9
9
  flinventory/datacleanup.py,sha256=_CImmWJhq5uKz21jJQUqKYoQfbHEYA0000RyPRt5BI0,11363
10
10
  flinventory/defaulted_data.py,sha256=KAy6V2KLcifLg7zHBFnx_eFLp31sCWih1Btp6cE0bQc,21585
11
11
  flinventory/generate_labels.py,sha256=wB9ibokHOcab599qZhi5uTzfy3DTo3wT4DJP9qLMzXs,6642
12
- flinventory/inventory_io.py,sha256=bC5NjJ2XAVZDPlr4pcJaAyh7TmRV6ELQs1LJOHW2j3U,9841
12
+ flinventory/inventory_io.py,sha256=OWThcf9nzeZNqvNpzQiBhESQAnVXC7hUA8DEVzq-w-Y,12561
13
13
  flinventory/location.py,sha256=eaZ8tF8HdzH17IBDl3_p_MsnSw5-H1GfbvkTe3dPFGk,16593
14
14
  flinventory/sign.py,sha256=8G7fsne3Nsf8zZKKTUl40uWMNsWIv7FYV2KcqBR2MQI,5515
15
15
  flinventory/signprinter_latex.py,sha256=Ytf1T_ADedj_Wkqe8bWyN23-TwFaKE7zFpeoYxn5NzM,19105
16
- flinventory/thing.py,sha256=e1PZoS29EmDNVhFoPW1_XGaovai9WthitNalailyfTM,5064
16
+ flinventory/thing.py,sha256=86fXj3RwTbkCdVVWrbyO-VEW_e5lKJlV8PPt1Xf8ejY,5079
17
17
  flinventory/thingtemplate_latex/.gitignore,sha256=DTF250Ttj8O2lxrQBwMNrQ73rWPvdwCytipfZSLFtlU,51
18
18
  flinventory/thingtemplate_latex/dummyImage.jpg,sha256=bIBH5Lrxlr5qJ42nP1cpJXPRNGLOwyEuzwXFSvNwTSk,147857
19
19
  flinventory/thingtemplate_latex/sign.tex,sha256=cVlOjImuS97Gf19MGW27HiP6Uw8JNnobXym6NlY-qSI,787
20
20
  flinventory/thingtemplate_latex/signlist-footer.tex,sha256=LcZw5__h8SqgMmYxs5oLbXLaFTQlx_X5rtYnpxwUh9Y,14
21
21
  flinventory/thingtemplate_latex/signlist-header.tex,sha256=F1J4aSPq6QO_Ved4Zn7-rytP1vDkdWTqjjtGJpe_FDg,297
22
22
  flinventory/thingtemplate_latex/signs-example.tex,sha256=J6eCcPhP0Xklgn8xnSenDOvjzmc_NGmakWU4RGbeUtM,3090
23
- flinventory-0.3.2.dist-info/RECORD,,
23
+ flinventory-0.4.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.4.3)
2
+ Generator: pdm-backend (2.4.4)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any