vicinus 0.0.1__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 (40) hide show
  1. vicinus-0.0.1/.gitignore +9 -0
  2. vicinus-0.0.1/PKG-INFO +272 -0
  3. vicinus-0.0.1/changelog.md +8 -0
  4. vicinus-0.0.1/docs.md +166 -0
  5. vicinus-0.0.1/license +17 -0
  6. vicinus-0.0.1/old/0.vectordb.md +255 -0
  7. vicinus-0.0.1/pyproject.toml +45 -0
  8. vicinus-0.0.1/readme.md +254 -0
  9. vicinus-0.0.1/vicinus/SKILL.md +182 -0
  10. vicinus-0.0.1/vicinus/__init__.py +12 -0
  11. vicinus-0.0.1/vicinus/cli.py +181 -0
  12. vicinus-0.0.1/vicinus/errors.py +8 -0
  13. vicinus-0.0.1/vicinus/hamming.py +19 -0
  14. vicinus-0.0.1/vicinus/helpers.py +37 -0
  15. vicinus-0.0.1/vicinus/levenshtein.py +37 -0
  16. vicinus-0.0.1/vicinus/ngf_idf.py +167 -0
  17. vicinus-0.0.1/vicinus/ngrams.py +23 -0
  18. vicinus-0.0.1/vicinus/samples/__init__.py +23 -0
  19. vicinus-0.0.1/vicinus/samples/agentic-ai-emerging-cyber-threat.txt +22 -0
  20. vicinus-0.0.1/vicinus/samples/agentic-ai-technical.txt +36 -0
  21. vicinus-0.0.1/vicinus/samples/bespoke-data-erasure.txt +28 -0
  22. vicinus-0.0.1/vicinus/samples/breakfast.txt +33 -0
  23. vicinus-0.0.1/vicinus/samples/carl-jung-anima-animus.txt +18 -0
  24. vicinus-0.0.1/vicinus/samples/common-cold-vs-flu.txt +14 -0
  25. vicinus-0.0.1/vicinus/samples/finance-capitalism.txt +56 -0
  26. vicinus-0.0.1/vicinus/samples/hamming-levenshtein.txt +50 -0
  27. vicinus-0.0.1/vicinus/samples/horse-tinder-pitch.txt +14 -0
  28. vicinus-0.0.1/vicinus/samples/hymn-to-tourac.txt +49 -0
  29. vicinus-0.0.1/vicinus/samples/n-grams-jaccards-index.txt +46 -0
  30. vicinus-0.0.1/vicinus/samples/ngf-idf.txt +26 -0
  31. vicinus-0.0.1/vicinus/samples/sanctions-guide.md +57 -0
  32. vicinus-0.0.1/vicinus/samples/sanctions-lamentation.txt +26 -0
  33. vicinus-0.0.1/vicinus/samples/software-design-patterns.md +115 -0
  34. vicinus-0.0.1/vicinus/samples/spirits-cause-disease.txt +10 -0
  35. vicinus-0.0.1/vicinus/samples/tf-idf-cosine-similarity.txt +63 -0
  36. vicinus-0.0.1/vicinus/samples/wallace-in-underland.txt +22 -0
  37. vicinus-0.0.1/vicinus/samples/wolf-who-cried-boy.txt +18 -0
  38. vicinus-0.0.1/vicinus/sparse_vector.py +85 -0
  39. vicinus-0.0.1/vicinus/tokenize.py +9 -0
  40. vicinus-0.0.1/vicinus/version.py +5 -0
@@ -0,0 +1,9 @@
1
+ venv/
2
+ .vscode/
3
+ __pycache__/
4
+ **/__pycache__/
5
+ dist/
6
+ build/
7
+ temp/
8
+ **/debug.py
9
+ **.sw?
vicinus-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,272 @@
1
+ Metadata-Version: 2.4
2
+ Name: vicinus
3
+ Version: 0.0.1
4
+ Summary: Fuzzy search library from scratch implementing novel NGF/NGF-IDF system.
5
+ Project-URL: Homepage, https://pycelium.com
6
+ Project-URL: Repository, https://github.com/k98kurz/vicinus
7
+ Project-URL: Bug Tracker, https://github.com/k98kurz/vicinus/issues
8
+ Author-email: k98kurz <k98kurz@gmail.com>
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: License :: OSI Approved :: ISC License (ISCL)
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Text Processing :: Linguistic
14
+ Requires-Python: >=3.10
15
+ Provides-Extra: docs
16
+ Requires-Dist: autodox>=0.1.16; extra == 'docs'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # Vicinus
20
+
21
+ Vicinus is a library for building fuzzy search tools. It includes multiple
22
+ similarity/distance algorithms, an in-memory vector DB, and an optional
23
+ persistent vector DB using my sqloquent ORM package (sqlite3). Made from
24
+ all-organic, artisanal, 100% hand-crafted code with no gen AI (except to write
25
+ some text samples for testing) and no external dependencies.
26
+
27
+ This library includes several standard algorithms as well as a few novel (to my
28
+ knowledge) constructions: NGF and NGF-IDF, adapted from TF and TF-IDF but using
29
+ N-Grams to construct a comprehensive lexicon (26 letters + 10 numerals). The goal
30
+ of these novel constructions is to provide a lightweight alternative to text
31
+ embedding models and full TF-IDF while preserving utility for fuzzy searching.
32
+
33
+ ("Vicinus" means "neighboring/nearby" in Latin.)
34
+
35
+ ## Status
36
+
37
+ - [x] Hamming Distance/Similarity
38
+ - [x] Levenshtein Distance/Similarity
39
+ - [x] N-Gram Extraction
40
+ - [x] Jaccard Index
41
+ - [x] Sparse Vector Cosine Similarity
42
+ - [x] NGF (N-Gram Frequency)
43
+ - [x] NGF-IDF (N-Gram Frequency * Inverse Document Frequecy)
44
+ - [ ] Planned Optimizations: Levenshtein, NGF-IDF
45
+ - [ ] In-Memory VectorDB using NGF or NGF-IDF
46
+ - [ ] Persistent VectorDB using NGF or NGF-IDF
47
+
48
+ Open issues can be tracked [here](https://github.com/k98kurz/vicinus/issues).
49
+ Historical changes can be found in the
50
+ [changelog](https://github.com/k98kurz/vicinus/blob/master/changelog.md).
51
+
52
+ ## Usage
53
+
54
+ ### Installation
55
+
56
+ ```bash
57
+ pip install vicinus
58
+ ```
59
+
60
+ ### CLI
61
+
62
+ This package includes a CLI tool for exporting an agent skill to help clankers
63
+ use this package correctly. (It also serves as decent documentation in general,
64
+ so it might also be worth scanning if you aren't coding with a clanker.)
65
+
66
+ ```bash
67
+ vicinus skill # prints to stdout
68
+ vicinus skill -o path # exports to path/vicinus/
69
+ vicinus skill --agent # exports to .agent/skills/vicinus/
70
+ vicinus skill --claude # exports to .claude/skills/vicinus/
71
+ vicinus skill --codex # exports to .agent/skills/vicinus/
72
+ vicinus skill --cursor # exports to .cursor/skills/vicinus/
73
+ vicinus skill --opencode # exports to .opencode/skills/vicinus/
74
+ ```
75
+
76
+ The CLI can also be used to export the bundled text samples for experimentation.
77
+
78
+ ```bash
79
+ vicinus samples # prints all to stdout with filenames
80
+ vicinus samples -l # prints list of all filenames
81
+ vicinus samples -n name # prints a specific sample to stdout
82
+ vicinus samples -o path # exports all files to path/
83
+ ```
84
+
85
+ ### Distance/Similarity
86
+
87
+ There are two distance metrics with corresponding similarity scores Hamming and
88
+ Levenshtein.
89
+
90
+ There are additional similarity scores:
91
+ - N-Grams w/ Jaccard Index:
92
+ - NGF w/ Cosine Similarity
93
+ - NGF-IDF w/ Cosine Similarity
94
+
95
+ There are also two helper functions:
96
+ - `rank(score_fn: Callable, candidates: list) -> list[tuple[float, int]]`
97
+ - `select(rankings: list[tuple[float, int]], k: int = 4) -> list[tuple[float, int]]`
98
+
99
+ #### Hamming
100
+
101
+ Relatively simple and cheap, but not very robust. Not suitable for large texts.
102
+
103
+ ```python
104
+ from vicinus import hamming_distance, hamming_similarity, rank, select
105
+
106
+ # distance between two texts
107
+ distance = hamming_distance(text1, text2)
108
+
109
+ # rank by similarity
110
+ corpus = [text1, text2, ...]
111
+ query = "something"
112
+ # rank all by query similarity
113
+ rankings = rank(lambda t: hamming_similarity(query, t), corpus)
114
+ # get top k=2 rankings
115
+ candidates = select(rankings, 2)
116
+ ```
117
+
118
+ #### Levenshtein
119
+
120
+ More complex and robust than Hamming, but entails recursive computation. Optimized
121
+ by a limited `lru_cache(maxsize=1024)`. Not suitable for large texts.
122
+
123
+ ```python
124
+ from vicinus import levenshtein_distance, levenshtein_similarity, rank, select
125
+
126
+ # distance between two texts
127
+ distance = levenshtein_distance(text1, text2)
128
+
129
+ # rank by similarity
130
+ corpus = [text1, text2, ...]
131
+ query = "something"
132
+ # rank all by query similarity
133
+ rankings = rank(lambda t: levenshtein_similarity(query, t), corpus)
134
+ # get top k=2 rankings
135
+ candidates = select(rankings, 2)
136
+ ```
137
+
138
+ #### N-Grams w/ Jaccard Index
139
+
140
+ Normalize and break text into N-Grams, then use Jaccard Index on the N-Gram sets.
141
+ Scales well but loses cardinality of N-Gram frequencies -- a "bag of words"
142
+ technique. N-Grams should be at least 3 long (trigrams) but can be made longer for
143
+ larger texts. Jaccard Index is a measure of similarity based upon set inclusion of
144
+ N-Grams: shared/total (|intersection| / |union|). Only aphanumeric chars (standard
145
+ Latin lowercase + Arabic numerals) are supported.
146
+
147
+ ```python
148
+ from vicinus import n_grams, jaccard_index
149
+
150
+ # calculate similarity
151
+ ng1 = n_grams(text1, N=3) # default N
152
+ ng2 = n_grams(text2, N=3)
153
+ similarity = jaccard_index(ng1, ng2) # between 0 and 1.0
154
+
155
+ # rank by similarity
156
+ corpus = [text1, text2, ...]
157
+ query = "something"
158
+ corpus_ngrams = [n_grams(t) for t in corpus]
159
+ query_ngrams = n_grams(query)
160
+ # rank all by query similarity
161
+ rankings = rank(lambda t: jaccard_index(query_ngrams, t), corpus_ngrams)
162
+ # get top k=2 rankings
163
+ candidates = select(rankings, k=2)
164
+ ```
165
+
166
+ #### NGF w/ Cosine Similarity
167
+
168
+ Like TF but with N-Grams instead of terms. Includes cardinality of N-Gram
169
+ frequencies within texts but not between texts. Does not require recalculating
170
+ all vectors when a text in the corpus changes. Uses `SparseVector`s for efficiency.
171
+
172
+ ```python
173
+ from vicinus import ngf, ngf_rank, ngf_select
174
+
175
+ corpus = ["Text 1 is some text...", "Text 2 is another thing...", ...]
176
+ vecs = [ngf(t) for t in corpus]
177
+ query = "text about something"
178
+ # to sort all texts
179
+ rankings = ngf_rank(query, vecs)
180
+ # or select top k=2
181
+ candidates = ngf_select(query, vecs, k=2) # or candidates = select(rankings, 2)
182
+ ```
183
+
184
+ #### NGF-IDF w/ Cosine Similarity
185
+
186
+ Like TF-IDF but with N-Grams instead of terms. Considers N-Gram frequencies within
187
+ texts and between texts. Requires setup phase that recalculates the IDF for a
188
+ corpus whenever a text changes.
189
+
190
+ ```python
191
+ from vicinus import ngf_idf_setup, ngf_idf_rank, ngf_idf_select
192
+
193
+ corpus = ["Text 1 is some text...", "Text 2 is another thing...", ...]
194
+ corpus_idf, vecs = ngf_idf_setup(corpus)
195
+ query = "text about something"
196
+ # to sort all texts by cosine similarity
197
+ all_ranked = ngf_idf_rank(query, corpus_idf, vecs)
198
+ # or select the top k=4 (default)
199
+ candidates = ngf_idf_select(query, corpus_idf, vecs)
200
+ ```
201
+
202
+ Note: N=5 resulted in far more accurate rankings for the test vectors than the
203
+ default N=3 for Jaccard Index, NGF, and NGF-IDF. This may require some tuning.
204
+ Higher `N` values lead to sparser vectors and lower cosine similarity/Jaccard
205
+ Index scores, but this appears to be primarily a culling of noise.
206
+
207
+ ### Docs
208
+
209
+ Documentation generated by [autodox](https://pypi.org/project/autodox) (with one
210
+ fix due to a bug/missing feature in autodox) can be found
211
+ [here](https://github.com/k98kurz/vicinus/blob/master/docs.md).
212
+
213
+ ## Note on Generative AI Use
214
+
215
+ All code and documentation was written by hand, including the test suite. I used
216
+ mistral and gemma4:e4b (running on my own machine via ollama with some fun bashfu)
217
+ to write the text samples for testing. I also used gemma4:31b via Ollama cloud in
218
+ OpenCode for code review (it caught a few loose ends and documentation issues).
219
+
220
+ The inspiration for this library came during development of a yet unreleased new
221
+ agentic harness system that I intend to optimize for small, local models: as I
222
+ drafted a spec for a `tool_search` tool as an option to avoid context bloat, I
223
+ initially thought to copy a Hamming distance implementation I wrote a few months
224
+ ago in a different project for fuzzy search. I reviewed the draft spec with
225
+ gemma4:e4b, and it suggested I look at Levenshtein distance and Jaccard Index.
226
+ I then read some formulas on Wikipedia, implemented Levenshtein distance, N-grams,
227
+ and Jaccard index, and then derived the concept of NGF/NGF-IDF independently while
228
+ reflecting upon the code I had just written and the inherent difficulties with
229
+ TF/TF-IDF (i.e. the need to construct an indexed lexicon or use a text embedding
230
+ model).
231
+
232
+ Code projects like this are too fun to give to clankers. Gotta maintain some joy
233
+ in life.
234
+
235
+ ## Testing
236
+
237
+ First, clone the repo, set up a virtual env, and install requirements from
238
+ requirements.txt. Then run the following command to run the test suite.
239
+
240
+ ```bash
241
+ pip install -e . # or use uv
242
+ python -m unittest -s discover tests
243
+ ```
244
+
245
+ There are currently 38 tests covering all functionality except the CLI, which is
246
+ tested manually.
247
+
248
+ ## Contributing
249
+
250
+ Check out the [Pycelium discord server](https://discord.gg/b2QFEJDX69). If you
251
+ experience a problem, please discuss it on the Discord server. All suggestions
252
+ for improvement are also welcome, and the best place for that is also Discord.
253
+ If you experience a bug and do not use Discord, open an issue or discussion on
254
+ Github.
255
+
256
+ ## ISC License
257
+
258
+ Copyright (c) 2026 Jonathan Voss (k98kurz)
259
+
260
+ Permission to use, copy, modify, and/or distribute this software
261
+ for any purpose with or without fee is hereby granted, provided
262
+ that the above copyright notice and this permission notice appear in
263
+ all copies.
264
+
265
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
266
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
267
+ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
268
+ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
269
+ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
270
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
271
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
272
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,8 @@
1
+ ## 0.0.1
2
+
3
+ - Initial version:
4
+ - Hamming & Levenshtein distance and similarity
5
+ - N-Grams w/ Jaccard Index
6
+ - NGF w/ Cosine Similarity (and `SparseVector`s)
7
+ - NGF-IDF w/ Cosine Similarity
8
+ - CLI: export skill and bundled samples
vicinus-0.0.1/docs.md ADDED
@@ -0,0 +1,166 @@
1
+ # vicinus
2
+
3
+ ## Classes
4
+
5
+ ### `SparseVector`
6
+
7
+ Class representing a sparse vector, i.e. omitting every element that equals 0.
8
+ Useful for high dimensionality vectors with mostly 0s.
9
+
10
+ #### Methods
11
+
12
+ ##### `__init__(data: dict[int, int | float] = None):`
13
+
14
+ Initialize. Raises `TypeError` for invalid data.
15
+
16
+ ##### `get(index: int = 0) -> int | float | None:`
17
+
18
+ Get the element at the specified index.
19
+
20
+ ##### `keys() -> set[int]:`
21
+
22
+ Return the set of indices for which elements exist.
23
+
24
+ ##### `values() -> ValuesView[int | float]:`
25
+
26
+ Return a view of all elements.
27
+
28
+ ##### `items() -> ItemsView[tuple[int, int | float]]:`
29
+
30
+ Return an ItemsView for `for i, e in vec.items()` syntax.
31
+
32
+ ##### `norm() -> float:`
33
+
34
+ Calculate the Euclidean norm of a SparseVector, defined as the square root of
35
+ the dot product of itself (i.e. the sqrt of the sum of the squares of the
36
+ elements). Raises `TypeError` for invalid input.
37
+
38
+ ##### `dot_product(other: SparseVector) -> float:`
39
+
40
+ Calculate the dot product between two `SparseVector`s. Raises `TypeError` for
41
+ invalid other. Treats unset indices as 0 values mathematically.
42
+
43
+ ##### `cosine_similarity(other: SparseVector) -> float:`
44
+
45
+ Calculate the cosine similarity with another SparseVector. Raises `TypeError`.
46
+
47
+ ## Functions
48
+
49
+ ### `hamming_distance(str1: str, str2: str, normalize: bool = False) -> int | float:`
50
+
51
+ Calculate Hamming distance between two strs. If `normalize` is `False`
52
+ (default), distance is returned directly as an int. If `normalize` is set to
53
+ `True`, the distance is normalized to a float proportional to the length of the
54
+ longest string.
55
+
56
+ ### `hamming_similarity(str1: str, str2: str) -> float:`
57
+
58
+ Hamming similarity: 1 - normalized Hamming distance.
59
+
60
+ ### `rank(score_fn: Callable, candidates: list) -> list[tuple[float, int]]:`
61
+
62
+ Ranks `candidates` using the `score_fn` callable. Returns a list of tuples in
63
+ form `(score: float, index: int)`, sorted by score descending.
64
+
65
+ ### `select(rankings: list, k: int = 4) -> list[tuple[float, int]]:`
66
+
67
+ Select the top `k` from the rankings. Sorts beforehand. Assumes similarity
68
+ scores and not distance scores. Raises `TypeError` or `ValueError` for invalid
69
+ inputs.
70
+
71
+ ### `levenshtein_distance(a: str, b: str, normalize: bool = False) -> int|float:`
72
+
73
+ Calculate Levenshtein distance between two strs. If `normalize` is `False`
74
+ (default), distance is returned directly as an int. If `normalize` is set to
75
+ `True`, the distance is normalized to a float proportional to the average
76
+ length of the strings, clamped to a max of 1.0. Optimized by `@lru_cache`
77
+ decorator -- be sure to use `.lower()` or `' '.join(tokenize())` on strings
78
+ before passing them in to avoid cache fragmentation.
79
+
80
+ ### `levenshtein_similarity(a: str, b: str) -> float:`
81
+
82
+ Turns the normalized Levenshtein difference metric into a similarity metric by
83
+ substracting it from 1.0.
84
+
85
+ ### `tokenize(text: str) -> list[str]:`
86
+
87
+ Preprocess some text by casting to lower, removing punctuation, and splitting on
88
+ word boundaries. Returns only alphanumeric tokens.
89
+
90
+ ### `ngf_index(ng: str) -> int:`
91
+
92
+ Calculate the NGF vector index for a given alphanumeric N-Gram.
93
+
94
+ ### `ng_count(text: str, N: int = 3, ngs: set = None) -> SparseVector:`
95
+
96
+ Calculate the N-Gram Count of some text. First step in NGF or NGF-IDF analysis,
97
+ where NGF is like TF but with N-Grams instead of whole words. The `N` parameter
98
+ controls N-Gram size. Produces a SparseVector with max length `36^N`, where
99
+ element index is ordered by N-Gram alphanumeric order, e.g. 000, 001, ..., 0a0,
100
+ 0a1, ..., zzz.
101
+
102
+ ### `ngf(text: str, N: int = 3, vec: SparseVector = None) -> SparseVector:`
103
+
104
+ Calculate the N-Gram Frequency of some text. Analogous to TF, but with N-Grams
105
+ instead of whole words. The `N` parameter controls N-Gram size. Produces a
106
+ SparseVector max length `36^N`, where element index is ordered by N-Gram
107
+ alphanumeric order, e.g. 000, 001, ..., 0a0, 0a1, ..., zzz. Pass `vec` result of
108
+ `ng_count` to bypass retokenization of the text and recalculation of N-Grams.
109
+
110
+ ### `ngf_rank(query: str, text_vecs: list, N: int = 3) -> list[tuple[float, int]]:`
111
+
112
+ Runs NGF cosine similarity between the query and the text vectors. Returns a
113
+ sorted list of form `[(similarity, index)]`.
114
+
115
+ ### `ngf_select(query: str, text_vecs: list, k: int = 4, N: int = 3) -> list[tuple[float, int]]:`
116
+
117
+ Runs NGF cosine similarity between the query and the text vectors. Returns the
118
+ top `k` candidates in a sorted list of form `[(similarity, index)]`.
119
+
120
+ ### `ngf_idf_setup(corpus: list, N: int = 3) -> tuple[vicinus.sparse_vector.SparseVector, list[vicinus.sparse_vector.SparseVector]]:`
121
+
122
+ Processes a corpus, creating the vectors for each text in a pipeline: 1) extract
123
+ N-Grams and create NG count vectors; 2) aggregate corpus NG count vector; 3)
124
+ create NGF vectors; 4) calculate the IDF vector; 5) modify NGF vectors by
125
+ multiplying by the IDF vector. Returns the corpus IDF vector as well as the
126
+ NGF-IDF vectors to enable fuzzy search on queries.
127
+
128
+ ### `ngf_idf_query(query: str, corpus_idf: SparseVector, N: int = 3) -> SparseVector:`
129
+
130
+ Processes a query, calculating the NGF-IDF vector for it using the corpus IDF
131
+ vector.
132
+
133
+ ### `ngf_idf_rank(query: str, corpus_idf: SparseVector, text_vecs: list, N: int = 3) -> list[tuple[float, int]]:`
134
+
135
+ Runs NGF-IDF cosine similarity between the query and the text vectors. Returns a
136
+ sorted list of form `[(similarity, index)]`.
137
+
138
+ ### `ngf_idf_select(query: str, corpus_idf: SparseVector, text_vecs: list, k: int = 4, N: int = 3) -> list[tuple[float, int]]:`
139
+
140
+ Runs NGF-IDF cosine similarity between the query and the text vectors. Returns
141
+ the top `k` candidates in a sorted list of form `[(similarity, index)]`.
142
+
143
+ ### `n_grams(text: str, N: int = 3) -> set[str]:`
144
+
145
+ Extract the N-Grams of a text, defined as the set of unique substrings of the
146
+ given N.
147
+
148
+ ### `jaccard_index(a: set, b: set) -> float:`
149
+
150
+ Calculate the Jaccard similarity index between two sets, e.g. of N-Grams.
151
+ Defined as the cardinality of the intersection divided by the cardinality of the
152
+ union.
153
+
154
+ ### `list_samples() -> list[str]:`
155
+
156
+ Returns the list of bundled sample file names.
157
+
158
+ ### `get_sample(name: str) -> str:`
159
+
160
+ Reads and returns the content of the named sample. Raises FileNotFoundError for
161
+ an invalid name.
162
+
163
+ ### `version() -> str:`
164
+
165
+ Return the current library version.
166
+
vicinus-0.0.1/license ADDED
@@ -0,0 +1,17 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Jonathan Voss (k98kurz)
4
+
5
+ Permission to use, copy, modify, and/or distribute this software
6
+ for any purpose with or without fee is hereby granted, provided
7
+ that the above copyright notice and this permission notice appear in
8
+ all copies.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11
+ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12
+ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13
+ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
14
+ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
15
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.