Skip to content

Commit

Permalink
basic attrs wrapper for nested parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
danh91 committed Apr 6, 2019
1 parent 17a3378 commit 9ee687a
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,4 @@ venv.bak/

# mypy
.mypy_cache/
.vscode/
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
# jstruct

JSON to struct to JSON

## Installation

```bash
pip install -f https://git.io/purplship jstruct
```
6 changes: 6 additions & 0 deletions jstruct/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from jstruct.types import (
JStruct,
JList,
JDict,
REQUIRED
)
62 changes: 62 additions & 0 deletions jstruct/types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import attr
from functools import reduce
from typing import List, Dict


REQUIRED = True


@attr.s(auto_attribs=True)
class _JStruct:
def __getitem__(self, arguments):
class_, required_, *kwargs = arguments if isinstance(arguments, tuple) else (arguments, False)

def build(args) -> class_:
return class_(**args) if isinstance(args, dict) else args
default_ = dict(default=attr.NOTHING if required_ else None)
return attr.ib(
**default_,
converter=build,
**dict(reduce(lambda r, d: r + list(d.items()), kwargs, []))
)


@attr.s(auto_attribs=True)
class _JList:
def __getitem__(self, arguments):
class_, required_, *kwargs = arguments if isinstance(arguments, tuple) else (arguments, False)

def build(args) -> List[class_]:
if isinstance(args, list):
items = args
else:
items = [args]
return [
(class_(**item) if isinstance(item, dict) else item)
for item in items
]
default_ = dict(default=attr.NOTHING if required_ else [])
return attr.ib(
**default_,
converter=build,
**dict(reduce(lambda r, d: r + list(d.items()), kwargs, []))
)


@attr.s(auto_attribs=True)
class _JDict:
def __getitem__(self, arguments):
key_type, value_type, required_, *kwargs = arguments if isinstance(arguments, tuple) else (arguments, False)

def build(args) -> Dict[key_type, value_type]:
return {
key_type(key): (value_type(**value) if isinstance(value, dict) else value)
for (key, value) in args.items()
}
default_ = dict(default=attr.NOTHING if required_ else {})
return attr.ib(**default_, converter=build, **kwargs)


JStruct = _JStruct()
JList = _JList()
JDict = _JDict()
14 changes: 14 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from setuptools import setup

setup(name='jstruct',
version='1.0.0',
description='Elegant JSON to python Data class',
url='https://github.com/DanH91/jstruct',
author='DanH91',
author_email='danielk.developer@gmail.com',
license='MIT',
packages=['jstruct'],
install_requires=[
'attrs==18.2.0'
],
zip_safe=False)

0 comments on commit 9ee687a

Please sign in to comment.