Python dictionaries with advanced dot notation access

Overview

BuildStatus License

BoxImage

from box import Box

movie_box = Box({ "Robin Hood: Men in Tights": { "imdb stars": 6.7, "length": 104 } })

movie_box.Robin_Hood_Men_in_Tights.imdb_stars
# 6.7

Box will automatically make otherwise inaccessible keys safe to access as an attribute. You can always pass conversion_box=False to Box to disable that behavior. Also, all new dict and lists added to a Box or BoxList object are converted automatically.

There are over a half dozen ways to customize your Box and make it work for you.

Check out the new Box github wiki for more details and examples!

Install

pip install --upgrade python-box[all]

Box 5 is no longer forcing install of external dependencies such as yaml and toml. Instead you can specify which you want, for example, all is shorthand for:

pip install --upgrade python-box[ruamel.yaml,toml,msgpack]

But you can also sub out "ruamel.yaml" for "PyYAML".

Check out more details on installation details.

Box 5 is tested on python 3.6+ and pypy3, if you are upgrading from previous versions, please look through any breaking changes and new features.

If you have any issues please open a github issue with the error you are experiencing!

Overview

Box is designed to be an easy drop in transparently replacements for dictionaries, thanks to Python's duck typing capabilities, which adds dot notation access. Any sub dictionaries or ones set after initiation will be automatically converted to a Box object. You can always run .to_dict() on it to return the object and all sub objects back into a regular dictionary.

Check out the Quick Start for more in depth details.

Box can be instantiated the same ways as dict.

Box({'data': 2, 'count': 5})
Box(data=2, count=5)
Box({'data': 2, 'count': 1}, count=5)
Box([('data', 2), ('count', 5)])

# All will create
# <Box: {'data': 2, 'count': 5}>

Box is a subclass of dict which overrides some base functionality to make sure everything stored in the dict can be accessed as an attribute or key value.

small_box = Box({'data': 2, 'count': 5})
small_box.data == small_box['data'] == getattr(small_box, 'data')

All dicts (and lists) added to a Box will be converted on lookup to a Box (or BoxList), allowing for recursive dot notation access.

Box also includes helper functions to transform it back into a dict, as well as into JSON, YAML, TOML, or msgpack strings or files.

Thanks

A huge thank you to everyone that has given features and feedback over the years to Box! Check out everyone that has contributed.

A big thanks to Python Software Foundation, and PSF-Trademarks Committee, for official approval to use the Python logo on the Box logo!

Also special shout-out to PythonBytes, who featured Box on their podcast.

License

MIT License, Copyright (c) 2017-2020 Chris Griffith. See LICENSE file.

Comments
  • Regression due to ruamel.yaml

    Regression due to ruamel.yaml

    Potentially dangerous regression in config box, due to the new ruamel.yaml dependency.

    >>> from box import ConfigBox
    >>> b = ConfigBox.from_yaml("kill_all_humans_mode: no")
    >>> if b.kill_all_humans_mode: 
    ...     print("ok, killing all humans...") 
    ...
    ok, killing all humans...
    

    Same problem with box.Box. Our test suite caught this, but others might not be so lucky. ruamel isn't exactly a drop-in replacement for yaml, despite claims to the contrary (ruamel defaults to spec 1.2 and yaml is spec 1.1).

    I would advise to make the toml and ruamel.yaml dependencies optional (or "soft" dependencies, like it was in 3.x) since users might prefer other providers such as pytoml and PyYAML and you don't want to tie their hands here.

    Personally, I can not use box>=4 at all because the ruamel.yaml has an insane installer which, for various reasons, does not work in the prod environment at $EMPLOYER.

    opened by wimglenn 15
  • Add a way to view the last made request to the box (and sub box) objects.

    Add a way to view the last made request to the box (and sub box) objects.

    from box import Box
    
    class test(object):
    	def __init__(self, **kwargs):
    		d = Box({
    		'item':'value', 
    		'item2': self.ok
    		})
    		self.d = d 
    
    	def ok(self, **kwargs):
    		print "test"
    		print kwargs.keys()
    		for key in kwargs.keys():
    			print kwargs[key]
    		return 
    
    data={
    	'test':'value',
    	'test1':'value1'
    }
    
    t = test()
    print t.d.item2(**data)
    

    From t.d.item2 how do I get that path while in the 'ok' function.

    Thanks!

    opened by chavenor 14
  • Box.update is slow

    Box.update is slow

    Is Box.update supposed to be much slower than dict.update? I expected the performance to be comparable, and ran into trouble. The code below shows the timing for dict.update and Box. .update

    import random
    import box
    import string
    import time
    
    def random_string(N):
        return ''.join(random.choices(string.ascii_uppercase + string.digits, k=N))
    
    
    a = dict((random_string(64), 0) for i in range(10**3))
    for i in a:
        a[i.upper()] = 0
    
    b = box.Box(dict((random_string(64), 0) for i in range(10)))
    c = dict((random_string(64), 0) for i in range(10))
    
    st = time.time()
    c.update(a)
    et = time.time()
    print(et - st)
    
    st = time.time()
    b.update(a)
    et = time.time()
    print(et - st)
    

    Output:

    2.09808349609375e-05
    4.840667724609375
    

    With

    Python 3.7.5 (default, Nov  1 2019, 02:16:32) 
    [Clang 11.0.0 (clang-1100.0.33.8)] on darwin
    
    bug 
    opened by jkylling 10
  • Update() is broken as of 3.4.3

    Update() is broken as of 3.4.3

    Given this sample code:

    import box
    
    if __name__ == '__main__':
        b = box.Box({
            'one': {
                'sub1': 'monkey',
                'sub2': 'goat',
            }
        }, box_it_up = True)
    
        print(f'box: {b}')
        print(f'one is a {type(b.one)}')
        print(f'expect monkey: {b.one.sub1}')
        print(f'expect goat: {b.one.sub2}')
                
        b.update({'one': {'sub2': 'alpaca'}})
        print(f'one is a {type(b.one)}')
        print(f'expect monkey: {b.one.sub1}')
        print(f'expect alpaca: {b.one.sub2}')
    

    It works with < 3.4.3:

    box: {'one': {'sub1': 'monkey', 'sub2': 'goat'}}
    one is a <class 'box.Box'>
    expect monkey: monkey
    expect goat: goat
    one is a <class 'box.Box'>
    expect monkey: monkey
    expect alpaca: alpaca
    

    But using >= 3.4.3, this is the result:

    box: {'one': {'sub1': 'monkey', 'sub2': 'goat'}}
    one is a <class 'box.Box'>
    expect monkey: monkey
    expect goat: goat
    one is a <class 'dict'>
    Traceback (most recent call last):
      File "./test.py", line 16, in <module>
        print(f'expect monkey: {b.one.sub1}')
    AttributeError: 'dict' object has no attribute 'sub1'
    

    I notice there were changes to the update() method.

    (edited: added some code to print out the types, which show the difference)

    bug 
    opened by alertedsnake 10
  • Bug/camel killer conflicts

    Bug/camel killer conflicts

    Partially solves #46 . I have limited time today so I only fixed the default_box + camel_killer issue.

    Now, "camel-killed" attributes will be looked up before the default_box logic is used.

    I've added regression test for this case.

    opened by matan129 9
  • Allowed characters in keys

    Allowed characters in keys

    Would you please explain the rationale behind allowing only string.ascii_letters + string.digits + "_" in keys? I would like to use greek letters and end up with silent errors like:

    >>> a = Box()
    >>> a.σeq = 1
    >>> a.µeq = 2
    >>> a
    <Box: {'σeq': 2}>
    

    Is there anything wrong with adding more utf-8 characters to allowed?

    enhancement 
    opened by eevleevs 8
  • flatten dot keys

    flatten dot keys

    I have implemented support for dot keys by sub-classing Box and using it for two years by now. Among other things it provides an alternative data model which essentially flattens the hierarchy - a useful approach in certain cases. To fully support this model I needed to allow also flat iteration over the data elements. It was implemented by adding optional parameter in keys and items and values members.

    For example, for keys:

    def keys(self, depth=False):
        ...
    

    So that

    box.keys(depth=True)
    # ['a.b.c', 'a.b.d', 'a.x.y']
    

    That makes the 'flat' model complete and can be implemented with minimal code and performance overhead.

    Do you think it could be generic enough to include into the package?

    opened by ipcoder 8
  • Add `box_intact_types`

    Add `box_intact_types`

    #78

    from box import Box
    
    class MyList(list): 
        def sq(self):
            return [x*x for x in self]
    	
    b = Box(a = MyList([1,2,4]), box_intact_types = (MyList, ))
    b.a.sq()
    # [1,4,16]
    
    opened by pwwang 8
  • Issues #46 & #48

    Issues #46 & #48

    Wow, sorry this took so long to get around to (new job, life, etc...).

    @matan129 and @polishmatt, Thank you for finding those bugs and code contributions to fix them. I needed to modify how they were handled and this PR happens to (hopefully) handle both those issues.

    If you could both please look at the last file, the tests, and just make sure that your respective bug would be caught with it, would be much appreciated.

    bug 
    opened by cdgriffith 8
  • ModuleNotFoundError: No module named 'box'

    ModuleNotFoundError: No module named 'box'

    I get the following error when I have this line in my code: from box import Box

    ModuleNotFoundError: No module named 'box'

    I've installed on RasPi Zero using pip3 install box. Also tried the regular pip install box.

    Am running Python 3 3.7.3

    Am I missing something obvious?

    Thanks, Ken

    opened by kwalkerk 7
  • Treat None values as unexisting keys for default_box

    Treat None values as unexisting keys for default_box

    Hi,

    thanks a lot for your project, it's currently helping me a lot :) one feature i missed is the ability to treat None values as if there was no key defined.

    like in this example.

    b=Box({'brol': None}, default_box=True)
    b.brol.truc
    

    gives

    Traceback (most recent call last): File "", line 1, in AttributeError: 'NoneType' object has no attribute 'truc'

    but this works as exepected

    b=Box({}, default_box=True)
    b.brol.truc
    

    many many thanks 👍

    enhancement 
    opened by eMerzh 7
  • `__add__` and `__or__` operators for frozen boxes

    `__add__` and `__or__` operators for frozen boxes

    Frozen boxes are great for enforcing a functional style of programming at runtime. But the implementation of Box.__add__ assumes that the left-hand side is non-frozen.

    The following piece of code fails in box/box.py:274: box.box.Box.__add__ with box.exceptions.BoxError: Box is frozen

    foo = box.Box(frozen_box=True)
    foobar = foo + {"bar": 1}
    

    As far as I can judge, there is no reason to restrict __add__ (and __or__) operations to non-frozen boxes. The implementation of Box.__add__ creates a copy of the input box before merging/updating, thus the operations leave the input boxes unmodified.

    This implementation of Box.__or__ would solve the issue:

    ...
    new_box = other.copy()
    new_box._box_config["frozen_box"] = False
    new_box.update(other)
    new_box._box_config["frozen_box"] = other._box_config["frozen_box"]
    ...
    

    I've made a quick check that this works for flat and nested structures. But there might be some unintended side effects for nested structures. But this would be an issue even for non-frozen boxes. I guess most programmers will assume that writing foobar = foo + {"bar": 1} won't mutate foo.

    What are the objections against frozen boxes in Box.__add__ (Box.__or__)? And, how should this be implemented?

    opened by barmettl 0
  • Keys method with (dotted=True) gives multiplication of the same key

    Keys method with (dotted=True) gives multiplication of the same key

    Bug of keys in Box:

    When you use keys() method in a "dotted" situation, meaning we have a tree of keys in a Box, and you want to get the keys of a given node, one can notice that we get back a list of keys that are multiplicated if the value of a key is a list. (and the multiplication is by the lengh of the list)

    For example:

     

    b = Box({
    "Animals" : {"Land_animals" : ["Lion", "Elephant"], "Sea_animals" : ["Dolphin", "Shark"]},
    "Trees" : ["Palm_tree", "Coconut_tree"]
    }, box_dots = True)
    
     
    

    When you are using keys = b.keys(dotted = True) you get -

    ['Animals.Land_animals[0]',
    'Animals.Land_animals[1]',
    'Animals.Sea_animals[0]',
    'Animals.Sea_animals[1]',
    'Trees[0]',
    'Trees[1]']
    
    

    and we can see the multiple occurances of the keys (with indexes of their number of values), and the method len(keys) would have wrong answer - 6 instead of 3.

    The output which I thought would be right is: ['Animals.Land_animals', 'Animals.Sea_animals', 'Trees']

     

    A workaround is to add to the box this:

    box_intact_types = (tuple,list)

    so that lists wouldn't be converted, and than it works fine.

    wontfix 
    opened by aviveh21 1
  • Using help (`?`) with `default_box=True` unintentionally adds a key

    Using help (`?`) with `default_box=True` unintentionally adds a key

    Box is really useful when accessing non-existing keys/attributes and assigning new keys on them e.g. box.foo.bar.baz = 1.

    Noting down here an issue I have found. When IPython's help using ? is called it adds a key getdoc in Box object.

    Version

    python-box v6.1.0

    Reproducer

    box-repro

    Cause

    This seems expected and is a side-effect of this line in IPython which tries a find a custom method getdoc() to get docstring for an object.

    Is there a workaround here?

    opened by nishikantparmariam 1
  • Breaking convention with __or__/ __ror__ dunder methods

    Breaking convention with __or__/ __ror__ dunder methods

    Hi,

    An __or__ method is not meant to be cumulative, as we know. In box-box operations new_box = box_1 | box_2 , everything is working properly That said, new_boxwould be different if we would write new_box = box_2 | box_1

    The same is with dictionaries ( as introduced in PEP 584), and dict-dict operations.

    The problem starts when you combine Box with a dict in an __or__/__ror__ method, for example new_box = box_1 | dict_1.

    You can check that:

    new_box1 = box_1 | dict_1 , new_box2 = dict_1 | box_1

    And you get that - new_box1 **==** new_box2

    As opposed to the noncumulative attribute of OR operation in Dicts and Boxes.

    If you would make the change: new_box1 = box_1 | Box(dict_1) , new_box2 = Box(dict_1) | box_1

    you would get - new_box1 **!=** new_box2.

    But that means that you can't do box operations with normal dicts (at least with OR dunder method)

    opened by aviveh21 0
  • Two small typos in Wiki / Types of Boxes

    Two small typos in Wiki / Types of Boxes

    Hello,


    I noticed two small typos on the Wiki page Types of Boxes:

    Types of Boxes / Box Dots

    Support for traversing box lists as well!

    my_box = Box({'data': [ {'rabbit': 'hole'} ] }, box_dots=True)
    print(data.data[0].rabbit)
    # hole
    

    To change

    my_box = Box({'data': [ {'rabbit': 'hole'} ] }, box_dots=True)
    - print(data.data[0].rabbit)
    + print(my_box.data[0].rabbit)
    # hole
    

    Types of Boxes / Box Recast Values

    If it cannot be converted, it will raise a BoxValueError (catachable with either BoxError or ValueError as well)

    To change

    - If it cannot be converted, it will raise a `BoxValueError` (catachable with either `BoxError` or `ValueError` as well)
    + If it cannot be converted, it will raise a `BoxValueError` (catchable with either `BoxError` or `ValueError` as well)
    

    Thank you for your work on the Box library and kind regards Martin

    opened by schorfma 2
  • Support for tracking the box

    Support for tracking the box "namespace"

    I have some nested Boxes using an overridden __convert_and_store in a subclass to convert values to an expected type (eg: I want all values to be an int or some other custom class). For that conversion, I would like to know the "namespace" of the Box/value in order to reference it in the conversion and show nicer error messages.

    For example, when handling the conversion of 5 in the example below:

    box = MyBox({"a": {"b": {"c": 5}}})
    

    I would like to know that I'm assigning to ("a", "b", "c").

    This is quite hard to setup only in a subclass because of the recursive value conversion (and copying) during __init__ and conversion doesn't give a good hook to intercept after the box is created, but before sub-boxes are created.

    I think the easiest way to support this is by adding a box_path or box_namespace param to __init__ (defaulting to ()) and then into _box_config, which can be passed through (and extended) in __get_default and __convert_and_store when creating sub-boxes.

    Is this something you'd be open to? I'd be happy to make a PR for this if so!

    enhancement 
    opened by JacobHayes 2
Releases(6.1.0)
  • 6.1.0(Oct 29, 2022)

    • Adding Python 3.11 support
    • Adding #195 box_from_string function (thanks to Marcelo Huerta)
    • Changing the deprecated toml package with modern tomllib, tomli and tomli-w usage (thanks to Michał Górny)
    • Fixing mypy ior type (thanks to Jacob Hayes)
    • Fixing line endings with a pre-commit update
    • Fixing BoxList was using old style of super in internal code usage

    Co-authored-by: Jacob Hayes [email protected] Co-authored-by: Michał Górny [email protected]

    Source code(tar.gz)
    Source code(zip)
  • 6.0.2(Apr 2, 2022)

  • 6.0.1(Mar 16, 2022)

    • Fixing #218 Box dots would not raise KeyError on bad key (thanks to Cliff Wells)
    • Fixing #217 wording in readme overview needed updated (thanks to Julie Jones)
    Source code(tar.gz)
    Source code(zip)
  • 6.0.0(Mar 15, 2022)

    • Adding Cython support to greatly speed up normal Box operations on supported systems
    • Adding #161 support for access box dots with get and checking with in (thanks to scott-createplay)
    • Adding #183 support for all allowed character sets (thanks to Giulio Malventi)
    • Adding #196 support for sliceable boxes (thanks to Dias)
    • Adding #164 default_box_create_on_get toggle to disable setting box variable on get request (thanks to ipcoder)
    • Changing #208 repr to produce eval-able text (thanks to Jeff Robbins)
    • Changing #215 support ruamel.yaml new syntax (thanks to Ivan Pepelnjak)
    • Changing update and merge_update to not use a keyword that could cause issues in rare circumstances
    • Changing internal _safe_key logic to be twice as fast
    • Removing support for ruamel.yaml < 0.17
    Source code(tar.gz)
    Source code(zip)
  • 6.0.0rc4(Feb 12, 2022)

  • 6.0.0rc3(Jan 23, 2022)

    • Add ability to set attributes to ruamel.yaml class
    • Fix pytest working with underscore functions
    • Fix for pyinstaller
    • Fix python publish version issues
    Source code(tar.gz)
    Source code(zip)
  • 6.0.0rc2(Jan 21, 2022)

  • 6.0.0rc1(Jan 21, 2022)

    • Adding Cython support to greatly speed up normal Box operations on supported systems
    • Adding #161 support for access box dots with get and checking with in (thanks to scott-createplay)
    • Adding #183 support for all allowed character sets (thanks to Giulio Malventi)
    • Adding #196 support for sliceable boxes (thanks to Dias)
    • Changing #208 repr to produce eval-able text (thanks to Jeff Robbins)
    • Changing #215 support ruamel.yaml new syntax (thanks to Ivan Pepelnjak)
    • Changing update and merge_update to not use a keyword that could cause issues in rare circumstances
    • Fixing internal _safe_key logic to be twice as fast
    • Removing support for 3.6 as it is EOL
    • Removing support for ruamel.yaml < 0.17

    This is a pre-release and under testing, do not use in production

    Source code(tar.gz)
    Source code(zip)
  • 5.4.1(Aug 22, 2021)

  • 5.4.0(Aug 15, 2021)

    • Adding py.typed for mypy support (thanks to Dominic)
    • Adding testing for Python 3.10-dev
    • Fixing #189 by adding mappings for mypy
    • Fixing setdefault behavior with box_dots (thanks to ipcoder)
    • Changing #193 how magic methods are handled with default_box (thanks to Rexbard)
    Source code(tar.gz)
    Source code(zip)
  • 5.3.0(Feb 13, 2021)

    • Adding support for functions to box_recast (thanks to Jacob Hayes)
    • Adding #181 support for extending or adding new items to list during merge_update (thanks to Marcos Dione)
    • Fixing maintain stacktrace cause for BoxKeyError and BoxValueError (thanks to Jacob Hayes)
    • Fixing #177 that emtpy yaml files raised errors instead of returning empty objects (thanks to Tim Schwenke)
    • Fixing #171 that popitems wasn't first checking if box was frozen (thanks to Varun Madiath)
    Source code(tar.gz)
    Source code(zip)
  • 5.2.0(Oct 29, 2020)

    • Adding checks for frozen boxes to pop, popitem and clear (thanks to Varun Madiath)
    • Fixing requirements-test.txt (thanks to Fabian Affolter)
    • Fixing Flake8 conflicts with black (thanks to Varun Madiath)
    • Fixing coveralls update (thanks to Varun Madiath)
    Source code(tar.gz)
    Source code(zip)
  • 5.1.1(Aug 20, 2020)

  • 5.1.0(Jul 23, 2020)

    • Adding dotted option for items function (thanks to ipcoder)
    • Fixing bug in box.set_default where value is dictionary, return the internal value and not detached temporary (thanks to Noam Graetz)
    • Removing warnings on import if optional libraries are missing
    Source code(tar.gz)
    Source code(zip)
  • 5.0.1(Jul 13, 2020)

  • 5.0.0(Jul 12, 2020)

    • Adding support for msgpack converters to_msgpack and from_msgpack
    • Adding support for comparision of Box to other boxes or dicts via the - sub operator #144 (thanks to Hitz)
    • Adding support to | union boxes like will come default in Python 3.9 from PEP 0584
    • Adding mypy type checking, black formatting and other checks on commit
    • Adding new parameter box_class for cleaner inheritance #148 (thanks to David Aronchick)
    • Adding dotted option for keys method to return box_dots style keys (thanks to ipcoder)
    • Fixing box_dots to properly delete items from lists
    • Fixing box_dots to properly find items with dots in their key
    • Fixing that recast of subclassses of Box or BoxList were not fed box properties (thanks to Alexander Kapustin)
    • Changing that sub boxes are always created to properly propagate settings and copy objects #150 (thanks to ipcoder)
    • Changing that default_box will not raise key errors on pop #67 (thanks to Patrock)
    • Changing to_csv and from_csv to have same string and filename options as all other transforms
    • Changing back to no required external imports, instead have extra requires like [all] (thanks to wim glenn)
    • Changing from putting all details in README.rst to a github wiki at https://github.com/cdgriffith/Box/wiki
    • Changing BoxList.box_class to be stored in BoxList.box_options dict as box_class
    • Changing del will raise BoxKeyError, subclass of both KeyError and BoxError
    • Removing support for single level circular references
    • Removing readthedocs generation
    • Removing overrides for keys, values and items which will return views again
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0.a2(Jul 3, 2020)

  • 5.0.0a1(Jun 15, 2020)

    • Adding dotted and flat option for keys method to return box_dots style keys (thanks to ipcoder)
    • Fixing box_dots to properly delete items from lists
    • Fixing box_dots to properly find items with dots in their key
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0a0(Apr 27, 2020)

    • Adding support for msgpack coverters to_msgpack and from_msgpack
    • Adding support for comparision of Box to other boxes or dicts via the - sub operator #144 (thanks to Hitz)
    • Adding support to | union boxes like will come default in Python 3.9 from PEP 0584
    • Adding mypy type checking, black formatting and other checks on commit
    • Adding new parameter box_class for cleaner inheritance #148 (thanks to David Aronchick)
    • Changing that sub boxes are always created to properly propagate settings and copy objects #150 (thanks to ipcoder)
    • Changing that default_box will not raise key errors on pop or del #67 (thanks to Patrock)
    • Changing to_csv and from_csv to have same string and filename options as all other transforms
    • Changing back to no required external imports
    • Changing from putting all details in README.rst to a github wiki at https://github.com/cdgriffith/Box/wiki
    • Changing BoxList.box_class to be stored in BoxList.box_options dict as box_class
    • Removing support for single level circular references
    • Removing readthedocs generation
    • Removing overrides for keys, values and items which will return views again
    Source code(tar.gz)
    Source code(zip)
  • 4.2.3(Apr 27, 2020)

    • Fixing README.md example #149 (thanks to J Alan Brogan)
    • Changing protected_keys to remove magic methods from dict #146 (thanks to Krishna Penukonda)
    Source code(tar.gz)
    Source code(zip)
  • 4.2.2(Mar 11, 2020)

    • Fixing default_box doesn't first look for safe attributes before falling back to default (thanks to Pymancer)
    • Changing from TravisCI to Github Actions
    Source code(tar.gz)
    Source code(zip)
  • 4.2.1(Feb 29, 2020)

  • 4.2.0(Feb 26, 2020)

    • Adding optimizations for speed ups to creation and inserts
    • Adding internal record of safe attributes for faster lookups, increases memory footprint for speed (thanks to Jonas Irgens Kylling)
    • Adding all additional methods specific to Box as protected keys
    • Fixing merge_update from incorrectly calling __setattr__ which was causing a huge slowdown (thanks to Jonas Irgens Kylling)
    • Fixing copy and __copy__ not copying box options
    Source code(tar.gz)
    Source code(zip)
  • 4.1.0(Feb 22, 2020)

    • Adding support for list traversal with box_dots (thanks to Lei)
    • Adding BoxWarning class to allow for the clean suppression of warnings
    • Fixing default_box_attr to accept items that evaluate to None (thanks to Wenbo Zhao and Yordan Ivanov)
    • Fixing BoxList to properly send internal box options down into new lists
    • Fixing issues with conversion and camel killer boxes not being set properly on insert
    • Changing default_box to set objects in box on lookup
    • Changing camel_killer to convert items on insert, which will change the keys when converted back to dict unlike before
    • Fallback to PyYAML if ruamel.yaml is not detected (thanks to wim glenn)
    • Removing official support for pypy as it's pickling behavior is not the same as CPython
    • Removing internal __box_heritage as it was no longer needed due to behavior update
    Source code(tar.gz)
    Source code(zip)
  • 4.0.4(Dec 29, 2019)

  • 4.0.3(Dec 26, 2019)

  • 4.0.2(Dec 26, 2019)

  • 4.0.1(Dec 25, 2019)

  • 4.0.0(Dec 25, 2019)

    • Adding support for retrieving items via dot notation in keys
    • Adding box_from_file helper function
    • Adding merge_update that acts like previous Box magic update
    • Adding support to + boxes together
    • Adding default_box now can support expanding on None placeholders (thanks to Harun Tuncay and Jeremiah Lowin)
    • Adding ability to recast specified fields (thanks to Steven McGrath)
    • Adding to_csv and from_csv capability for BoxList objects (thanks to Jiuli Gao)
    • Changing layout of project to be more object specific
    • Changing update to act like normal dict update
    • Changing to 120 line character limit
    • Changing how safe_attr handles unsafe characters
    • Changing all exceptions to be bases of BoxError so can always be caught with that base exception
    • Changing delete to also access converted keys (thanks to iordanivanov)
    • Removing ordered_box as Python 3.6+ is ordered by default
    • Removing BoxObject in favor of it being another module
    Source code(tar.gz)
    Source code(zip)
Owner
Chris Griffith
Staff Software Engineer
Chris Griffith
An Embedded Linux Project Build and Compile Tool -- An Bitbake UI Extension

Dianshao - An Embedded Linux Project Build and Compile Tool

0 Mar 27, 2022
An Airdrop alternative for cross-platform users only for desktop with Python

PyDrop An Airdrop alternative for cross-platform users only for desktop with Python, -version 1.0 with less effort, just as a practice. ##############

Bernardo Olisan 6 Mar 25, 2022
Basic infrastructure for writing scripts in Python

Base Script Python is an excellent language that makes writing scripts very straightforward. Over the course of writing many scripts, we realized that

Deep Compute, LLC 9 Jan 07, 2023
Integration between the awesome window manager and the firefox web browser.

Integration between the awesome window manager and the firefox web browser.

contribuewwt 3 Feb 02, 2022
Reproduction repository for the MDX 2021 Hybrid Demucs model

Submission This is the submission for MDX 2021 Track A, for Track B go to the track_b branch. Submission Summary Submission ID: 151378 Submitter: defo

Alexandre Défossez 62 Dec 18, 2022
Very efficient backup system based on the git packfile format, providing fast incremental saves and global deduplication

Very efficient backup system based on the git packfile format, providing fast incremental saves and global deduplication (among and within files, including virtual machine images). Current release is

bup 6.9k Dec 27, 2022
Robotic hamster to give you financial advice

hampp Robotic hamster to give you financial advice. I am not liable for any advice that the hamster gives. Follow at your own peril. Description Hampp

1 Nov 17, 2021
Simple calculator with random number button and dark gray theme created with PyQt6

Calculator Application Simple calculator with random number button and dark gray theme created with : PyQt6 Python 3.9.7 you can download the dark gra

Flamingo 2 Mar 07, 2022
This library attempts to abstract the handling of Sigma rules in Python

This library attempts to abstract the handling of Sigma rules in Python. The rules are parsed using a schema defined with pydantic, and can be easily loaded from YAML files into a structured Python o

Caleb Stewart 44 Oct 29, 2022
NFT generator for Solana!

Solseum NFT Generator for Solana! Check this guide here! Creating your randomized uniques NFTs, getting rarity information and displaying it on a webp

Solseum™ VR NFTs 145 Dec 30, 2022
ToDoListAndroid - To-do list application created using Kivymd

ToDoListAndroid To-do list application created using Kivymd. Version 1.0.0 (1/Jan/2022). Planned to do next: -Add setting (theme selector, etc) -Add f

AghnatHs 1 Jan 01, 2022
Time tracking program that will format output to be easily put into Gitlab

time_tracker Time tracking program that will format output to be easily put into Gitlab. Feel free to branch and use it yourself! Getting Started Clon

Jake Strasler 2 Oct 13, 2022
A project to find out all the words in a crossword.

A project to find out all the words in a crossword.

Kalpesh Dhoundiyal 1 Feb 06, 2022
A Python 3 client for the beanstalkd work queue

Greenstalk Greenstalk is a small and unopinionated Python client library for communicating with the beanstalkd work queue. The API provided mostly map

Justin Mayhew 67 Dec 08, 2022
A PG3D API Made with Python

PG3D Python API A Pixel Gun 3D Python API (Public Ver) Features Count: 29 How To Use? import api as pbn Examples pbn.isBanned(192819483) - True pbn.f

Karim 2 Mar 24, 2022
The Begin button and menu for the Meadows operating system. The start button for UNIX/Linux.

By: Seanpm2001, Meadows Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af Afrikaans Afri

Sean P. Myrick V19.1.7.2 4 Aug 28, 2022
Google Scholar App Using Python

Google Scholar App Watch the tutorial video How to build a Google Scholar App | Streamlit #30 Demo Launch the web app: Reproducing this web app To rec

Chanin Nantasenamat 4 Jun 05, 2022
An integrated library for checking email if it is registered on social media

An integrated library for checking email if it is registered on social media

Sidra ELEzz 13 Dec 08, 2022
Implements a polyglot REPL which supports multiple languages and shared meta-object protocol scope between REPLs.

MetaCall Polyglot REPL Description This repository implements a Polyglot REPL which shares the state of the meta-object protocol between the REPLs. Us

MetaCall 10 Dec 28, 2022
Push a record and you will receive a email when that date

Push a record and you will receive a email when that date

5 Nov 28, 2022