The bidirectional mapping library for Python.

Overview

bidict

The bidirectional mapping library for Python.

bidict logo

Status

Latest release Documentation GitHub Actions CI status Test coverage License PyPI Downloads Sponsor through GitHub

bidict:

  • has been used for many years by several teams at Google, Venmo, CERN, Bank of America Merrill Lynch, Bloomberg, Two Sigma, and many others
  • has carefully designed APIs for safety, simplicity, flexibility, and ergonomics
  • is fast, lightweight, and has no runtime dependencies other than Python's standard library
  • integrates natively with Python’s collections.abc interfaces
  • provides type hints for all public APIs
  • is implemented in concise, well-factored, pure (PyPy-compatible) Python code that is optimized for running efficiently as well as for reading and learning [1]
  • has extensive docs and test coverage (including property-based tests and benchmarks) run continuously on all supported Python versions

Installation

pip install bidict

Quick Start

>>> from bidict import bidict
>>> element_by_symbol = bidict({'H': 'hydrogen'})
>>> element_by_symbol['H']
'hydrogen'
>>> element_by_symbol.inverse['hydrogen']
'H'

For more usage documentation, head to the intro [3] and proceed from there.

Enterprise Support

Enterprise-level support for bidict can be obtained via the Tidelift subscription or by contacting me directly.

I have a US-based LLC set up for invoicing, and I have 15+ years of professional experience delivering software and support to companies successfully.

You can also sponsor my work through platforms like GitHub Sponsors. See the Sponsoring section below for details. For rationale and examples of companies doing this, see this post among others.

Voluntary Community Support

Please search through already-asked questions and answers in GitHub Discussions and the issue tracker in case your question has already been addressed.

Otherwise, please feel free to start a new discussion or create a new issue on GitHub, or ask in the bidict chatroom for voluntary community support.

Notice of Usage

If you use bidict, and especially if your usage or your organization is significant in some way, please let me know in any of the following ways:

Changelog

See the changelog [2] for a history of notable changes to bidict.

Release Notifications

Watch releases on GitHub to be notified when new versions of bidict are released.

Learning from bidict

One of the best things about bidict is that it touches a surprising number of interesting Python corners, especially given its small size and scope.

Check out learning-from-bidict [1] if you're interested in learning more.

Contributing

I have been bidict's sole maintainer and active contributor since I started the project almost 15 years ago.

Your help would be most welcome! See the contributors-guide [4] for more information.

Sponsoring

Sponsor through GitHub

Bidict is the product of thousands of hours of my unpaid work over the ~15 years that I've been the sole maintainer.

If bidict has helped you or your company accomplish your work, especially work that you or your company were paid for, please sponsor my work through GitHub, and ask others you know who got value from my work to do the same.

Choose a tier and GitHub handles everything else. Sponsorship just goes on the same bill that GitHub already charges you or your company for automatically, so after the one-time signup, there's nothing extra to do.

You can also sponsor my work through Gumroad or PayPal, or through a support engagement with my LLC. See Enterprise Support above for details.

Finding Documentation

If you're viewing this on https://bidict.readthedocs.io, note that multiple versions of the documentation are available, and you can choose a different version using the popup menu at the bottom-right. Please make sure you're viewing the version of the documentation that corresponds to the version of bidict you'd like to use.

If you're viewing this on GitHub, PyPI, or some other place that can't render and link this documentation properly and are seeing broken links, try these alternate links instead:

[1] (1, 2) docs/learning-from-bidict.rst | https://bidict.readthedocs.io/learning-from-bidict.html
[2] CHANGELOG.rst | https://bidict.readthedocs.io/changelog.html
[3] (1, 2) docs/intro.rst | https://bidict.readthedocs.io/intro.html
[4] docs/contributors-guide.rst | https://bidict.readthedocs.io/contributors-guide.html

Next: intro [3]

Comments
  • Consider removing slice and ~ syntax

    Consider removing slice and ~ syntax

    Some of the syntactic sugar in bidict causes a readability problem for me. Syntactic sugar is always going to be subjective, but I'd like to propose the removal of the overloading of slicing and bitwise negation - because .inv is succinct and covers all these cases without needing the sugar:

    • ~d is clearer written as d.inv
    • d[:key] is clearer written as d.inv[key].

    These don't need to be explained/learned in the same way as they follow from the same clear rule.

    Naturally this would be a big breaking change but if bidict is not yet at a 1.0 release then this could presumably still be considered.

    opened by lordmauve 24
  • global name 'BidirectionalMapping' is not defined

    global name 'BidirectionalMapping' is not defined

    Hi, we are using version bidict==0.18.0 and CPython 2.7.13 and got the following error here:

    bidict/_abc.py in subclasshook at line 90

        def __subclasshook__(cls, C):  # noqa: N803 (argument name should be lowercase)
            """Check if *C* is a :class:`~collections.abc.Mapping`
            that also provides an ``inverse`` attribute,
            thus conforming to the :class:`BidirectionalMapping` interface,
            in which case it will be considered a (virtual) C
            even if it doesn't explicitly extend it.
            """
            that also provides an ``inverse`` attribute,
            thus conforming to the :class:`BidirectionalMapping` interface,
            in which case it will be considered a (virtual) C
            even if it doesn't explicitly extend it.
            """
            if cls is not BidirectionalMapping:  # lgtm [py/comparison-using-is]  # global name 'BidirectionalMapping' is not defined here
                return NotImplemented
            if not Mapping.__subclasshook__(C):
                return NotImplemented
            mro = getattr(C, '__mro__', None)
            if mro is None:  # Python 2 old-style class
            ...
    

    C is a <type 'unicode'> here. So we simply pass unicode string to logger and such error raised. Looks like this happened because of the following line in python2.7/logging/init.py:

    if (args and len(args) == 1 and isinstance(args[0], collections.Mapping)
    

    Could anybody help with this issue? What we are doing wrong? Thanks in advance.

    opened by andreykryazhev 21
  • provide type annotations

    provide type annotations

    Maybe after removing support for older versions of Python.

    Ref:

    • https://docs.python.org/3/library/typing.html
    • https://mypy.readthedocs.io/en/stable/generics.html#defining-sub-classes-of-generic-classes
    • MagicStack/immutables#13
    opened by jab 18
  • bidict should be subclass of dict

    bidict should be subclass of dict

    issubclass(bidict, dict) returns False. We thus cannot pass it to function that test it. If dict were at least at last place of mro it would be settled.

    opened by pacholik 17
  • implement stricter 1-to-1 checking

    implement stricter 1-to-1 checking

    • raise ValueExistsException on insert new key associated with existing value
    • stifled by forceput just like CollapseException was
    • ValueExistsException replaces CollapseException since it's more general
    • rename collapsingbidict loosebidict now that ValueExistsException has replaced CollapseException
    • add forceupdate method for bulk forceput
    • update docs and tests
    opened by jab 12
  • add license title and fix short identifier

    add license title and fix short identifier

    The license title is not strictly required, but it's useful metadata, and part of the recommended license template text:

    • http://choosealicense.com/licenses/isc/
    • https://opensource.org/licenses/isc-license
    • http://spdx.org/licenses/ISC.html#licenseText

    The short identifier has been codified by both SPDX and OSI as "ISC" -- see https://opensource.org/licenses/ISC and http://spdx.org/licenses/ISC.html.

    opened by waldyrious 11
  • New properties

    New properties

    Hi,

    We are working with @hgoldstein95, @bcpierce00, @lemonidas and @seyoungjkim on a mutation testing tool developped as a pytest plugin, called pytest-mutagen. It allows the user to introduce some mutated versions of its functions to check that its test suite catches them.

    It's particularly suited for property-based testing, and that's why we decided to use it on bidict. We found some trivial mutants (like replacing the "clear" or "put" function by just "pass") that were not caught by your test suite, so we added some properties to the existing ones to make sure that they are now caught.

    To witness this you can simply run these commands in the bidict repo (branch new_properties) : python3 -m pip install pytest-mutagen ./run_tests.py --mutate --quick-mut -q

    Therefore we think that these properties could be a relevant addition to yours.

    opened by timpaquatte 10
  • Every bidict creates a reference cycle

    Every bidict creates a reference cycle

    The fact that every bidict creates an holds a reference to its inverse bidict, and each inverse holds a reference to the forward bidict, means that bidicts will create reference cycles.

    This has two implications:

    1. Memory won't be reclaimed immediately if the references are deleted. They will be reclaimed by the garbage collector - but at some later point. Large bidicts could therefore hold memory much longer than a standard dict.
    2. Prior to Python 3.4, any subclasses of bidict that happen to implement __del__() methods won't be garbage collectable at all.

    I'm not sure how important this is, but it's more important the less you know about ways in which bidict is used.

    A workaround might be not to hold a full reference to inv, but to instead hold a weak memoized reference. This would guarantee

    d.inv.inv is d
    

    but would allow immediate reclamation of either side of the bidict pair if no reference to them are held.

    opened by lordmauve 10
  • Missing __all__ in bidict/__init__.py leads to implicit reexport error with mypy in strict mode.

    Missing __all__ in bidict/__init__.py leads to implicit reexport error with mypy in strict mode.

    Hi, Pull request 107 has removed __all__ from bidict/__init__.py.

    This leads to implicit reexports of all the imported classes etc., which generates a error when typechecking with mypy in strict mode (which sets --no-implicit-reexport).

    So for example with test.py...

    from bidict import bidict, BidirectionalMapping
    element_by_symbol: BidirectionalMapping[str, str] = bidict({'H': 'hydrogen'})
    

    ... due to disallowing implicit reexports, the imports will not be found by mypy, while the code obviously works:

    $ mypy --strict .\test.py
    test.py:1: error: Module 'bidict' has no attribute 'bidict'
    test.py:1: error: Module 'bidict' has no attribute 'BidirectionalMapping'; maybe "MutableBidirectionalMapping"?
    Found 2 errors in 1 file (checked 1 source file)
    

    Was there some reasoning behind removing __all__ or could it be re-added? Thanks in advance. :)

    opened by FlorianKoegler 9
  • Add strictbidict that throws exception on any duplicate value assignment

    Add strictbidict that throws exception on any duplicate value assignment

    I see considerable value preventing people accidentally creating mappings that are not invertible. In our codebase, there are several hundred instances of code like

    PRODUCT_REMAP = {... hundreds of lines ...}
    REVERSE_PRODUCT_REMAP = dict((v, k) for k, v in PRODUCT_REMAP.iteritems())
    

    A concern with these is that literals that were accidentally written to include duplicate values would create an incorrect inverse mapping.

    Using bidict does little to improve matters. In code like that below, one of those keys will "win":

    d = bidict({
         'foo': 1,
         ... hundreds of lines ...
         'bar': 1
    })
    

    This has the advantage that the inverse mapping will genuinely reflect the forward mapping, but it carries the disadvantage the mapping for one of the keys is lost. In many cases this is worse - for example, when the forward mapping is fundamental and the inverse mapping is just informational. The only reasonable solution in cases like these is to throw an exception for the programmer to deal with.

    I suggest creating a "strictbidict" in which _put() throws a CollapseException if any value is duplicated, rather than dropping the previous key that maps to that value.

    opened by lordmauve 9
  • Issue #6 multi type hypothesis tests

    Issue #6 multi type hypothesis tests

    opened by tomviner 9
  • Automate upgrading dev dependencies

    Automate upgrading dev dependencies

    Currently, I manually run a script periodically to keep development dependencies up-to-date.

    It looks like https://github.com/marketplace/actions/dependencies-autoupdate could be used to automate this.

    help wanted 
    opened by jab 0
  • logo

    logo

    The old logo is black on a transparent background, and was only designed for use on pages with light backgrounds. The logo is not visible on pages with dark backgrounds, which has become a much more common way for it to be displayed now that GitHub supports dark mode.

    • SVG supports embedded CSS in <style> elements. Can @media (prefers-color-scheme: dark) be used in an SVG to make the same image file look good on both light and dark backgrounds? If so, if we switch the logo from PNGs to SVGs that use this trick, will it work everywhere the logo is displayed?
    • Instead (or in addition), the logo could use other foreground colors that work well on both light and dark backgrounds. Python blue and yellow? (At that point, does it actually need a snake or two? Perhaps encircling a dictionary in a heart shape, or forming { braces around it } (as @lordmauve once mocked up)? A full redesign is not out of scope here :)
    help wanted 
    opened by jab 5
Releases(v0.22.1)
Imports an object based on a string import_string('package.module:function_name')() - Based on werkzeug.utils

DEPRECATED don't use it. Please do: import importlib foopath = 'src.apis.foo.Foo' module_name = '.'.join(foopath.split('.')[:-1]) # to get src.apis.f

Bruno Rocha Archived Projects 11 Nov 12, 2022
1. 네이버 카페 댓글을 빨리 다는 기능

naver_autoprogram 기능 설명 네이버 카페 댓글을 빨리 다는 기능 네이버 카페 자동 출석 체크 기능 동작 방식 카페 댓글 기능 기본 동작은 주기적인 스케쥴 동작으로 해당 카페 ID 와 특정 API 주소로 대상이 새글을 작성했는지 체크. 해당 대상이 새글 등

1 Dec 22, 2021
Timetable scripts for python

Timetable Scripts timetable_to_json: https://beta.elektronplus.pl/timetable classes_taught_by_teacher: a.adam (aa) ['1Tc', '1Td', '3Te', '3Ti', '4Tf',

Elektron++ 2 Jan 02, 2022
Delayed iteration for polling and retries.

Does Python need yet another retry / poll library? It needs at least one that isn't coupled to decorators and functions. Decorators prevent the caller

A. Coady 22 Dec 29, 2022
This code makes the logs provided by Fiddler proxy of the Google Analytics events coming from iOS more readable.

GA-beautifier-iOS This code makes the logs provided by Fiddler proxy of the Google Analytics events coming from iOS more readable. To run it, create a

Rafael Machado 3 Feb 02, 2022
Linux Security and Monitoring Scripts

Linux Security and Monitoring Scripts These are a collection of security and monitoring scripts you can use to monitor your Linux installation for sec

Andre Pawlowski 65 Aug 27, 2022
Small projects for python beginners.

Python Mini Projects For Beginners I recently started doing the #100DaysOfCode Challenge in Python. I've used Python before, but I had switched to JS

Sreekesh Iyer 10 Dec 12, 2022
Code repo for the book "Feature Engineering for Machine Learning," by Alice Zheng and Amanda Casari, O'Reilly 2018

feature-engineering-book This repo accompanies "Feature Engineering for Machine Learning," by Alice Zheng and Amanda Casari. O'Reilly, 2018. The repo

Alice Zheng 1.3k Dec 30, 2022
Remote Worker

Remote Worker Separation of Responsibilities There are several reasons to move some processing out of the main code base for security or performance:

V2EX 69 Dec 05, 2022
MobaXterm-GenKey

MobaXterm-GenKey 你懂的!! 本地启动 需要安装Python3!!!

malaohu 328 Dec 29, 2022
Never get kicked for inactivity ever again!

FFXIV AFK Bot Tired of getting kicked from games due to inactivity? This Bot will make random movements in random intervals to prevent you from gettin

5 Jan 12, 2022
Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

Advent Of Code 2021 - Python English Advent of Code is an Advent calendar of small programming puzzles for a variety of skill sets and skill levels th

Coral Izquierdo Muñiz 2 Jan 09, 2022
Subnet calculator script using python

subnetCalculator Subnet calculator script using python3 Interactive Version Define the subnet variable interactively Use: subnetDict = subnetCalculato

1 Feb 15, 2022
Malicious Document IoC Extractor is a collection of scripts that helps extracting IoCs from various maldoc families.

MDIExtractor Malicious Document IoC Extractor (MDIExtractor) is a collection of scripts that helps extracting IoCs from various maldoc families. Prere

Malwrologist 14 Nov 25, 2022
sawa (ꦱꦮ) is an open source programming language, an interpreter to be precise, where you can write python code using javanese character.

ꦱꦮ sawa (ꦱꦮ) is an open source programming language, an interpreter to be precise, where you can write python code using javanese character. sawa iku

Rony Lantip 307 Jan 07, 2023
A Blender addon for VSE that auto-adjusts video strip's length, if speed effect is applied.

Blender VSE Speed Adjust Addon When using Video Sequence Editor in Blender, the speed effect strip doesn't auto-adjusts clip length when changing its

Arpit Srivastava 2 Jan 18, 2022
Sikulix with Ubuntu Calculator Automation

CalculatorAutomation Sikulix with Ubuntu Calculator Automation STEP 1: DOWNLOAD and INSTALL SIKULIX https://raiman.github.io/SikuliX1/downloads.html T

Bedirhan Sayakci 2 Oct 27, 2021
New multi tool im making adding features currently

Emera Multi Tool New multi tool im making adding features currently Current List of Planned Features - Linkvertise Bypasser - Discord Auto Bump - Gith

Lamp 3 Dec 03, 2021
A bot to use in a pump & dump event

A bot to use in a pump & dump event on Binance.com. Please note the bot is in heavy devleopment currently so be aware of errors. If you experience err

Freddie Jonas 189 Dec 24, 2022
A discord group chat creator just made it because i saw people selling this stuff for like up to 40 bucks

gccreator some discord group chat tools just made it because i saw people selling this stuff for like up to 40 bucks (im currently working on a faster

baum1810 6 Oct 03, 2022