Skip to main content

Safitty. Wrapper on JSON/YAML configs for Python.

Project description

Safitty

Safitty is a wrapper on JSON/YAML configs for Python. Designed with a focus on the security of get/set operations for deep-nested dictionaries and lists.

Installation

Currently only submodule installation is available

git submodule add https://github.com/TezRomacH/safitty.git safitty

Features

  • Safe get for dictionaries and lists
  • Nested keys at one time
  • Several strategies

Usage

Suppose you have a configuration file looks like:

verbose: false

status: 1

paths:
  jsons:
    - first
    - second
    - third
  images: important/path/to/images/

transforms:
  - name: Normalize
    function: ToTensor
    params: null
  -
    name: Padding
    function: Pad
    params:
      fill: 3
      padding_mode: reflect

Maybe it's located at your project folder or you receive it from a server. For now we want to load the config and get some of the nested keys

import safitty as sf
import yaml


with open("path/to/config.yml") as stream:
    config = yaml.load(stream)

param = sf.safe_get(config, 'paths', 'images')
# param == 'important/path/to/images/'

Python's dict will throw an error if we try to get a non-existing path. Or it will turn into a disgusting construction.

# usual way to work with dict

>>> config['transforms'][1]['param']['fill'] # oops, we wrote `param` insted of `params
KeyError: 'param'

>>> config.get('transforms')[1].get('param').get('fill') # What if we go deeeeeeper
AttributeError: 'NoneType' object has no attribute 'get'

>>> config.get('transforms')[1].get('params').get('fill') # it works, but looks awful
3

Anyway this last way doesn't help us with lists. Standard Python library doesn't provide safe get method for type list

>>> config.get('transforms')[2].get('params').get('fill') # wrong index
IndexError: list index out of range

Solution here is to use Saffity:

>>> sf.safe_get(config, 'transforms', 2, 'params', 'fill')
# None

>>> sf.safe_get(config, 'transforms', 1, 'params', 'fill')
3

>>> sf.safe_get(config, 'transforms', 2, 'values', 'fill', default=42)
42

With Safitty you'll not be scared about nested depth

>>> sf.safe_get(config, 'transforms', 1, 'params', 'fill', 'what', 'if', 'we', 'go', 'deeper')
# None

>>> sf.safe_get(config, 'transforms', 3, "wrong_key", 55, 'params', 'go', 'deeper', default="This is default value")
This is default value

Safitty provides several strategies for using the default param.

>>> sf.safe_get(config, 'transforms', 0, 'values', strategy='missing_key', default=42)
42

>>> sf.safe_get(config 'transforms', 0, 'values', strategy='last_value', default=42)
{"name": "Normalize", "function": "ToTensor", "params": None}
  1. For strategy final, it returns default if the final result on applying keys is None. Safitty uses it by default
  2. For strategy missing_key, it returns default only if some key in keys doesn't exist in config.
  3. Strategy last_value returns last non null value if exists
  4. Strategy last_container returns last non null container if exists

Note the difference for final and missing_key strategies.

>>> sf.safe_get(config, 'transforms', 0, 'params', default='No value')
No value

>>> sf.safe_get(config, 'transforms', 0, 'params', strategy='missing_key', default='No value')
# return None, because there were not not-existing keys

# But if we make a mistake in keys 
>>> sf.safe_get(config, 'transforms', 23, 'params', strategy='missing_key', default='No value')
No value

# or
>>> sf.safe_get(config, 'transforms', 0, 'values', strategy='missing_key', default='No value')
No value

Saffity provides transform params. If it's not None, the result will be applied to this type or function.

>>> from pathlib import Path
>>> sf.safe_get(config, 'paths', 'images', transform=Path)
PosixPath('important/path/to/images/')
>>> sf.safe_get(config, 'status', transform=bool)
True

Lambdas are also supported

NOT_FOUND = 404
>>> sf.safe_get(config, 'status', transform=lambda x: x != NOT_FOUND)

True

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

safitty-0.3.1.tar.gz (5.8 kB view hashes)

Uploaded Source

Built Distribution

safitty-0.3.1-py3-none-any.whl (6.7 kB view hashes)

Uploaded Python 3

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