glitchlings 0.4.5__cp311-cp311-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.

Potentially problematic release.


This version of glitchlings might be problematic. Click here for more details.

Files changed (53) hide show
  1. glitchlings/__init__.py +71 -0
  2. glitchlings/__main__.py +8 -0
  3. glitchlings/_zoo_rust.cp311-win_amd64.pyd +0 -0
  4. glitchlings/compat.py +282 -0
  5. glitchlings/config.py +386 -0
  6. glitchlings/config.toml +3 -0
  7. glitchlings/data/__init__.py +1 -0
  8. glitchlings/data/hokey_assets.json +193 -0
  9. glitchlings/dlc/__init__.py +7 -0
  10. glitchlings/dlc/_shared.py +153 -0
  11. glitchlings/dlc/huggingface.py +81 -0
  12. glitchlings/dlc/prime.py +254 -0
  13. glitchlings/dlc/pytorch.py +166 -0
  14. glitchlings/dlc/pytorch_lightning.py +209 -0
  15. glitchlings/lexicon/__init__.py +192 -0
  16. glitchlings/lexicon/_cache.py +108 -0
  17. glitchlings/lexicon/data/default_vector_cache.json +82 -0
  18. glitchlings/lexicon/metrics.py +162 -0
  19. glitchlings/lexicon/vector.py +652 -0
  20. glitchlings/lexicon/wordnet.py +228 -0
  21. glitchlings/main.py +364 -0
  22. glitchlings/util/__init__.py +195 -0
  23. glitchlings/util/adapters.py +27 -0
  24. glitchlings/util/hokey_generator.py +144 -0
  25. glitchlings/util/stretch_locator.py +140 -0
  26. glitchlings/util/stretchability.py +375 -0
  27. glitchlings/zoo/__init__.py +172 -0
  28. glitchlings/zoo/_ocr_confusions.py +32 -0
  29. glitchlings/zoo/_rate.py +131 -0
  30. glitchlings/zoo/_rust_extensions.py +143 -0
  31. glitchlings/zoo/_sampling.py +54 -0
  32. glitchlings/zoo/_text_utils.py +100 -0
  33. glitchlings/zoo/adjax.py +128 -0
  34. glitchlings/zoo/apostrofae.py +127 -0
  35. glitchlings/zoo/assets/__init__.py +0 -0
  36. glitchlings/zoo/assets/apostrofae_pairs.json +32 -0
  37. glitchlings/zoo/core.py +582 -0
  38. glitchlings/zoo/hokey.py +173 -0
  39. glitchlings/zoo/jargoyle.py +335 -0
  40. glitchlings/zoo/mim1c.py +109 -0
  41. glitchlings/zoo/ocr_confusions.tsv +30 -0
  42. glitchlings/zoo/redactyl.py +193 -0
  43. glitchlings/zoo/reduple.py +148 -0
  44. glitchlings/zoo/rushmore.py +153 -0
  45. glitchlings/zoo/scannequin.py +171 -0
  46. glitchlings/zoo/typogre.py +231 -0
  47. glitchlings/zoo/zeedub.py +185 -0
  48. glitchlings-0.4.5.dist-info/METADATA +648 -0
  49. glitchlings-0.4.5.dist-info/RECORD +53 -0
  50. glitchlings-0.4.5.dist-info/WHEEL +5 -0
  51. glitchlings-0.4.5.dist-info/entry_points.txt +2 -0
  52. glitchlings-0.4.5.dist-info/licenses/LICENSE +201 -0
  53. glitchlings-0.4.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,71 @@
1
+ from .config import AttackConfig, build_gaggle, load_attack_config
2
+ from .util import SAMPLE_TEXT
3
+ from .zoo import (
4
+ Adjax,
5
+ Apostrofae,
6
+ Gaggle,
7
+ Glitchling,
8
+ Hokey,
9
+ Jargoyle,
10
+ Mim1c,
11
+ Redactyl,
12
+ Reduple,
13
+ Rushmore,
14
+ Scannequin,
15
+ Typogre,
16
+ Zeedub,
17
+ adjax,
18
+ apostrofae,
19
+ hokey,
20
+ is_rust_pipeline_enabled,
21
+ is_rust_pipeline_supported,
22
+ jargoyle,
23
+ mim1c,
24
+ pipeline_feature_flag_enabled,
25
+ plan_glitchling_specs,
26
+ plan_glitchlings,
27
+ redactyl,
28
+ reduple,
29
+ rushmore,
30
+ scannequin,
31
+ summon,
32
+ typogre,
33
+ zeedub,
34
+ )
35
+
36
+ __all__ = [
37
+ "Typogre",
38
+ "typogre",
39
+ "Mim1c",
40
+ "mim1c",
41
+ "Jargoyle",
42
+ "jargoyle",
43
+ "Adjax",
44
+ "adjax",
45
+ "Apostrofae",
46
+ "apostrofae",
47
+ "Hokey",
48
+ "hokey",
49
+ "Redactyl",
50
+ "redactyl",
51
+ "Reduple",
52
+ "reduple",
53
+ "Rushmore",
54
+ "rushmore",
55
+ "Scannequin",
56
+ "scannequin",
57
+ "Zeedub",
58
+ "zeedub",
59
+ "summon",
60
+ "Glitchling",
61
+ "Gaggle",
62
+ "plan_glitchlings",
63
+ "plan_glitchling_specs",
64
+ "is_rust_pipeline_enabled",
65
+ "is_rust_pipeline_supported",
66
+ "pipeline_feature_flag_enabled",
67
+ "SAMPLE_TEXT",
68
+ "AttackConfig",
69
+ "build_gaggle",
70
+ "load_attack_config",
71
+ ]
@@ -0,0 +1,8 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+
5
+ from .main import main
6
+
7
+ if __name__ == "__main__":
8
+ sys.exit(main())
glitchlings/compat.py ADDED
@@ -0,0 +1,282 @@
1
+ """Compatibility helpers centralising optional dependency imports and extras."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from dataclasses import dataclass
7
+ from importlib import import_module, metadata
8
+ from types import ModuleType
9
+ from typing import Any, Callable, Iterable, Protocol, cast
10
+
11
+
12
+ class _MissingSentinel:
13
+ __slots__ = ()
14
+
15
+
16
+ _MISSING = _MissingSentinel()
17
+
18
+
19
+ class _MarkerProtocol(Protocol):
20
+ def evaluate(self, environment: dict[str, str]) -> bool: ...
21
+
22
+
23
+ class _RequirementProtocol(Protocol):
24
+ marker: _MarkerProtocol | None
25
+ name: str
26
+
27
+ def __init__(self, requirement: str) -> None: ...
28
+
29
+
30
+ try: # pragma: no cover - packaging is bundled with modern Python environments
31
+ from packaging.markers import default_environment as _default_environment
32
+ except ModuleNotFoundError: # pragma: no cover - fallback when packaging missing
33
+ _default_environment = None
34
+
35
+ try: # pragma: no cover - packaging is bundled with modern Python environments
36
+ from packaging.requirements import Requirement as _RequirementClass
37
+ except ModuleNotFoundError: # pragma: no cover - fallback when packaging missing
38
+ _RequirementClass = None
39
+
40
+ default_environment: Callable[[], dict[str, str]] | None
41
+ if _default_environment is None:
42
+ default_environment = None
43
+ else:
44
+ default_environment = cast(Callable[[], dict[str, str]], _default_environment)
45
+
46
+ Requirement: type[_RequirementProtocol] | None
47
+ if _RequirementClass is None:
48
+ Requirement = None
49
+ else:
50
+ Requirement = cast(type[_RequirementProtocol], _RequirementClass)
51
+
52
+
53
+ @dataclass
54
+ class OptionalDependency:
55
+ """Lazily import an optional dependency and retain the import error."""
56
+
57
+ module_name: str
58
+ _cached: ModuleType | None | _MissingSentinel = _MISSING
59
+ _error: ModuleNotFoundError | None = None
60
+
61
+ def _attempt_import(self) -> ModuleType | None:
62
+ try:
63
+ module = import_module(self.module_name)
64
+ except ModuleNotFoundError as exc:
65
+ self._cached = None
66
+ self._error = exc
67
+ return None
68
+ else:
69
+ self._cached = module
70
+ self._error = None
71
+ return module
72
+
73
+ def get(self) -> ModuleType | None:
74
+ """Return the imported module or ``None`` when unavailable."""
75
+ cached = self._cached
76
+ if isinstance(cached, _MissingSentinel):
77
+ return self._attempt_import()
78
+ if cached is None:
79
+ return None
80
+ return cached
81
+
82
+ def load(self) -> ModuleType:
83
+ """Return the dependency, raising the original import error when absent."""
84
+ module = self.get()
85
+ if module is None:
86
+ error = self._error
87
+ if error is not None:
88
+ raise error
89
+ message = f"{self.module_name} is not installed"
90
+ raise ModuleNotFoundError(message)
91
+ return module
92
+
93
+ def require(self, message: str) -> ModuleType:
94
+ """Return the dependency or raise ``ModuleNotFoundError`` with ``message``."""
95
+ try:
96
+ return self.load()
97
+ except ModuleNotFoundError as exc:
98
+ raise ModuleNotFoundError(message) from exc
99
+
100
+ def available(self) -> bool:
101
+ """Return ``True`` when the dependency can be imported."""
102
+ return self.get() is not None
103
+
104
+ def reset(self) -> None:
105
+ """Forget any cached import result."""
106
+ self._cached = _MISSING
107
+ self._error = None
108
+
109
+ def attr(self, attribute: str) -> Any | None:
110
+ """Return ``attribute`` from the dependency when available."""
111
+ module = self.get()
112
+ if module is None:
113
+ return None
114
+ return getattr(module, attribute, None)
115
+
116
+ @property
117
+ def error(self) -> ModuleNotFoundError | None:
118
+ """Return the most recent ``ModuleNotFoundError`` (if any)."""
119
+ self.get()
120
+ return self._error
121
+
122
+
123
+ pytorch_lightning = OptionalDependency("pytorch_lightning")
124
+ datasets = OptionalDependency("datasets")
125
+ verifiers = OptionalDependency("verifiers")
126
+ jellyfish = OptionalDependency("jellyfish")
127
+ jsonschema = OptionalDependency("jsonschema")
128
+ nltk = OptionalDependency("nltk")
129
+ torch = OptionalDependency("torch")
130
+
131
+
132
+ def reset_optional_dependencies() -> None:
133
+ """Clear cached optional dependency imports (used by tests)."""
134
+ for dependency in (pytorch_lightning, datasets, verifiers, jellyfish, jsonschema, nltk, torch):
135
+ dependency.reset()
136
+
137
+
138
+ def get_datasets_dataset() -> Any | None:
139
+ """Return Hugging Face ``Dataset`` class when the dependency is installed."""
140
+ return datasets.attr("Dataset")
141
+
142
+
143
+ def require_datasets(message: str = "datasets is not installed") -> ModuleType:
144
+ """Ensure the Hugging Face datasets dependency is present."""
145
+ return datasets.require(message)
146
+
147
+
148
+ def get_pytorch_lightning_datamodule() -> Any | None:
149
+ """Return the PyTorch Lightning ``LightningDataModule`` when available."""
150
+ return pytorch_lightning.attr("LightningDataModule")
151
+
152
+
153
+ def require_pytorch_lightning(message: str = "pytorch_lightning is not installed") -> ModuleType:
154
+ """Ensure the PyTorch Lightning dependency is present."""
155
+ return pytorch_lightning.require(message)
156
+
157
+
158
+ def require_verifiers(message: str = "verifiers is not installed") -> ModuleType:
159
+ """Ensure the verifiers dependency is present."""
160
+ return verifiers.require(message)
161
+
162
+
163
+ def require_jellyfish(message: str = "jellyfish is not installed") -> ModuleType:
164
+ """Ensure the jellyfish dependency is present."""
165
+ return jellyfish.require(message)
166
+
167
+
168
+ def require_torch(message: str = "torch is not installed") -> ModuleType:
169
+ """Ensure the PyTorch dependency is present."""
170
+ return torch.require(message)
171
+
172
+
173
+ def get_torch_dataloader() -> Any | None:
174
+ """Return PyTorch ``DataLoader`` when the dependency is installed."""
175
+ torch_module = torch.get()
176
+ if torch_module is None:
177
+ return None
178
+
179
+ utils_module = getattr(torch_module, "utils", None)
180
+ if utils_module is None:
181
+ return None
182
+
183
+ data_module = getattr(utils_module, "data", None)
184
+ if data_module is None:
185
+ return None
186
+
187
+ return getattr(data_module, "DataLoader", None)
188
+
189
+
190
+ def get_installed_extras(
191
+ extras: Iterable[str] | None = None,
192
+ *,
193
+ distribution: str = "glitchlings",
194
+ ) -> dict[str, bool]:
195
+ """Return a mapping of optional extras to installation availability."""
196
+ try:
197
+ dist = metadata.distribution(distribution)
198
+ except metadata.PackageNotFoundError:
199
+ return {}
200
+
201
+ provided = {extra.lower() for extra in dist.metadata.get_all("Provides-Extra") or []}
202
+ targets = {extra.lower() for extra in extras} if extras is not None else provided
203
+ requirements = dist.requires or []
204
+ mapping: dict[str, set[str]] = {extra: set() for extra in provided}
205
+
206
+ for requirement in requirements:
207
+ names = _extras_from_requirement(requirement, provided)
208
+ if not names:
209
+ continue
210
+ req_name = _requirement_name(requirement)
211
+ for extra in names:
212
+ mapping.setdefault(extra, set()).add(req_name)
213
+
214
+ status: dict[str, bool] = {}
215
+ for extra in targets:
216
+ deps = mapping.get(extra)
217
+ if not deps:
218
+ status[extra] = False
219
+ continue
220
+ status[extra] = all(_distribution_installed(dep) for dep in deps)
221
+ return status
222
+
223
+
224
+ def _distribution_installed(name: str) -> bool:
225
+ try:
226
+ metadata.distribution(name)
227
+ except metadata.PackageNotFoundError:
228
+ return False
229
+ return True
230
+
231
+
232
+ _EXTRA_PATTERN = re.compile(r'extra\\s*==\\s*"(?P<extra>[^"]+)"')
233
+
234
+
235
+ def _extras_from_requirement(requirement: str, candidates: set[str]) -> set[str]:
236
+ if Requirement is not None and default_environment is not None:
237
+ req = Requirement(requirement)
238
+ if req.marker is None:
239
+ return set()
240
+ extras: set[str] = set()
241
+ for extra in candidates:
242
+ environment = default_environment()
243
+ environment["extra"] = extra
244
+ if req.marker.evaluate(environment):
245
+ extras.add(extra)
246
+ return extras
247
+
248
+ matches = set()
249
+ for match in _EXTRA_PATTERN.finditer(requirement):
250
+ extra = match.group("extra").lower()
251
+ if extra in candidates:
252
+ matches.add(extra)
253
+ return matches
254
+
255
+
256
+ def _requirement_name(requirement: str) -> str:
257
+ if Requirement is not None:
258
+ req = Requirement(requirement)
259
+ return req.name
260
+
261
+ candidate = requirement.split(";", 1)[0].strip()
262
+ for delimiter in ("[", "(", " ", "<", ">", "=", "!", "~"):
263
+ index = candidate.find(delimiter)
264
+ if index != -1:
265
+ return candidate[:index]
266
+ return candidate
267
+
268
+
269
+ __all__ = [
270
+ "OptionalDependency",
271
+ "datasets",
272
+ "verifiers",
273
+ "jellyfish",
274
+ "jsonschema",
275
+ "nltk",
276
+ "get_datasets_dataset",
277
+ "require_datasets",
278
+ "require_verifiers",
279
+ "require_jellyfish",
280
+ "get_installed_extras",
281
+ "reset_optional_dependencies",
282
+ ]