Skip to content

Commit 456af40

Browse files
committed
Fixed bug in guess mode
1 parent 4d0c93e commit 456af40

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

‎src/codext/__common__.py‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,17 +1370,22 @@ def __make_encodings_dict(include, exclude):
13701370
""" Process encodings inclusion and exclusion lists, listing categories and developping codecs' lists of possible
13711371
encoding names. It also creates a cache with the CodecInfo objects for improving performance. """
13721372
def _develop(d, keep=True):
1373-
d = d or {}
1373+
d, names = d or {}, None
13741374
for k, v in d.items():
13751375
l, cc, sc = [], [e for e in v if e in CODECS_CATEGORIES], [e for e in v if e not in CODECS_CATEGORIES]
1376+
cn = list_encodings(*cc) if (len(cc) > 0 or keep) and len(sc) == 0 else []
1377+
if len(sc) > 0 and names is None:
1378+
names = set(list_encodings())
13761379
# list from in-scope categories and then everything that is not a category
1377-
for enc in ((list_encodings(*cc) if (len(cc) > 0 or keep) and len(sc) == 0 else []) + sc):
1380+
for enc in cn + sc:
13781381
g = []
13791382
for e in (search(enc, False) or [enc]):
13801383
g.extend(__guess_list(e))
1381-
if enc in g: # e.g. "rot-1" => ["rot-1", "rot-2", ...] ; only "rot-1" is to be selected
1382-
l.append(enc)
1383-
else: # e.g. "rot" => ["rot-1", "rot-2", ...] ; all the "rot-N" shall be selected
1384+
# an encoding name selects only itself, while a codec name selects all its encodings, even when it is
1385+
# one of them (e.g. "base45" => ["base45", "base45-inv"])
1386+
if enc in g and enc not in cn and enc not in names:
1387+
l.append(enc) # e.g. "rot-1" => ["rot-1", "rot-2", ...] ; only "rot-1" is to be selected
1388+
else: # e.g. "rot" => ["rot-1", "rot-2", ...] ; all the "rot-N" shall be selected
13841389
l.extend(g)
13851390
d[k] = list(set(l))
13861391
return d

‎tests/test_common.py‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,22 @@ def test_guess_decode(self):
184184
self.assertEqual(txt, _l(codext.guess(b64, "0123456789", max_depth=1, scoring_heuristic=True, include="base")))
185185
self.assertRaises(ValueError, codext.stopfunc._reload_lang, "DOES_NOT_EXIST")
186186

187+
def test_guess_codec_variants(self):
188+
STR = "This is a test"
189+
_g = lambda enc, **kw: codext.guess(codext.encode(STR, enc), "a test", max_depth=1, **kw)
190+
# a codec name, given directly or through its category, selects all its encodings to be guessed, even when it is
191+
# one of them (e.g. "base45" => ["base45", "base45-inv"])
192+
for enc, inc in [("base45-inv", "base"), ("base45-inv", "base45"), ("whitespace-inv", "stegano"),
193+
("whitespace-inv", "whitespace")]:
194+
self.assertIn((enc, ), _g(enc, include=inc))
195+
# both Ook! decoders accept both forms, hence either can be found first
196+
for inc in ["esoteric", "ook"]:
197+
self.assertIn(STR, _g("ook-short", include=inc).values())
198+
# while an encoding name only selects itself
199+
self.assertEqual(list(_g("base45-inv", include="base45-inv")), [("base45-inv", )])
200+
self.assertEqual(len(_g("base45-inv", include="base45", exclude="base45-inv")), 0)
201+
self.assertEqual(len(_g("base45-inv", include="base", exclude="base45")), 0)
202+
187203
def test_rank_input(self):
188204
codext.remove("test_codec")
189205
self.assertRaises(LookupError, codext.encode, "TEST", "test")

0 commit comments

Comments
 (0)