Skip to content

Commit

Permalink
Add support for JSON string configuration casting (#43)
Browse files Browse the repository at this point in the history
* Add new JSON config casting
* Preparing a minor release with JSON cast support
* Remove pypy3 support because it is breaking at Travis
  • Loading branch information
osantana authored Jan 7, 2021
1 parent 2d92ef7 commit 5fa7b48
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 2 deletions.
5 changes: 5 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2.2.0
=====

- Add new cast `config.json` for JSON configurations

2.1.0
=====

Expand Down
1 change: 1 addition & 0 deletions docs/source/casts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Buitin Casts
objects (alias to Python's ``ast.literal_eval``).
#. ``config.list`` - converts comma separated strings into lists.
#. ``config.tuple`` - converts comma separated strings into tuples.
#. ``config.json`` - unserialize a string with JSON object into Python.
#. ``config.option`` - get a return value based on specific options:

.. code-block:: python
Expand Down
10 changes: 10 additions & 0 deletions prettyconf/casts.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import json

from .exceptions import InvalidConfiguration


Expand Down Expand Up @@ -93,3 +95,11 @@ def __call__(self, value):
return self.options[value]
except KeyError:
raise InvalidConfiguration("Invalid option {!r}".format(value))


class JSON(AbstractCast):
def __call__(self, value):
try:
return json.loads(value)
except json.JSONDecodeError as ex:
raise InvalidConfiguration('Invalid option {!r}'.format(value)) from ex
3 changes: 2 additions & 1 deletion prettyconf/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import sys

from .casts import Boolean, List, Option, Tuple
from .casts import Boolean, JSON, List, Option, Tuple
from .exceptions import UnknownConfiguration
from .loaders import Environment, RecursiveSearch

Expand All @@ -24,6 +24,7 @@ class Configuration(object):
tuple = Tuple()
option = Option
eval = staticmethod(ast.literal_eval)
json = JSON()

def __init__(self, loaders=None):
self._recursive_search = None
Expand Down
19 changes: 18 additions & 1 deletion tests/test_casts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

from prettyconf import config
from prettyconf.casts import Boolean, List, Option, Tuple
from prettyconf.casts import Boolean, JSON, List, Option, Tuple
from prettyconf.exceptions import InvalidConfiguration


Expand Down Expand Up @@ -104,3 +104,20 @@ def test_fail_invalid_option_config():

def test_if_cast_is_unbounded():
assert config.eval("None") is None


@pytest.mark.parametrize('value,result', [
('"string"', 'string'),
('["obj1", "obj2"]', ['obj1', 'obj2']),
('{"key": "value"}', {'key': 'value'}),
('null', None),
])
def test_basic_json_cast_values(value, result):
json = JSON()
assert json(value) == result


def test_fail_invalid_json_config():
json = JSON()
with pytest.raises(InvalidConfiguration):
json('invalid')

0 comments on commit 5fa7b48

Please sign in to comment.