{"id":836,"library":"bidict","title":"Bidirectional Mapping Library","description":"The bidict library for Python provides efficient and Pythonic data structures for working with bidirectional (one-to-one) mappings. It offers familiar dictionary-like APIs, automatically keeping forward and inverse mappings in sync. The library is mature, actively maintained, and currently at version 0.23.1, with a regular release cadence. [1, 3, 10]","status":"active","version":"0.23.1","language":"python","source_language":"en","source_url":"https://github.com/jab/bidict","tags":["mapping","bidirectional","dictionary","collections"],"install":[{"cmd":"pip install bidict","lang":"bash","label":"Install bidict"}],"dependencies":[],"imports":[{"symbol":"bidict","correct":"from bidict import bidict"},{"note":"The `.inv` attribute was renamed to `.inverse` in v0.18.0. `inv` became an alias but `inverse` is the canonical and recommended name. [2, 5]","wrong":"my_bidict.inv","symbol":"bidict.inv","correct":"my_bidict.inverse"}],"quickstart":{"code":"from bidict import bidict\n\nelement_by_symbol = bidict({'H': 'hydrogen'})\nprint(f\"Forward mapping: {element_by_symbol['H']}\")\nprint(f\"Inverse mapping: {element_by_symbol.inverse['hydrogen']}\")\n\n# Updates are automatically synchronized in both directions\nelement_by_symbol['H'] = 'hydrogène'\nprint(f\"Updated forward mapping: {element_by_symbol['H']}\")\nprint(f\"Updated inverse mapping: {element_by_symbol.inverse['hydrogène']}\")","lang":"python","description":"This example demonstrates creating a basic bidirectional mapping, accessing forward and inverse entries, and observing how updates are automatically synchronized. [3, 10]"},"warnings":[{"fix":"Replace `.inv` with `.inverse`.","message":"The `.inv` attribute for accessing the inverse mapping was renamed to `.inverse`. While `.inv` was an alias for a period, it's recommended to use `.inverse` for clarity and future compatibility.","severity":"breaking","affected_versions":"<0.18.0"},{"fix":"Upgrade to Python 3.8+ (recommended `bidict` requirement) or ensure your `bidict` version is pinned to <0.22.0.","message":"Support for Python 3.6 was dropped. If you are using bidict with Python 3.6, you must remain on an older version of the library or upgrade your Python interpreter.","severity":"breaking","affected_versions":">=0.22.0"},{"fix":"Consult the changelog for `bidict` 0.20.0 for alternative approaches to handling duplicate key/value scenarios. [2]","message":"Several old APIs, including the `on_dup_key`, `on_dup_val`, and `on_dup_kv` arguments to `put()` and `putall()`, as well as the constants `bidict.OVERWRITE` and `bidict.IGNORE`, were removed.","severity":"breaking","affected_versions":">=0.20.0"},{"fix":"Ensure that any values you intend to store in a `bidict` are immutable and hashable (e.g., strings, numbers, tuples). [6]","message":"Unlike standard `dict` values, values stored in a `bidict` must be hashable. This is because values serve as keys in the inverse mapping, and keys must always be hashable in Python dictionaries.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `my_ordered_bidict.equals_order_sensitive(other_bidict)` for order-aware comparisons. [9, 14]","message":"For `OrderedBidict`, the `==` operator (`__eq__`) performs an order-insensitive comparison, similar to regular `dict`s. If you require order-sensitive equality checking, use the `equals_order_sensitive()` method.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use `bidict` for one-to-one bidirectional mappings to ensure consistency and correctness. [1, 4, 6]","message":"Attempting to create a bidirectional mapping using two separate `dict`s or a single `dict` with duplicated key/value entries is error-prone and leads to manual synchronization issues and potential data inconsistency. `bidict` handles these invariants automatically.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use `import importlib.metadata; importlib.metadata.version('bidict')` or `bidict.__version__` to get the version string. [2]","message":"The `bidict.__version_info__` attribute was removed.","severity":"deprecated","affected_versions":">=0.21.0"}],"env_vars":null,"last_verified":"2026-05-12T20:16:48.406Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Install the library using pip: `pip install bidict`","cause":"The `bidict` library is not installed in the Python environment, or the Python interpreter being used cannot find it.","error":"ModuleNotFoundError: No module named 'bidict'"},{"fix":"Ensure all values inserted into a `bidict` are unique. If overwriting is desired, use `forceput()` or specify an appropriate `OnDupAction` with `put()`, for example: `b.forceput('new_key', 'existing_value')` or `b.put('new_key', 'existing_value', on_dup=bidict.OnDup(val=bidict.ON_DUP_DROP_OLD))`.","cause":"This error occurs when attempting to add an item to a `bidict` where the value already exists, violating the bidirectional uniqueness constraint.","error":"bidict.ValueDuplicationError: <value>"},{"fix":"Use hashable types for values, such as tuples, frozensets, strings, numbers, or custom objects that implement `__hash__` and `__eq__` methods. For example, replace `['opt', 'pot', 'top']` with `('opt', 'pot', 'top')`.","cause":"Bidict requires both keys and *values* to be hashable because it maintains an inverse mapping where values become keys. Unhashable types like lists or dictionaries cannot be used as values.","error":"TypeError: unhashable type: 'list'"},{"fix":"Use the mutable `bidict` type if you need to modify the mapping after creation, or create a new `frozenbidict` with the desired changes.","cause":"`frozenbidict` is an immutable version of `bidict`, meaning its contents cannot be changed after creation.","error":"TypeError: 'frozenbidict' object does not support item assignment"},{"fix":"Update your code to use the modern `OnDupAction` enum or its predefined instances. For example, replace `bidict.OVERWRITE` with `bidict.ON_DUP_DROP_OLD` when using methods like `put()` or `putall()`.","cause":"The API for handling duplication actions changed in `bidict`. Older constants like `OVERWRITE` have been replaced by the `OnDupAction` enum and related constants (e.g., `ON_DUP_DROP_OLD`, `ON_DUP_RAISE`).","error":"AttributeError: module 'bidict' has no attribute 'OVERWRITE'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.23.1","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.8,"disk_size":"18.0M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.8,"disk_size":"18.0M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.01,"mem_mb":0.8,"disk_size":"18M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.8,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.2,"disk_size":"19.8M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.2,"disk_size":"19.8M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.6,"import_time_s":0.03,"mem_mb":1.2,"disk_size":"20M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.2,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"11.7M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"11.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.4,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"11.4M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"11.3M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"17.5M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.7,"disk_size":"17.5M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.01,"mem_mb":0.7,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}