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
edgetest is a tox-inspired python library that will loop through your project's dependencies, and check if your project is compatible with the latest version of each dependency

Bleeding edge dependency testing Full Documentation edgetest is a tox-inspired python library that will loop through your project's dependencies, and

Capital One 16 Dec 07, 2022
A python program, imitating functionalities of a banking system

A python program, imitating functionalities of a banking system, in order for users to perform certain operations in a bank.

Moyosore Weke 1 Nov 26, 2021
Simple dotfile pre-processor with a per-file configuration

ix (eeks) Simple dotfile pre-processor with a per-file configuration Summary (TL;DR) ix.py is all you need config is an ini file. files to be processe

Poly 12 Dec 16, 2021
pvaPy provides Python bindings for EPICS pvAccess

PvaPy - PvAccess for Python The PvaPy package is a Python API for EPICS7. It supports both PVA and CA providers, all standard EPICS7 types (structures

EPICS Base 25 Dec 05, 2022
A simple script for generating screenshots with Vapoursynth

Vapoursynth-Screenshots A simple script for generating screenshots with Vapoursynth. About I'm lazy, and hate changing variables for each batch of scr

7 Dec 31, 2022
jonny is a stack based programming language

jonny-lang jonny is a stack based programming language also compiling jonny files currently doesnt work on windows you can probably compile jonny file

1 Nov 24, 2021
GCP Scripts and API Client Toolss

GCP Scripts and API Client Toolss Script Authentication The scripts and CLI assume GCP Application Default Credentials are set. Credentials can be set

3 Feb 21, 2022
laTEX is awesome but we are lazy -> groff with markdown syntax and inline code execution

pyGroff A wrapper for groff using python to have a nicer syntax for groff documents DOCUMENTATION Very similar to markdown. So if you know what that i

Subhaditya Mukherjee 27 Jul 23, 2022
jmespath.rs Python binding

rjmespath-py jmespath.rs Python binding.

messense 3 Dec 14, 2022
Results of Robot Framework 5.0 survey

Robot Framework 5.0 survey results We had a survey asking what features Robot Framework community members would like to see in the forthcoming Robot F

Pekka Klärck 2 Oct 16, 2021
Improved version calculator, now using while True and etc

CalcuPython_2.0 Olá! Calculadora versão melhorada, agora usando while True e etc... melhorei o design e os carai tudo (rode no terminal, pra melhor ex

Scott 2 Jan 27, 2022
Defichain maxi - Scripts to optimize performance on defichain rewards

defichain_maxi This script is made to optimize your defichain vault rewards by m

kuegi 75 Dec 31, 2022
Using Python to parse through email logs received through several backup systems.

outlook-automated-backup-control Backup monitoring on a mailbox: In this mailbox there will be backup logs. The identification will based on the follo

Connor 2 Sep 28, 2022
API to summarize input text

summaries API to summarize input text normal run $ docker-compose exec web python -m pytest disable warnings $ docker-compose exec web python -m pytes

Brad 1 Sep 08, 2021
An easy way to access to your EPITECH subjects based on the Roslyn's database.

An easy way to access to your EPITECH subjects based on the Roslyn's database.

Mathias 1 Feb 09, 2022
Python script which synchronizes the replica-directoty with the original-one.

directories_synchronizer Python script which synchronizes the replica-directoty with the original-one. Automatically detects all changes when script i

0 Feb 13, 2022
Random Turkish name generator with realistic probabilities.

trnames Random Turkish name generator with realistic probabilities. Based on Trey Hunner's names package. Installation The package can be installed us

Kaan Öztürk 20 Jan 02, 2023
A tool to allow New World players to calculate the best place to put their Attribute Points for their build and level

New World Damage Simulator A tool designed to take a characters base stats including armor and weapons, level, and base damage of their items (slash d

Joseph P Langford 31 Nov 01, 2022
Hypothesis strategies for generating Python programs, something like CSmith

hypothesmith Hypothesis strategies for generating Python programs, something like CSmith. This is definitely pre-alpha, but if you want to play with i

Zac Hatfield-Dodds 73 Dec 14, 2022
Synthetik Python Mod - A save editor tool for the game Synthetik written in python

Synthetik_Python_Mod A save editor tool for the game Synthetik written in python

2 Sep 10, 2022