Skip to main content

Python dictionaries with recursive dot notation access

Project description

Box

Python dictionaries with recursive dot notation access.

from box import Box

my_box = Box(
    {"owner": "Mr. Powers",
     "contents": [{"qty": 1, "item": "blue crushed-velvet suit"},
                  {"qty": 1, "item": "frilly lace crava"},
                  {"qty": 1, "item": "gold medallion with peace symbol"},
                  {"qty": 1, "item": "Swedish-made enlarger pump"},
                  {"qty": 1, "item": "credit card receipt for Swedish-made enlarger pump, "
                                     "signed Austin Powers."},
                  {"qty": 1, "item": "warranty card for Swedish-made enlarger pump, "
                                     "filled out by Austin Powers."},
                  {"qty": 1, "item": "book, Swedish-Made Enlarger Pumps and Me"}],
     "affiliates": {
         "Vanessa": "Sexy",
         "Dr Evil": "Not groovy",
         "Scott Evil": "Doesn't want to take over family business"}
    })

my_box.affiliates.Vanessa == my_box['affiliates']['Vanessa']

my_box.contents[0].item
'blue crushed-velvet suit'

# Here's something that no other library supports (that I know of)
# Automatic creation of Boxes in sub-lists
my_box.contents.append({"qty": 1, "item": "tie-dyed socks"})
my_box.contents[-1].item
'tie-dyed socks'

# Box object is callable, and returns a tuple of available keys
my_box()
('owner', 'contents', 'affiliates')

my_box.funny_line = "They tried to steal my lucky charms!"

my_box['funny_line']
'They tried to steal my luck charms!'

my_box.credits = {'Austin Powers': "Mike Myers", "Vanessa Kensington": "Elizabeth Hurley"}
# <Box: {'Austin Powers': 'Mike Myers', 'Vanessa Kensington': 'Elizabeth Hurley'}>

my_box.to_yaml()  # .to_json() also available
# owner: Mr. Powers
# affiliates:
#   Dr Evil: Not groovy
#   Scott Evil: Doesn't want to take over family business
#   Vanessa: Sexy
# contents:
# - item: blue crushed-velvet suit
#   qty: 1
# - item: frilly lace crava
#   qty: 1
# - item: gold medallion with peace symbol
#   qty: 1
# ...

Install

BuildStatus CoverageStatus

pip install python-box

Box is tested on python 2.6+, 3.3+ and PyPy2, and should work on other interpreters as well. If it does not install with this command, please open a ticket with the error you are experiencing!

If you want to be able to use the to_yaml functionality make sure to install PyYAML as well.

Overview

Box is designed to be easy drop in replacements for dictionaries, with the latter having tools for dealing with config files.

Box is designed to transparently act as a dictionary, thanks to Python’s duck typing capabilities, but add dot notation access like classes do. 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.

del my_box.contents # Lets keep this short

my_box.to_dict()
{'affiliates':
        {'Dr Evil': 'Not groovy',
         'Scott Evil': "Doesn't want to take over family business",
         'Vanessa': 'Sexy'},
 'owner': 'Mr. Powers'}

# Will only convert outermost object
dict(my_box)
# {'owner': 'Mr. Powers',
#  'affiliates': <Box: {'Vanessa': 'Sexy',
#                      'Dr Evil': 'Not groovy',
#                      'Scott Evil': "Doesn't want to take over family business"}>}}

Box was originally named Namespaces in the reusables project, created over three years ago. LightBox is the direct dependant of Namespace, and should operate as a near drop in replacement if you are switching over.

Box

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')

Any time a list or dict is added to a Box, it is converted into a BoxList or Box respectively.

Box includes helper functions to transform it back into dict, and into JSON or YAML strings.

to_dict

Return the Box object and all sub Box and BoxList objects into regular dicts and list.

my_box.to_dict()
{'owner': 'Mr. Powers',
 'affiliates': {'Vanessa': 'Sexy',
                'Dr Evil': 'Not groovy',
                'Scott Evil': "Doesn't want to take over family business"}}

to_json

Available on all systems that support the default json library.:

to_json(filename=None, indent=4, **json_kwargs)
    Transform the Box object into a JSON string.

    :param filename: If provided will save to file
    :param indent: Automatic formatting by indent size in spaces
    :param json_kwargs: additional arguments to pass to json.dump(s)
    :return: string of JSON or return of `json.dump`
my_box.to_json()
{
    "owner": "Mr. Powers",
    "affiliates": {
        "Vanessa": "Sexy",
        "Dr Evil": "Not groovy",
        "Scott Evil": "Doesn't want to take over family business"
    }
}

to_yaml

Only available if PyYAML is installed (not automatically installed via pip or setup.py):

to_yaml(filename=None, default_flow_style=False, **yaml_kwargs)
    Transform the Box object into a YAML string.

    :param filename:  If provided will save to file
    :param default_flow_style: False will recursively dump dicts
    :param yaml_kwargs: additional arguments to pass to yaml.dump
    :return: string of YAML or return of `yaml.dump`
my_box.to_yaml()
affiliates:
  Dr Evil: Not groovy
  Scott Evil: Doesn't want to take over family business
  Vanessa: Sexy
owner: Mr. Powers

BoxList

To make sure all items added to lists in the box are also converted, all lists are covered into BoxList. It’s possible to initiate these directly and use them just like a Box.

from box import BoxList

my_boxlist = BoxList({'item': x} for x in range(10))
#  <BoxList: [<Box: {'item': 0}>, <Box: {'item': 1}>, ...

my_boxlist[5].item
5

to_list

Transform a BoxList and all components back into regular list and dict items.

my_boxlist.to_list()
# [{'item': 0},
#  {'item': 1},
#  ...

ConfigBox

This module has support for a ConfigBox. It is based on top of LightBox as there are no lists of dicts to dive into in a configuration file.

test_config.ini

[General]
example=A regular string

[Examples]
my_bool=yes
anint=234
exampleList=234,123,234,543
floatly=4.4

With the combination of reusables and ConfigBox you can easily read python config values into python types. It supports list, bool, int and float.

import reusables
from box import ConfigBox

config = ConfigBox(reusables.config_dict("test_config.ini"))
# <ConfigBox: {'General': {'example': 'A regular string'},
# 'Examples': {'my_bool': 'yes', 'anint': '234', 'examplelist': '234,123,234,543', 'floatly': '4.4'}}>

config.Examples.list('examplelist')
# ['234', '123', '234', '543']

config.Examples.float('floatly')
# 4.4

Similar Libraries

EasyDict

  • EasyDict not have a way to make sub items recursively back into a regular dictionary.

  • Adding new dicts to lists in the dictionary does not make them into EasyDicts.

  • Both EasyDicts str and repr print a dictionary look alike, Box makes it clear in repr that it is a Box object.

addict

  • Adding new dicts or lists does not make them into addict.Dict objects.

  • Is a default dictionary, as in it will never fail on lookup.

  • Both addict.Dict’s str and repr print a dictionary look alike, Box makes it clear in repr that it is a Box object.

License

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python-box-2.1.0.tar.gz (10.8 kB view details)

Uploaded Source

Built Distributions

python_box-2.1.0-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

python_box-2.1.0-py2-none-any.whl (15.9 kB view details)

Uploaded Python 2

File details

Details for the file python-box-2.1.0.tar.gz.

File metadata

  • Download URL: python-box-2.1.0.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for python-box-2.1.0.tar.gz
Algorithm Hash digest
SHA256 d107b78a499723e9200768ea84a71caf9d097039f0c6161c14a726844d365a37
MD5 1b64c6afda692f5934a8ef1006d04405
BLAKE2b-256 666aa2e58c1c5481c003efbef031bec04d5f8aafbcae3103e91a2dabfb3e8ed7

See more details on using hashes here.

File details

Details for the file python_box-2.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for python_box-2.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3bca12ea20764365d57a136bf8def9bdc539084ea8979257cfefcf14e0dcc076
MD5 460d14650bc707c267a94edaaddcad42
BLAKE2b-256 5df60ad084308765be21ad88239828ce063bcd39537636d8ed536cd5475e4ec9

See more details on using hashes here.

File details

Details for the file python_box-2.1.0-py2-none-any.whl.

File metadata

File hashes

Hashes for python_box-2.1.0-py2-none-any.whl
Algorithm Hash digest
SHA256 6c4a310402e80291bc913019f54e674843f5bc264454b8a2923dff219f4b2aa2
MD5 8e644f68bfcd5c3c6f45f6648a5068b7
BLAKE2b-256 6070b68fe934630c5fa8fa08bdce061ef5eab38d65dffcf02555fe8c4410c8ab

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page