glitchlings 0.2.1__cp312-cp312-win_amd64.whl → 0.2.2__cp312-cp312-win_amd64.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.
Binary file
glitchlings/main.py CHANGED
@@ -11,31 +11,12 @@ from . import SAMPLE_TEXT
11
11
  from .zoo import (
12
12
  Glitchling,
13
13
  Gaggle,
14
- jargoyle,
15
- mim1c,
16
- typogre,
17
- reduple,
18
- rushmore,
19
- redactyl,
20
- scannequin,
14
+ BUILTIN_GLITCHLINGS,
15
+ DEFAULT_GLITCHLING_NAMES,
16
+ parse_glitchling_spec,
21
17
  summon,
22
18
  )
23
19
 
24
-
25
- BUILTIN_GLITCHLINGS: dict[str, Glitchling] = {
26
- g.name.lower(): g
27
- for g in [
28
- typogre,
29
- mim1c,
30
- jargoyle,
31
- reduple,
32
- rushmore,
33
- redactyl,
34
- scannequin,
35
- ]
36
- }
37
-
38
- DEFAULT_GLITCHLING_NAMES: list[str] = list(BUILTIN_GLITCHLINGS.keys())
39
20
  MAX_NAME_WIDTH = max(len(glitchling.name) for glitchling in BUILTIN_GLITCHLINGS.values())
40
21
 
41
22
 
@@ -62,8 +43,11 @@ def build_parser() -> argparse.ArgumentParser:
62
43
  "--glitchling",
63
44
  dest="glitchlings",
64
45
  action="append",
65
- metavar="NAME",
66
- help="Glitchling to apply (repeat for multiples). Defaults to all built-ins.",
46
+ metavar="SPEC",
47
+ help=(
48
+ "Glitchling to apply, optionally with parameters like "
49
+ "Typogre(max_change_rate=0.05). Repeat for multiples; defaults to all built-ins."
50
+ ),
67
51
  )
68
52
  parser.add_argument(
69
53
  "-s",
@@ -147,23 +131,16 @@ def read_text(args: argparse.Namespace, parser: argparse.ArgumentParser) -> str:
147
131
  def summon_glitchlings(
148
132
  names: list[str] | None, parser: argparse.ArgumentParser, seed: int
149
133
  ) -> Gaggle:
150
- """Instantiate the requested glitchlings and bundle them in a ``Gaggle``.
151
-
152
- Args:
153
- names: Optional list of glitchling names provided by the user.
154
- parser: The argument parser used for emitting user-facing errors.
155
- seed: Master seed controlling deterministic corruption order.
156
-
157
- Returns:
158
- Gaggle: A ready-to-use collection of glitchlings.
159
-
160
- Raises:
161
- SystemExit: Raised indirectly via ``parser.error`` when a provided glitchling
162
- name is invalid.
163
- """
134
+ """Instantiate the requested glitchlings and bundle them in a ``Gaggle``."""
164
135
 
165
136
  if names:
166
- normalized = [name.lower() for name in names]
137
+ normalized: list[str | Glitchling] = []
138
+ for specification in names:
139
+ try:
140
+ normalized.append(parse_glitchling_spec(specification))
141
+ except ValueError as exc:
142
+ parser.error(str(exc))
143
+ raise AssertionError("parser.error should exit")
167
144
  else:
168
145
  normalized = DEFAULT_GLITCHLING_NAMES
169
146
 
@@ -174,6 +151,7 @@ def summon_glitchlings(
174
151
  raise AssertionError("parser.error should exit")
175
152
 
176
153
 
154
+
177
155
  def show_diff(original: str, corrupted: str) -> None:
178
156
  """Display a unified diff between the original and corrupted text."""
179
157
 
@@ -141,6 +141,36 @@ _register_layout(
141
141
  ),
142
142
  )
143
143
 
144
+ _register_layout(
145
+ "QWERTZ",
146
+ (
147
+ "^1234567890ß´",
148
+ " qwertzuiopü+",
149
+ " asdfghjklöä#",
150
+ " yxcvbnm,.-",
151
+ ),
152
+ )
153
+
154
+ _register_layout(
155
+ "SPANISH_QWERTY",
156
+ (
157
+ "º1234567890'¡",
158
+ " qwertyuiop´+",
159
+ " asdfghjklñ´",
160
+ " <zxcvbnm,.-",
161
+ ),
162
+ )
163
+
164
+ _register_layout(
165
+ "SWEDISH_QWERTY",
166
+ (
167
+ "§1234567890+´",
168
+ " qwertyuiopå¨",
169
+ " asdfghjklöä'",
170
+ " <zxcvbnm,.-",
171
+ ),
172
+ )
173
+
144
174
 
145
175
  class KeyNeighbors:
146
176
  def __init__(self) -> None:
@@ -1,6 +1,11 @@
1
+ from __future__ import annotations
2
+
3
+ import ast
4
+ from typing import Any
5
+
1
6
  from .typogre import Typogre, typogre
2
7
  from .mim1c import Mim1c, mim1c
3
- from .jargoyle import Jargoyle, jargoyle
8
+ from .jargoyle import Jargoyle, jargoyle, dependencies_available as _jargoyle_available
4
9
  from .reduple import Reduple, reduple
5
10
  from .rushmore import Rushmore, rushmore
6
11
  from .redactyl import Redactyl, redactyl
@@ -25,33 +30,105 @@ __all__ = [
25
30
  "Glitchling",
26
31
  "Gaggle",
27
32
  "summon",
33
+ "BUILTIN_GLITCHLINGS",
34
+ "DEFAULT_GLITCHLING_NAMES",
35
+ "parse_glitchling_spec",
28
36
  ]
29
37
 
38
+ _HAS_JARGOYLE = _jargoyle_available()
39
+
40
+ _BUILTIN_GLITCHLING_LIST: list[Glitchling] = [typogre, mim1c]
41
+ if _HAS_JARGOYLE:
42
+ _BUILTIN_GLITCHLING_LIST.append(jargoyle)
43
+ _BUILTIN_GLITCHLING_LIST.extend([reduple, rushmore, redactyl, scannequin])
44
+
45
+ BUILTIN_GLITCHLINGS: dict[str, Glitchling] = {
46
+ glitchling.name.lower(): glitchling for glitchling in _BUILTIN_GLITCHLING_LIST
47
+ }
48
+
49
+ _BUILTIN_GLITCHLING_TYPES: dict[str, type[Glitchling]] = {
50
+ typogre.name.lower(): Typogre,
51
+ mim1c.name.lower(): Mim1c,
52
+ reduple.name.lower(): Reduple,
53
+ rushmore.name.lower(): Rushmore,
54
+ redactyl.name.lower(): Redactyl,
55
+ scannequin.name.lower(): Scannequin,
56
+ }
57
+ if _HAS_JARGOYLE:
58
+ _BUILTIN_GLITCHLING_TYPES[jargoyle.name.lower()] = Jargoyle
59
+
60
+ DEFAULT_GLITCHLING_NAMES: list[str] = list(BUILTIN_GLITCHLINGS.keys())
61
+
62
+
63
+ def parse_glitchling_spec(specification: str) -> Glitchling:
64
+ """Return a glitchling instance configured according to ``specification``."""
65
+
66
+ text = specification.strip()
67
+ if not text:
68
+ raise ValueError("Glitchling specification cannot be empty.")
69
+
70
+ if "(" not in text:
71
+ glitchling = BUILTIN_GLITCHLINGS.get(text.lower())
72
+ if glitchling is None:
73
+ raise ValueError(f"Glitchling '{text}' not found.")
74
+ return glitchling
75
+
76
+ if not text.endswith(")"):
77
+ raise ValueError(f"Invalid parameter syntax for glitchling '{text}'.")
78
+
79
+ name_part, arg_source = text[:-1].split("(", 1)
80
+ name = name_part.strip()
81
+ if not name:
82
+ raise ValueError(f"Invalid glitchling specification '{text}'.")
83
+
84
+ lower_name = name.lower()
85
+ glitchling_type = _BUILTIN_GLITCHLING_TYPES.get(lower_name)
86
+ if glitchling_type is None:
87
+ raise ValueError(f"Glitchling '{name}' not found.")
88
+
89
+ try:
90
+ call_expr = ast.parse(f"_({arg_source})", mode="eval").body
91
+ except SyntaxError as exc:
92
+ raise ValueError(
93
+ f"Invalid parameter syntax for glitchling '{name}': {exc.msg}"
94
+ ) from exc
95
+
96
+ if not isinstance(call_expr, ast.Call) or call_expr.args:
97
+ raise ValueError(
98
+ f"Glitchling '{name}' parameters must be provided as keyword arguments."
99
+ )
100
+
101
+ kwargs: dict[str, Any] = {}
102
+ for keyword in call_expr.keywords:
103
+ if keyword.arg is None:
104
+ raise ValueError(
105
+ f"Glitchling '{name}' does not support unpacking arbitrary keyword arguments."
106
+ )
107
+ try:
108
+ kwargs[keyword.arg] = ast.literal_eval(keyword.value)
109
+ except (ValueError, SyntaxError) as exc:
110
+ raise ValueError(
111
+ f"Failed to parse value for parameter '{keyword.arg}' on glitchling '{name}': {exc}"
112
+ ) from exc
113
+
114
+ try:
115
+ return glitchling_type(**kwargs)
116
+ except TypeError as exc:
117
+ raise ValueError(f"Failed to instantiate glitchling '{name}': {exc}") from exc
118
+
30
119
 
31
120
  def summon(glitchlings: list[str | Glitchling], seed: int = 151) -> Gaggle:
32
121
  """Summon glitchlings by name (using defaults) or instance (to change parameters)."""
33
- available = {
34
- g.name.lower(): g
35
- for g in [
36
- typogre,
37
- mim1c,
38
- jargoyle,
39
- reduple,
40
- rushmore,
41
- redactyl,
42
- scannequin,
43
- ]
44
- }
45
- summoned = []
122
+
123
+ summoned: list[Glitchling] = []
46
124
  for entry in glitchlings:
47
125
  if isinstance(entry, Glitchling):
48
126
  summoned.append(entry)
49
127
  continue
50
128
 
51
- g = available.get(entry.lower())
52
- if g:
53
- summoned.append(g)
54
- else:
55
- raise ValueError(f"Glitchling '{entry}' not found.")
129
+ try:
130
+ summoned.append(parse_glitchling_spec(entry))
131
+ except ValueError as exc:
132
+ raise ValueError(str(exc)) from exc
56
133
 
57
134
  return Gaggle(summoned, seed=seed)
@@ -0,0 +1,34 @@
1
+ from __future__ import annotations
2
+
3
+ from importlib import resources
4
+
5
+ _CONFUSION_TABLE: list[tuple[str, list[str]]] | None = None
6
+
7
+
8
+ def load_confusion_table() -> list[tuple[str, list[str]]]:
9
+ """Load the OCR confusion table shared by Python and Rust implementations."""
10
+ global _CONFUSION_TABLE
11
+ if _CONFUSION_TABLE is not None:
12
+ return _CONFUSION_TABLE
13
+
14
+ data = resources.files(__package__) / "ocr_confusions.tsv"
15
+ text = data.read_text(encoding="utf-8")
16
+ indexed_entries: list[tuple[int, tuple[str, list[str]]]] = []
17
+ for line_number, line in enumerate(text.splitlines()):
18
+ stripped = line.strip()
19
+ if not stripped or stripped.startswith("#"):
20
+ continue
21
+ parts = stripped.split()
22
+ if len(parts) < 2:
23
+ continue
24
+ source, *replacements = parts
25
+ indexed_entries.append((line_number, (source, replacements)))
26
+
27
+ # Sort longer patterns first to avoid overlapping matches, mirroring the
28
+ # behaviour of the Rust `confusion_table` helper.
29
+ indexed_entries.sort(
30
+ key=lambda item: (-len(item[1][0]), item[0])
31
+ )
32
+ entries = [entry for _, entry in indexed_entries]
33
+ _CONFUSION_TABLE = entries
34
+ return entries
@@ -2,27 +2,67 @@ import random
2
2
  import re
3
3
  from collections.abc import Iterable
4
4
  from dataclasses import dataclass
5
- from typing import Any, Literal, cast
6
-
7
- import nltk
8
- from nltk.corpus.reader import WordNetCorpusReader
9
- from nltk.data import find
5
+ from typing import TYPE_CHECKING, Any, Literal, cast
6
+
7
+ try: # pragma: no cover - exercised in environments with NLTK installed
8
+ import nltk # type: ignore[import]
9
+ except ModuleNotFoundError as exc: # pragma: no cover - triggered when NLTK missing
10
+ nltk = None # type: ignore[assignment]
11
+ find = None # type: ignore[assignment]
12
+ _NLTK_IMPORT_ERROR = exc
13
+ else: # pragma: no cover - executed when NLTK is available
14
+ from nltk.corpus.reader import WordNetCorpusReader as _WordNetCorpusReader # type: ignore[import]
15
+ from nltk.data import find as _nltk_find # type: ignore[import]
16
+
17
+ find = _nltk_find
18
+ _NLTK_IMPORT_ERROR = None
19
+
20
+ if TYPE_CHECKING: # pragma: no cover - typing aid only
21
+ from nltk.corpus.reader import WordNetCorpusReader # type: ignore[import]
22
+ else: # Use ``Any`` at runtime to avoid hard dependency when NLTK missing
23
+ WordNetCorpusReader = Any
24
+
25
+ if nltk is not None: # pragma: no cover - guarded by import success
26
+ try:
27
+ from nltk.corpus import wordnet as _WORDNET_MODULE # type: ignore[import]
28
+ except ModuleNotFoundError: # pragma: no cover - only hit on namespace packages
29
+ _WORDNET_MODULE = None
30
+ else:
31
+ WordNetCorpusReader = _WordNetCorpusReader # type: ignore[assignment]
32
+ else:
33
+ _WORDNET_MODULE = None
10
34
 
11
35
  from .core import AttackWave, Glitchling
12
36
 
13
- try: # pragma: no cover - exercised when the namespace package is present
14
- from nltk.corpus import wordnet as _WORDNET_MODULE
15
- except ModuleNotFoundError: # pragma: no cover - triggered on modern NLTK installs
16
- _WORDNET_MODULE = None
17
-
18
37
  _WORDNET_HANDLE: WordNetCorpusReader | Any | None = _WORDNET_MODULE
19
38
 
20
39
  _wordnet_ready = False
21
40
 
22
41
 
42
+ def _require_nltk() -> None:
43
+ """Ensure the NLTK dependency is present before continuing."""
44
+
45
+ if nltk is None or find is None:
46
+ message = (
47
+ "The NLTK package is required for the jargoyle glitchling; install "
48
+ "the 'wordnet' extra via `pip install glitchlings[wordnet]`."
49
+ )
50
+ if '_NLTK_IMPORT_ERROR' in globals() and _NLTK_IMPORT_ERROR is not None:
51
+ raise RuntimeError(message) from _NLTK_IMPORT_ERROR
52
+ raise RuntimeError(message)
53
+
54
+
55
+ def dependencies_available() -> bool:
56
+ """Return ``True`` when the runtime NLTK dependency is present."""
57
+
58
+ return nltk is not None and find is not None
59
+
60
+
23
61
  def _load_wordnet_reader() -> WordNetCorpusReader:
24
62
  """Return a WordNet corpus reader from the downloaded corpus files."""
25
63
 
64
+ _require_nltk()
65
+
26
66
  try:
27
67
  root = find("corpora/wordnet")
28
68
  except LookupError:
@@ -59,6 +99,8 @@ def ensure_wordnet() -> None:
59
99
  if _wordnet_ready:
60
100
  return
61
101
 
102
+ _require_nltk()
103
+
62
104
  resource = _wordnet()
63
105
 
64
106
  try:
@@ -272,4 +314,4 @@ class Jargoyle(Glitchling):
272
314
  jargoyle = Jargoyle()
273
315
 
274
316
 
275
- __all__ = ["Jargoyle", "ensure_wordnet", "jargoyle"]
317
+ __all__ = ["Jargoyle", "dependencies_available", "ensure_wordnet", "jargoyle"]
@@ -0,0 +1,30 @@
1
+ # Source Replacements (space-separated)
2
+ li h
3
+ h li
4
+ rn m
5
+ m rn
6
+ cl d
7
+ d cl
8
+ I l
9
+ l I 1
10
+ 1 l I
11
+ 0 O
12
+ O 0
13
+ B 8
14
+ 8 B
15
+ S 5
16
+ 5 S
17
+ Z 2
18
+ 2 Z
19
+ G 6
20
+ 6 G
21
+ “ "
22
+ ” "
23
+ ‘ '
24
+ ’ '
25
+ — -
26
+ – -
27
+ vv w
28
+ w vv
29
+ ri n
30
+ n ri
@@ -82,7 +82,9 @@ def redact_words(
82
82
  if rng is None:
83
83
  rng = random.Random(seed)
84
84
 
85
- if _redact_words_rust is not None:
85
+ use_rust = _redact_words_rust is not None and isinstance(merge_adjacent, bool)
86
+
87
+ if use_rust:
86
88
  return _redact_words_rust(
87
89
  text,
88
90
  replacement_char,
@@ -1,6 +1,7 @@
1
1
  import re
2
2
  import random
3
3
 
4
+ from ._ocr_confusions import load_confusion_table
4
5
  from .core import Glitchling, AttackWave, AttackOrder
5
6
 
6
7
  try:
@@ -33,35 +34,9 @@ def _python_ocr_artifacts(
33
34
  if not text:
34
35
  return text
35
36
 
36
- # map: source -> list of possible replacements
37
- # Keep patterns small and specific; longer patterns first avoid overmatching
38
- confusion_table: list[tuple[str, list[str]]] = [
39
- ("li", ["h"]),
40
- ("h", ["li"]),
41
- ("rn", ["m"]),
42
- ("m", ["rn"]),
43
- ("cl", ["d"]),
44
- ("d", ["cl"]),
45
- ("I", ["l"]),
46
- ("l", ["I", "1"]),
47
- ("1", ["l", "I"]),
48
- ("0", ["O"]),
49
- ("O", ["0"]),
50
- ("B", ["8"]),
51
- ("8", ["B"]),
52
- ("S", ["5"]),
53
- ("5", ["S"]),
54
- ("Z", ["2"]),
55
- ("2", ["Z"]),
56
- ("G", ["6"]),
57
- ("6", ["G"]),
58
- ("“", ['"']),
59
- ("”", ['"']),
60
- ("‘", ["'"]),
61
- ("’", ["'"]),
62
- ("—", ["-"]), # em dash -> hyphen
63
- ("–", ["-"]), # en dash -> hyphen
64
- ]
37
+ # Keep the confusion definitions in a shared data file so both the Python
38
+ # and Rust implementations stay in sync.
39
+ confusion_table = load_confusion_table()
65
40
 
66
41
  # Build candidate matches as (start, end, choices)
67
42
  candidates: list[tuple[int, int, list[str]]] = []
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import math
3
4
  import random
4
5
  from typing import Optional
5
6
 
@@ -7,7 +8,7 @@ from .core import Glitchling, AttackWave, AttackOrder
7
8
  from ..util import KEYNEIGHBORS
8
9
 
9
10
  try:
10
- from glitchlings._typogre_rust import fatfinger as _fatfinger_rust
11
+ from glitchlings._zoo_rust import fatfinger as _fatfinger_rust
11
12
  except ImportError: # pragma: no cover - compiled extension not present
12
13
  _fatfinger_rust = None
13
14
 
@@ -91,8 +92,11 @@ def _fatfinger_python(
91
92
  layout: dict[str, list[str]],
92
93
  rng: random.Random,
93
94
  ) -> str:
95
+ rate = max(0.0, max_change_rate)
94
96
  s = text
95
- max_changes = max(1, int(len(s) * max_change_rate))
97
+ max_changes = math.ceil(len(s) * rate)
98
+ if max_changes == 0:
99
+ return s
96
100
 
97
101
  positional_actions = ("char_swap", "missing_char", "extra_char", "nearby_char")
98
102
  global_actions = ("skipped_space", "random_space", "unichar", "repeated_char")
@@ -148,12 +152,16 @@ def fatfinger(
148
152
  if not text:
149
153
  return ""
150
154
 
155
+ rate = max(0.0, max_change_rate)
156
+ if rate == 0.0:
157
+ return text
158
+
151
159
  layout = getattr(KEYNEIGHBORS, keyboard)
152
160
 
153
161
  if _fatfinger_rust is not None:
154
- return _fatfinger_rust(text, max_change_rate=max_change_rate, layout=layout, rng=rng)
162
+ return _fatfinger_rust(text, max_change_rate=rate, layout=layout, rng=rng)
155
163
 
156
- return _fatfinger_python(text, max_change_rate=max_change_rate, layout=layout, rng=rng)
164
+ return _fatfinger_python(text, max_change_rate=rate, layout=layout, rng=rng)
157
165
 
158
166
 
159
167
  class Typogre(Glitchling):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: glitchlings
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Monsters for your language games.
5
5
  Author: osoleve
6
6
  License: Apache License
@@ -232,11 +232,14 @@ Provides-Extra: hf
232
232
  Requires-Dist: datasets>=4.0.0; extra == "hf"
233
233
  Provides-Extra: wordnet
234
234
  Requires-Dist: nltk>=3.9.1; extra == "wordnet"
235
+ Requires-Dist: numpy<=2.0,>=1.24; extra == "wordnet"
235
236
  Provides-Extra: prime
236
237
  Requires-Dist: verifiers>=0.1.3.post0; extra == "prime"
237
238
  Provides-Extra: dev
238
239
  Requires-Dist: pytest>=8.0.0; extra == "dev"
239
240
  Requires-Dist: hypothesis>=6.140.0; extra == "dev"
241
+ Requires-Dist: nltk>=3.9.1; extra == "dev"
242
+ Requires-Dist: numpy<=2.0,>=1.24; extra == "dev"
240
243
  Dynamic: license-file
241
244
 
242
245
  #
@@ -294,22 +297,10 @@ print(gaggle(SAMPLE_TEXT))
294
297
 
295
298
  ## Usage
296
299
 
297
- Glitchlings slot into evaluation pipelines just as easily as they corrupt stray strings.
298
-
299
- - **Direct invocation** Instantiate a glitchling (or `Gaggle`) and call it on strings, iterables, or datasets. Keep the seed stable to make every run deterministic.
300
- - **Dataset corruption** – After ``import glitchlings.dlc.huggingface``, call ``Dataset.glitch(...)`` (or a `Gaggle`'s `.corrupt_dataset`) to perturb a Hugging Face `datasets.Dataset` and return a corrupted copy for training or evaluation.
301
-
302
- ### Rust pipeline acceleration (opt-in)
303
-
304
- The refactored Rust pipeline can execute multiple glitchlings without
305
- bouncing back through Python, but it is gated behind a feature flag so
306
- teams can roll it out gradually. After compiling the Rust extension
307
- (`python -m cibuildwheel --output-dir dist`) set
308
- `GLITCHLINGS_RUST_PIPELINE=1` (or `true`, `yes`, `on`) before importing
309
- `glitchlings`. When the flag is set and the extension is available,
310
- `Gaggle` automatically batches compatible glitchlings into the Rust
311
- pipeline; otherwise it transparently falls back to the legacy Python
312
- loop.
300
+ Need detailed usage patterns, dataset workflows, or tips for enabling the
301
+ Rust accelerator? Consult the [Glitchlings Usage Guide](docs/index.md)
302
+ for end-to-end instructions spanning the Python API, CLI, Hugging Face
303
+ integrations, and the feature-flagged Rust pipeline.
313
304
 
314
305
  ### Prime Intellect environments
315
306
 
@@ -384,11 +375,14 @@ glitchlings --list
384
375
  # Run Typogre against the contents of a file and inspect the diff.
385
376
  glitchlings -g typogre --file documents/report.txt --diff
386
377
 
378
+ # Configure glitchlings inline by passing keyword arguments.
379
+ glitchlings -g "Typogre(max_change_rate=0.05)" "Ghouls just wanna have fun"
380
+
387
381
  # Pipe text straight into the CLI for an on-the-fly corruption.
388
382
  echo "Beware LLM-written flavor-text" | glitchlings -g mim1c
389
383
  ```
390
384
 
391
- Use `--help` for a complete breakdown of available options.
385
+ Use `--help` for a complete breakdown of available options, including support for parameterised glitchlings via `-g "Name(arg=value, ...)"` to mirror the Python API.
392
386
 
393
387
  ## Development
394
388
 
@@ -0,0 +1,25 @@
1
+ glitchlings/__init__.py,sha256=w8heFqUejrXM_9NNlM9CQnIGkmGUyBV29acg3WsocXA,622
2
+ glitchlings/__main__.py,sha256=pqNe1C9hMf8pap4oh6x6yo2h4Nsa2RFSaMWHfGtNXj0,130
3
+ glitchlings/_zoo_rust.cp312-win_amd64.pyd,sha256=Eh4tD2b4ym3zX0KWxVWCFRpmPsZFnyeOiFWr_qQGg5A,1989632
4
+ glitchlings/main.py,sha256=krujz3GBrdP6FU3O6Z9f3rvc444rT79Hm69zAPG3b-U,6160
5
+ glitchlings/dlc/__init__.py,sha256=IHD-GGhVFb7SVzErvf2YCJkOR4wGo0nFHXkn_daMvS8,146
6
+ glitchlings/dlc/huggingface.py,sha256=PIesnDIEvyJxj1IuLw2P9nVPTr4Nv81XM7w2axfyhkA,3029
7
+ glitchlings/dlc/prime.py,sha256=oKVAVWSD-aa-LqDsctSLXzq0JW2RaIc1l2859ogr4lY,8107
8
+ glitchlings/util/__init__.py,sha256=GoyQuHTfGRkHzuZwJji6QWSiGd_LHa9QiyjjEpBFW7E,4679
9
+ glitchlings/zoo/__init__.py,sha256=kYKKlNvEwKtrD26E1hfde33rkN83CMf_h5AQFGjQyBQ,4312
10
+ glitchlings/zoo/_ocr_confusions.py,sha256=W59Aa5MBDwRF65f8GV-6XwGAmlR5Uk7pa5qvHvhIYdY,1252
11
+ glitchlings/zoo/core.py,sha256=aGGc0M97QeKM5rsQjTZs3fhIVac0g8A72mW4u72YnD0,14373
12
+ glitchlings/zoo/jargoyle.py,sha256=TBzt9CFL5GBP_DjqKqUY54DFsX2VAU4LnBNMDIg7P-Y,10444
13
+ glitchlings/zoo/mim1c.py,sha256=YHFELu3fpY_9VxRavYfCoAWZYp-HZBXdiLk4DTKdqcY,2979
14
+ glitchlings/zoo/ocr_confusions.tsv,sha256=S-IJEYCIXYKT1Uu7Id8Lnvg5pw528yNigTtWUdnMv9k,213
15
+ glitchlings/zoo/redactyl.py,sha256=VV2mPE2WQ41Sl874TjaHu9ShhYlFNLI7embQqKM5_ZE,3738
16
+ glitchlings/zoo/reduple.py,sha256=WuMpmuZrf5x7JneiRjDF2Y0beEAn7j1DPCV2BuuTuRY,2873
17
+ glitchlings/zoo/rushmore.py,sha256=dAiv53B_6Zg-zNG5aW8YobJevyBV586HtJVlZqgcGR8,2790
18
+ glitchlings/zoo/scannequin.py,sha256=BLJ8VFNTrXxv6mKjTMPUHOqziXO-NLpKNQNPbxG7jLI,4178
19
+ glitchlings/zoo/typogre.py,sha256=CISk0aqI8y5SdZXibqhfP0cu5MZ7TkiOQ7kftqW9RtI,5680
20
+ glitchlings-0.2.2.dist-info/licenses/LICENSE,sha256=EFEP1evBfHaxsMTBjxm0sZVRp2wct8QLvHE1saII5FI,11538
21
+ glitchlings-0.2.2.dist-info/METADATA,sha256=mRSQQoNoQAPmmVzfUn6ZZLHL1I6n5wxr45o3DyWsSMw,27811
22
+ glitchlings-0.2.2.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
23
+ glitchlings-0.2.2.dist-info/entry_points.txt,sha256=kGOwuAsjFDLtztLisaXtOouq9wFVMOJg5FzaAkg-Hto,54
24
+ glitchlings-0.2.2.dist-info/top_level.txt,sha256=VHFNBrLjtDwPCYXbGKi6o17Eueedi81eNbR3hBOoST0,12
25
+ glitchlings-0.2.2.dist-info/RECORD,,
@@ -1,24 +0,0 @@
1
- glitchlings/__init__.py,sha256=w8heFqUejrXM_9NNlM9CQnIGkmGUyBV29acg3WsocXA,622
2
- glitchlings/__main__.py,sha256=pqNe1C9hMf8pap4oh6x6yo2h4Nsa2RFSaMWHfGtNXj0,130
3
- glitchlings/_typogre_rust.cp312-win_amd64.pyd,sha256=k3PiIXoMQdZX8hMDkooQI4Rg2MH8YuHuq2rK7r5-8o4,265728
4
- glitchlings/_zoo_rust.cp312-win_amd64.pyd,sha256=SXku4dvAYyulH-ALhuxJ_A0UareKExQn6gQ75l8fBlk,1943040
5
- glitchlings/main.py,sha256=LIFZjSRlE4HiozHUhlIlEIelM6oCJii3GIsuTHW51DI,6547
6
- glitchlings/dlc/__init__.py,sha256=IHD-GGhVFb7SVzErvf2YCJkOR4wGo0nFHXkn_daMvS8,146
7
- glitchlings/dlc/huggingface.py,sha256=PIesnDIEvyJxj1IuLw2P9nVPTr4Nv81XM7w2axfyhkA,3029
8
- glitchlings/dlc/prime.py,sha256=oKVAVWSD-aa-LqDsctSLXzq0JW2RaIc1l2859ogr4lY,8107
9
- glitchlings/util/__init__.py,sha256=uGdfyq-RgEKu1nqrNbf-FoQRqnadjKME2aXbnK8hhuI,4169
10
- glitchlings/zoo/__init__.py,sha256=_tE2DXkTmQwsojvCeY1ddAE7QkOvZSMTV6c8JzP_CEw,1401
11
- glitchlings/zoo/core.py,sha256=aGGc0M97QeKM5rsQjTZs3fhIVac0g8A72mW4u72YnD0,14373
12
- glitchlings/zoo/jargoyle.py,sha256=BCaJ5gzxCun3-K1Kh3-xweLc2mzcEWgRKnLNln3bbaA,8747
13
- glitchlings/zoo/mim1c.py,sha256=YHFELu3fpY_9VxRavYfCoAWZYp-HZBXdiLk4DTKdqcY,2979
14
- glitchlings/zoo/redactyl.py,sha256=vD7XixZEMmu_xXVNzf3AY7OvdRV1iE_sEqqDrAU4mPM,3674
15
- glitchlings/zoo/reduple.py,sha256=WuMpmuZrf5x7JneiRjDF2Y0beEAn7j1DPCV2BuuTuRY,2873
16
- glitchlings/zoo/rushmore.py,sha256=dAiv53B_6Zg-zNG5aW8YobJevyBV586HtJVlZqgcGR8,2790
17
- glitchlings/zoo/scannequin.py,sha256=gwrbHpcCTp-SHXuQyQoqvw4pYzEogCjFdWPTGlmwURA,4796
18
- glitchlings/zoo/typogre.py,sha256=gr-c7qy1OpvyaAJgomwdfkGFACJiXc1DAiCtQTxrhVI,5542
19
- glitchlings-0.2.1.dist-info/licenses/LICENSE,sha256=EFEP1evBfHaxsMTBjxm0sZVRp2wct8QLvHE1saII5FI,11538
20
- glitchlings-0.2.1.dist-info/METADATA,sha256=6ekbj9GPLZgsJxKO-ZyOgyuGinxEsJlKxD-vdePvNe8,28243
21
- glitchlings-0.2.1.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
22
- glitchlings-0.2.1.dist-info/entry_points.txt,sha256=kGOwuAsjFDLtztLisaXtOouq9wFVMOJg5FzaAkg-Hto,54
23
- glitchlings-0.2.1.dist-info/top_level.txt,sha256=VHFNBrLjtDwPCYXbGKi6o17Eueedi81eNbR3hBOoST0,12
24
- glitchlings-0.2.1.dist-info/RECORD,,