|
101 | 101 | "binaryBitsFor", |
102 | 102 | ] |
103 | 103 |
|
104 | | -__version__ = "0.4.0" |
| 104 | +__version__ = "1.0.0" |
105 | 105 |
|
106 | 106 |
|
107 | 107 | class AutoMapping(collections.defaultdict): |
@@ -1317,16 +1317,41 @@ def pack_table( |
1317 | 1317 |
|
1318 | 1318 | # Set up mapping. See docstring. |
1319 | 1319 | if mapping is not None: |
1320 | | - # Validate mapping is consistently int→str or str→int |
| 1320 | + # Validate and normalize mapping to be bidirectional. |
| 1321 | + # Accept either unidirectional (all int→str or all str→int) or |
| 1322 | + # already-bidirectional mappings. |
1321 | 1323 | if not mapping: |
1322 | 1324 | raise ValueError("mapping must not be empty") |
| 1325 | + |
| 1326 | + # Check if it's a valid unidirectional mapping |
1323 | 1327 | int_to_nonint = all(isinstance(k, int) and not isinstance(v, int) for k, v in mapping.items()) |
1324 | 1328 | nonint_to_int = all(not isinstance(k, int) and isinstance(v, int) for k, v in mapping.items()) |
| 1329 | + |
| 1330 | + # Check if it's already bidirectional: every int key has a corresponding |
| 1331 | + # non-int value that maps back, and vice versa |
1325 | 1332 | if not (int_to_nonint or nonint_to_int): |
1326 | | - raise TypeError("mapping must be consistently int→str or str→int, not mixed") |
| 1333 | + # Not unidirectional, check if it's a valid bidirectional mapping |
| 1334 | + int_keys = {k for k in mapping.keys() if isinstance(k, int)} |
| 1335 | + nonint_keys = {k for k in mapping.keys() if not isinstance(k, int)} |
| 1336 | + |
| 1337 | + # Verify bidirectional consistency: for all int→nonint pairs, |
| 1338 | + # nonint→int must exist and match |
| 1339 | + is_bidirectional = ( |
| 1340 | + int_keys and nonint_keys and |
| 1341 | + all(isinstance(mapping.get(k), int) for k in nonint_keys) and |
| 1342 | + all(not isinstance(mapping.get(k), int) for k in int_keys) and |
| 1343 | + all(mapping.get(mapping.get(k)) == k for k in int_keys) and |
| 1344 | + all(mapping.get(mapping.get(k)) == k for k in nonint_keys) |
| 1345 | + ) |
| 1346 | + |
| 1347 | + if not is_bidirectional: |
| 1348 | + raise TypeError("mapping must be consistently int→str or str→int, or a valid bidirectional mapping") |
| 1349 | + |
| 1350 | + # Make bidirectional if not already |
1327 | 1351 | mapping2 = mapping.copy() |
1328 | 1352 | for k, v in mapping.items(): |
1329 | | - mapping2[v] = k |
| 1353 | + if v not in mapping2: |
| 1354 | + mapping2[v] = k |
1330 | 1355 | mapping = mapping2 |
1331 | 1356 | del mapping2 |
1332 | 1357 |
|
|
0 commit comments