{"id":1448,"library":"deepmerge","title":"Deepmerge","description":"deepmerge is a Python library providing a toolset for deeply merging Python dictionaries, handling nested structures, lists, and various data types with configurable strategies. The current stable version is 2.0, released recently with Python 3.8+ support. The library maintains a stable API, with new versions focusing on type hints, bug fixes, and minor enhancements.","status":"active","version":"2.0","language":"en","source_language":"en","source_url":"https://github.com/toumorokoshi/deepmerge","tags":["dictionary","merge","configuration","utilities","data-structure"],"install":[{"cmd":"pip install deepmerge","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Requires Python 3.8 or newer as of deepmerge v2.0.","package":"python","optional":false}],"imports":[{"note":"The default, most commonly used merger instance for deep merging dictionaries.","symbol":"always_merger","correct":"from deepmerge import always_merger"},{"note":"Used to create custom merger instances with specific strategies for different data types.","symbol":"Merger","correct":"from deepmerge import Merger"}],"quickstart":{"code":"from deepmerge import always_merger\n\ndict1 = {\n    \"name\": \"Alice\",\n    \"settings\": {\"theme\": \"dark\", \"notifications\": True},\n    \"tags\": [\"user\", \"admin\"]\n}\ndict2 = {\n    \"name\": \"Bob\",\n    \"settings\": {\"notifications\": False, \"language\": \"en\"},\n    \"tags\": [\"active\"]\n}\n\n# By default, always_merger modifies the first dict passed (or a copy).\n# To keep dict1 unchanged, merge into an empty dict or a deep copy of dict1.\nmerged_dict = always_merger.merge({}, dict1, dict2)\n\nprint(merged_dict)\n# Expected output for tags: ['user', 'admin', 'active'] (default list_extend_strategy)\n# Expected output for settings: {'theme': 'dark', 'notifications': False, 'language': 'en'}\n","lang":"python","description":"This example demonstrates how to use the default `always_merger` to combine two dictionaries. Nested dictionaries are merged recursively, and lists are extended by default (elements from the second list are appended to the first). It's crucial to understand that `always_merger.merge(a, b)` modifies `a` in-place, so passing `{}`, `copy.copy(a)`, or `copy.deepcopy(a)` as the first argument is often necessary to prevent unintended side effects on the original dictionary."},"warnings":[{"fix":"Upgrade your Python environment to 3.8+ or pin `deepmerge` to a version prior to 2.0 (e.g., `pip install 'deepmerge<2.0'`).","message":"Deepmerge v2.0 dropped support for Python versions older than 3.8. Projects still using Python 3.7 or earlier must pin `deepmerge<2.0`.","severity":"breaking","affected_versions":"2.0+"},{"fix":"Review any custom merge strategies or type-sensitive code after upgrading. Ensure your custom strategies correctly handle expected input and output types according to the new type hints.","message":"Version 2.0 introduced extensive type hinting. While this generally improves static analysis, if you have custom merge strategies or logic that relied on implicit type coercions or incorrect type assumptions, your code might now fail type checks or behave differently when used with type-aware tools like MyPy.","severity":"breaking","affected_versions":"2.0+"},{"fix":"Always pass a fresh dictionary (`{}`) or a deep copy (`copy.deepcopy(original_dict)`) as the first argument if the original dictionary must remain unchanged.","message":"The default `always_merger.merge(destination, source1, source2, ...)` modifies the `destination` dictionary in-place. If you intend to preserve the original `destination` dictionary, you must provide a copy (e.g., `always_merger.merge({}, original_dict, new_data)` or `always_merger.merge(copy.deepcopy(original_dict), new_data)`).","severity":"gotcha","affected_versions":"all"},{"fix":"To replace lists, initialize `Merger` with an 'override' strategy for lists: `my_merger = Merger([(list, ['override'])])`. To customize further, define your own list strategy function.","message":"The default list merging strategy for `always_merger` is `list_extend_strategy`, which appends elements from the source list to the destination list. If you expect lists to be overwritten/replaced or merged differently, you need to configure a custom `Merger` instance.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}