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
《赛马娘》(ウマ娘: Pretty Derby)辅助 🐎🖥 基于 auto-derby 可视化操作/设置 启动器 一键包

ok-derby 《赛马娘》(ウマ娘: Pretty Derby)辅助 🐎 🖥 基于 auto-derby 可视化操作/设置 启动器 一键包 便捷,好用的 auto_derby 管理器! 功能 支持客户端 DMM (前台) 实验性 安卓 ADB 连接(后台)开发基于 1080x1920 分辨率

秋葉あんず 90 Jan 01, 2023
Desenvolvendo as habilidades básicas de programação visando a construção de aplicativos por meio de bibliotecas apropriadas à Ciência de Dados.

Algoritmos e Introdução à Computação Ementa: Conceitos básicos sobre algoritmos e métodos para sua construção. Tipos de dados e variáveis. Estruturas

Dyanna Cruz 1 Jan 06, 2022
PKU team for 2021 project 'Guangchangwu detection'.

PKU team for 2021 project 'Guangchangwu detection'.

Helin Wang 3 Feb 21, 2022
Always fill your package requirements without the user having to do anything! Simple and easy!

WSL Should now work always-fill-reqs-python3 Always fill your package requirements without the user having to do anything! Simple and easy! Supported

Hashm 7 Jan 19, 2022
Official repository for the BPF Performance Tools book

BPF Performance Tools This is the official repository of BPF (eBPF) tools from the book BPF Performance Tools: Linux and Application Observability. Th

Brendan Gregg 1.2k Dec 28, 2022
Neogex is a human readable parser standard, being implemented in Python

Neogex (New Expressions) Parsing Standard Much like Regex, Neogex allows for string parsing and validation based on a set of requirements. Unlike Rege

Seamus Donnellan 1 Dec 17, 2021
A collection of full-stack resources for programmers.

A collection of full-stack resources for programmers.

Charles-Axel Dein 22.3k Dec 30, 2022
A python script for osu!lazer rulesets auto update.

osu-lazer-rulesets-autoupdater A python script for osu!lazer rulesets auto update. How to use: 如何使用: You can refer to the python script. The begining

3 Jul 26, 2022
Collections of python projects

nppy, mostly contains projects written in Python. Some projects are very simple while some are a bit lenghty and difficult(for beginners) Requirements

ghanteyyy 75 Dec 20, 2022
Handwrite - Type in your Handwriting!

Handwrite - Type in your Handwriting! Ever had those long-winded assignments, that the teacher always wants handwritten?

coded 7 Dec 06, 2022
Beancount: Double-Entry Accounting from Text Files.

beancount: Double-Entry Accounting from Text Files Contents Description Documentation Download & Installation Versions Filing Bugs Copyright and Licen

2.3k Dec 28, 2022
Small tool to use hero .json files created with Optolith for The Dark Eye/ Das Schwarze Auge 5 to perform talent probes.

DSA5-ProbeMaker A little tool for The Dark Eye 5th Edition (Das Schwarze Auge 5) to load .json from Optolith character generation and easily perform t

2 Jan 06, 2022
An event-based script that is designed to improve your aim

Aim-Trainer Info: This is an event-based script that is designed to improve a user's aim. It was built using Python Turtle and the Random library. Ins

Ethan Francolla 4 Feb 17, 2022
A Python script to convert your favorite TV series into an Anki deck.

Ankiniser A Python3.8 script to convert your favorite TV series into an Anki deck. How to install? Download the script with git or download it manualy

37 Nov 03, 2022
Palestra sobre desenvolvimento seguro de imagens e containers para a DockerCon 2021 sala Brasil

Segurança de imagens e containers direto na pipeline Palestra sobre desenvolvimento seguro de imagens e containers para a DockerCon 2021 sala Brasil.

Fernando Guisso 10 May 19, 2022
A tool to quickly create codeforces contest directories with templates.

Codeforces Template Tool I created this tool to help me quickly set up codeforces contests/singular problems with templates. Tested for windows, shoul

1 Jun 02, 2022
Tc-python - A Python script to receive message from a twitch chat

Twitch-Chat 📜 I did a script in Python to receive messages from a twitch chat.

miyucode 2 May 31, 2022
A tool to help you to do the monthly reading requirements

Monthly Reading Requirement Auto ⚙️ A tool to help you do the monthly reading requirements Important ⚠️ Some words can't be translated Links: Synonym

Julian Jauk 2 Oct 31, 2021
Aplicação que envia regularmente um email ao utilizador com todos os filmes disponíveis no cartaz dos cinemas Nos.

Cartaz-Cinemas-Nos Aplicação que envia regularmente uma notificação ao utilizador com todos os filmes disponíveis no cartaz dos cinemas Nos. Só funcio

Cavalex 1 Jan 09, 2022
Curso de Python 3 do Básico ao Avançado

Curso de Python 3 do Básico ao Avançado Desafio: Buscador de arquivos Criar um programa que faça a pesquisa de arquivos. É fornecido o caminho e um te

Diego Guedes 1 Jan 21, 2022