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