glitchlings 0.4.4__cp313-cp313-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.
- glitchlings/__init__.py +67 -0
- glitchlings/__main__.py +8 -0
- glitchlings/_zoo_rust.cp313-win_amd64.pyd +0 -0
- glitchlings/compat.py +284 -0
- glitchlings/config.py +388 -0
- glitchlings/config.toml +3 -0
- glitchlings/dlc/__init__.py +7 -0
- glitchlings/dlc/_shared.py +153 -0
- glitchlings/dlc/huggingface.py +81 -0
- glitchlings/dlc/prime.py +254 -0
- glitchlings/dlc/pytorch.py +166 -0
- glitchlings/dlc/pytorch_lightning.py +215 -0
- glitchlings/lexicon/__init__.py +192 -0
- glitchlings/lexicon/_cache.py +110 -0
- glitchlings/lexicon/data/default_vector_cache.json +82 -0
- glitchlings/lexicon/metrics.py +162 -0
- glitchlings/lexicon/vector.py +651 -0
- glitchlings/lexicon/wordnet.py +232 -0
- glitchlings/main.py +364 -0
- glitchlings/util/__init__.py +195 -0
- glitchlings/util/adapters.py +27 -0
- glitchlings/zoo/__init__.py +168 -0
- glitchlings/zoo/_ocr_confusions.py +32 -0
- glitchlings/zoo/_rate.py +131 -0
- glitchlings/zoo/_rust_extensions.py +143 -0
- glitchlings/zoo/_sampling.py +54 -0
- glitchlings/zoo/_text_utils.py +100 -0
- glitchlings/zoo/adjax.py +128 -0
- glitchlings/zoo/apostrofae.py +127 -0
- glitchlings/zoo/assets/__init__.py +0 -0
- glitchlings/zoo/assets/apostrofae_pairs.json +32 -0
- glitchlings/zoo/core.py +582 -0
- glitchlings/zoo/jargoyle.py +335 -0
- glitchlings/zoo/mim1c.py +109 -0
- glitchlings/zoo/ocr_confusions.tsv +30 -0
- glitchlings/zoo/redactyl.py +193 -0
- glitchlings/zoo/reduple.py +148 -0
- glitchlings/zoo/rushmore.py +153 -0
- glitchlings/zoo/scannequin.py +171 -0
- glitchlings/zoo/typogre.py +231 -0
- glitchlings/zoo/zeedub.py +185 -0
- glitchlings-0.4.4.dist-info/METADATA +627 -0
- glitchlings-0.4.4.dist-info/RECORD +47 -0
- glitchlings-0.4.4.dist-info/WHEEL +5 -0
- glitchlings-0.4.4.dist-info/entry_points.txt +2 -0
- glitchlings-0.4.4.dist-info/licenses/LICENSE +201 -0
- glitchlings-0.4.4.dist-info/top_level.txt +1 -0
glitchlings/__init__.py
ADDED
|
@@ -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
|
+
]
|
glitchlings/__main__.py
ADDED
|
Binary file
|
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
|
+
]
|