<a href="https://github.com/dynamic-graphics-inc/dgpy-libs">
<img align="right" src="https://github.com/dynamic-graphics-inc/dgpy-libs/blob/main/docs/images/dgpy_banner.svg?raw=true" alt="drawing" height="120" width="300"/>
</a>
# jsonbourne
[![Wheel](https://img.shields.io/pypi/wheel/jsonbourne.svg)](https://img.shields.io/pypi/wheel/jsonbourne.svg)
[![Version](https://img.shields.io/pypi/v/jsonbourne.svg)](https://img.shields.io/pypi/v/jsonbourne.svg)
[![py_versions](https://img.shields.io/pypi/pyversions/jsonbourne.svg)](https://img.shields.io/pypi/pyversions/jsonbourne.svg)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
**Install:** `pip install jsonbourne`
- Python json lib/pkg that makes json feel like the JSON module in javascript/typescript:
- `from jsonbourne import JSON; JSON.parse(JSON.stringify({"key": "value"}))`
- Automatically uses best json-lib-backend available (`orjson`/`python-rapidjson`) ~ can be configured
- Hybrid dict/class object (`jsonbourne.JsonObj`):
- Dot-notation getting/setting (featuring protected attributes!)
- All your favorite python dictionary methods (`items`, `keys`, `update`, `values`) and more!
- Works with `pydantic` and `attrs`
- FastAPI:
- JSONBOURNEResponse ~ auto use the best
- No hard dependencies ~ works with python-stdlib-json as well as `orjson` and `python-rapidjson`
- `jsonbourne.JsonObj` uses list/dict comprehensions (some are recursive) everywhere because 'why not?' and it is a bit faster
## Usage:
### JSON ~ `from jsonbourne import JSON`
**Importing:**
```python
# Importing JSON:
from jsonbourne import JSON
# or
import JSON
# Importing jsonbourne:
import jsonbourne
import david_webb # jsonbourne's `True` identity
```
**JSON basics:**
```python
import JSON # Module included with jsonbourne
string_stringify = JSON.stringify(
{"a": 1, "b": 2, "c": 3}
) # '{"a": 1, "b": 2, "c": 3}'
string_dumps = JSON.dumps({"a": 1, "b": 2, "c": 3}) # '{"a": 1, "b": 2, "c": 3}'
string_dumps
```
'{"a":1,"b":2,"c":3}'
#### JSON option kwargs ~ `pretty` & `sort_keys`
**pretty:**
```python
string_dumps = JSON.stringify(
{"b": 2, "a": 1, "c": 3}, pretty=True
) # '{"a": 1, "b": 2, "c": 3}'
print(string_dumps)
```
{
"b": 2,
"a": 1,
"c": 3
}
**sort_keys:**
```python
string_dumps = JSON.stringify(
{"b": 2, "a": 1, "c": 3}, pretty=True, sort_keys=True
) # '{"a": 1, "b": 2, "c": 3}'
print(string_dumps)
```
{
"a": 1,
"b": 2,
"c": 3
}
### JsonObj & JSON
- Python dictionary/object with dot access
- Protections against setting class/obj attributes
- Is as javascript-y as possible (keys have to be strings -- ints/floats will be converted to strings)
- Create a `jsonbourne.JsonObj` with `jsonbourne.JSON`
- Recursive jsonification
- Allows for kwarging (`**json_obj`)
- Works with `pydantic` and `attrs`
#### Make an empty JsonObj
The following 3 examples all produce the same thing
```python
from jsonbourne import JSON
j = JSON() # j => JsonObj(**{})
# OR
import JSON
j = JSON() # j => JsonObj(**{})
# OR
from jsonbourne import JsonObj
j = JsonObj() # j => JsonObj(**{})
```
#### From a dictionary o data
```python
import datetime
data = {
"key": "value",
"list": [1, 2, 3, 4, 5],
"dt": datetime.datetime(1970, 1, 1, 0, 0, 0, 1),
"sub": {
"b": 3,
"key": "val",
"a": 1,
},
"timedelta": datetime.timedelta(days=2),
}
JSON(data)
```
<pre>JsonObj(**{
'dt': datetime.datetime(1970, 1, 1, 0, 0, 0, 1),
'key': 'value',
'list': [1, 2, 3, 4, 5],
'sub': {'a': 1, 'b': 3, 'key': 'val'},
'timedelta': datetime.timedelta(days=2)
})</pre>
### Dot access
```python
JSON(data).sub.b
```
3
```python
stringified_data = JSON(data).stringify(pretty=True)
print(stringified_data)
```
{
"key": "value",
"list": [
1,
2,
3,
4,
5
],
"dt": "1970-01-01T00:00:00.000001",
"sub": {
"b": 3,
"key": "val",
"a": 1
},
"timedelta": 172800.0
}
```python
parsed_data = JSON(stringified_data)
parsed_data
```
<pre>JsonObj(**{
'dt': '1970-01-01T00:00:00.000001',
'key': 'value',
'list': [1, 2, 3, 4, 5],
'sub': {'a': 1, 'b': 3, 'key': 'val'},
'timedelta': 172800.0
})</pre>
```python
list(parsed_data.keys())
```
['key', 'list', 'dt', 'sub', 'timedelta']
```python
list(parsed_data.items())
```
[('key', 'value'),
('list', [1, 2, 3, 4, 5]),
('dt', '1970-01-01T00:00:00.000001'),
('sub', JsonObj(**{'b': 3, 'key': 'val', 'a': 1})),
('timedelta', 172800.0)]
```python
list(parsed_data.dot_keys())
```
[('key',),
('list',),
('dt',),
('sub', 'b'),
('sub', 'key'),
('sub', 'a'),
('timedelta',)]
```python
list(parsed_data.dot_items())
```
[(('key',), 'value'),
(('list',), [1, 2, 3, 4, 5]),
(('dt',), '1970-01-01T00:00:00.000001'),
(('sub', 'b'), 3),
(('sub', 'key'), 'val'),
(('sub', 'a'), 1),
(('timedelta',), 172800.0)]
```python
parsed_data[("sub", "key")]
```
'val'
```python
parsed_data.dot_lookup("sub.key")
```
'val'
```python
{**parsed_data}
```
{'key': 'value',
'list': [1, 2, 3, 4, 5],
'dt': '1970-01-01T00:00:00.000001',
'sub': JsonObj(**{'b': 3, 'key': 'val', 'a': 1}),
'timedelta': 172800.0}
```python
# fully eject
parsed_data.eject()
```
{'key': 'value',
'list': [1, 2, 3, 4, 5],
'dt': '1970-01-01T00:00:00.000001',
'sub': {'b': 3, 'key': 'val', 'a': 1},
'timedelta': 172800.0}
#### Protected keys
`jsonbourne.JsonObj` protects against setting attributes like `'items'` through dot-notation.
```python
from jsonbourne import JSON
j = JSON()
j.key = "value"
try: # CANNOT set 'items' using dot-access
j.items = [1, 2, 3, 4]
except ValueError:
pass
# CAN set 'items' through key/item access
j["items"] = [1, 2, 3, 4]
print(j.__dict__)
print(j)
j_items = j.items
print("items", j_items)
# Getting 'items' through dot-access returns the `items()` method
assert j.items != [1, 2, 3, 4]
# Getting 'items' with key-access returns the stored value
assert j["items"] == [1, 2, 3, 4]
```
{'_data': {'key': 'value', 'items': [1, 2, 3, 4]}}
JsonObj(**{
'items': [1, 2, 3, 4], 'key': 'value'
})
items <bound method JsonObj.items of JsonObj(**{'key': 'value', 'items': [1, 2, 3, 4]})>
### pydantic & jsonbourne
- `from jsonbourne.pydantic import JsonBaseModel`
- Allows for aliases when getting/setting attribute(s)
- Supports `__post_init__` (like dataclasses)
#### Basic usage:
```python
from jsonbourne import JsonObj
from jsonbourne.pydantic import JsonBaseModel
class JsonSubObj(JsonBaseModel):
herm: int
def to_dict(self):
return self.dict()
def to_json(self, *args, **kwargs):
return self.json()
@classmethod
def from_json(cls, json_string: str):
return JsonSubObj(json.loads(json_string))
class JsonObjModel(JsonBaseModel):
a: int
b: int
c: str
d: JsonObj
e: JsonSubObj
#
@property
def a_property(self) -> str:
return "prop_value"
def to_json(self, *args, **kwargs):
return self.json()
@classmethod
def from_json(cls, json_string: str):
return cls(**json.loads(json_string))
obj = JsonObjModel(
**{"a": 1, "b": 2, "c": "herm", "d": {"nested": "nestedval"}, "e": {"herm": 2}}
)
obj
```
<pre>JsonObjModel(**{
'a': 1,
'b': 2,
'c': 'herm',
'd': JsonObj(**{'nested': 'nestedval'}),
'e': {'herm': 2}
})</pre>
```python
# respects properties (which I don't think pydantic does(currently))
obj.a_property
```
'prop_value'
---
## JSON backend/lib
**`jsonbourne` finds the best json-lib (python-rapidjson/orjson) it can!** On import `jsonbourne` gets to
work spying on your python env. `jsonbourne`, the most highly qualified json-CIA-agent, will import the best
python-json library it can find; if `jsonbourne`'s cover is blown (meaning: the
only json library found is the python stdlib json), `jsonbourne` will fallback
to
the python stdlib json.
`jsonbourne` will look for the following json-packages in the following order:
1. `rapidjson`
2. `orjson`
### Custom lib preferences
```python
from jsonbourne import import_json
json = import_json(("rapidjson", "orjson")) # prefer rapidjson over orjson
string = json.dumps({"a": 1, "b": 2, "c": 3})
print(json)
print(string)
```
<class 'jsonbourne.jsonlib.RAPIDJSON'>
{"a":1,"b":2,"c":3}
### Installing better JSON lib:
#### `orjson`
- `pip install orjson` [pip]
#### `rapidjson`/`python-rapidjson`
- `pip install python-rapidjson` [pip]
- `conda install -c anaconda python-rapidjson` [conda anaconda/defaults]
- `conda install -c conda-forge python-rapidjson` [conda-forge]
Raw data
{
"_id": null,
"home_page": "https://github.com/dynamic-graphics-inc/dgpy-libs/tree/main/libs/jsonbourne",
"name": "jsonbourne",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "dgpy, pydantic, json, orjson, rapidjson",
"author": "jesse",
"author_email": "jesse@dgi.com",
"download_url": "https://files.pythonhosted.org/packages/8e/d3/8c9b831e49658afc055a89283a1ea714b7a55d416426c4133655a1c05ab5/jsonbourne-0.29.0.tar.gz",
"platform": null,
"description": "<a href=\"https://github.com/dynamic-graphics-inc/dgpy-libs\">\n<img align=\"right\" src=\"https://github.com/dynamic-graphics-inc/dgpy-libs/blob/main/docs/images/dgpy_banner.svg?raw=true\" alt=\"drawing\" height=\"120\" width=\"300\"/>\n</a>\n\n# jsonbourne\n\n[![Wheel](https://img.shields.io/pypi/wheel/jsonbourne.svg)](https://img.shields.io/pypi/wheel/jsonbourne.svg)\n[![Version](https://img.shields.io/pypi/v/jsonbourne.svg)](https://img.shields.io/pypi/v/jsonbourne.svg)\n[![py_versions](https://img.shields.io/pypi/pyversions/jsonbourne.svg)](https://img.shields.io/pypi/pyversions/jsonbourne.svg)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n\n**Install:** `pip install jsonbourne`\n\n- Python json lib/pkg that makes json feel like the JSON module in javascript/typescript:\n - `from jsonbourne import JSON; JSON.parse(JSON.stringify({\"key\": \"value\"}))`\n - Automatically uses best json-lib-backend available (`orjson`/`python-rapidjson`) ~ can be configured\n- Hybrid dict/class object (`jsonbourne.JsonObj`):\n - Dot-notation getting/setting (featuring protected attributes!)\n - All your favorite python dictionary methods (`items`, `keys`, `update`, `values`) and more!\n - Works with `pydantic` and `attrs`\n- FastAPI:\n - JSONBOURNEResponse ~ auto use the best\n- No hard dependencies ~ works with python-stdlib-json as well as `orjson` and `python-rapidjson`\n- `jsonbourne.JsonObj` uses list/dict comprehensions (some are recursive) everywhere because 'why not?' and it is a bit faster\n\n## Usage:\n\n### JSON ~ `from jsonbourne import JSON`\n\n**Importing:**\n\n```python\n# Importing JSON:\nfrom jsonbourne import JSON\n\n# or\nimport JSON\n\n# Importing jsonbourne:\nimport jsonbourne\nimport david_webb # jsonbourne's `True` identity\n```\n\n**JSON basics:**\n\n```python\nimport JSON # Module included with jsonbourne\n\nstring_stringify = JSON.stringify(\n {\"a\": 1, \"b\": 2, \"c\": 3}\n) # '{\"a\": 1, \"b\": 2, \"c\": 3}'\nstring_dumps = JSON.dumps({\"a\": 1, \"b\": 2, \"c\": 3}) # '{\"a\": 1, \"b\": 2, \"c\": 3}'\nstring_dumps\n```\n\n '{\"a\":1,\"b\":2,\"c\":3}'\n\n#### JSON option kwargs ~ `pretty` & `sort_keys`\n\n**pretty:**\n\n```python\nstring_dumps = JSON.stringify(\n {\"b\": 2, \"a\": 1, \"c\": 3}, pretty=True\n) # '{\"a\": 1, \"b\": 2, \"c\": 3}'\nprint(string_dumps)\n```\n\n {\n \"b\": 2,\n \"a\": 1,\n \"c\": 3\n }\n\n**sort_keys:**\n\n```python\nstring_dumps = JSON.stringify(\n {\"b\": 2, \"a\": 1, \"c\": 3}, pretty=True, sort_keys=True\n) # '{\"a\": 1, \"b\": 2, \"c\": 3}'\nprint(string_dumps)\n```\n\n {\n \"a\": 1,\n \"b\": 2,\n \"c\": 3\n }\n\n### JsonObj & JSON\n\n- Python dictionary/object with dot access\n- Protections against setting class/obj attributes\n- Is as javascript-y as possible (keys have to be strings -- ints/floats will be converted to strings)\n- Create a `jsonbourne.JsonObj` with `jsonbourne.JSON`\n- Recursive jsonification\n- Allows for kwarging (`**json_obj`)\n- Works with `pydantic` and `attrs`\n\n#### Make an empty JsonObj\n\nThe following 3 examples all produce the same thing\n\n```python\nfrom jsonbourne import JSON\nj = JSON() # j => JsonObj(**{})\n# OR\nimport JSON\nj = JSON() # j => JsonObj(**{})\n# OR\nfrom jsonbourne import JsonObj\nj = JsonObj() # j => JsonObj(**{})\n```\n\n#### From a dictionary o data\n\n```python\nimport datetime\n\ndata = {\n \"key\": \"value\",\n \"list\": [1, 2, 3, 4, 5],\n \"dt\": datetime.datetime(1970, 1, 1, 0, 0, 0, 1),\n \"sub\": {\n \"b\": 3,\n \"key\": \"val\",\n \"a\": 1,\n },\n \"timedelta\": datetime.timedelta(days=2),\n}\n\nJSON(data)\n```\n\n<pre>JsonObj(**{\n 'dt': datetime.datetime(1970, 1, 1, 0, 0, 0, 1),\n 'key': 'value',\n 'list': [1, 2, 3, 4, 5],\n 'sub': {'a': 1, 'b': 3, 'key': 'val'},\n 'timedelta': datetime.timedelta(days=2)\n})</pre>\n\n### Dot access\n\n```python\nJSON(data).sub.b\n```\n\n 3\n\n```python\nstringified_data = JSON(data).stringify(pretty=True)\nprint(stringified_data)\n```\n\n {\n \"key\": \"value\",\n \"list\": [\n 1,\n 2,\n 3,\n 4,\n 5\n ],\n \"dt\": \"1970-01-01T00:00:00.000001\",\n \"sub\": {\n \"b\": 3,\n \"key\": \"val\",\n \"a\": 1\n },\n \"timedelta\": 172800.0\n }\n\n```python\nparsed_data = JSON(stringified_data)\nparsed_data\n```\n\n<pre>JsonObj(**{\n 'dt': '1970-01-01T00:00:00.000001',\n 'key': 'value',\n 'list': [1, 2, 3, 4, 5],\n 'sub': {'a': 1, 'b': 3, 'key': 'val'},\n 'timedelta': 172800.0\n})</pre>\n\n```python\nlist(parsed_data.keys())\n```\n\n ['key', 'list', 'dt', 'sub', 'timedelta']\n\n```python\nlist(parsed_data.items())\n```\n\n [('key', 'value'),\n ('list', [1, 2, 3, 4, 5]),\n ('dt', '1970-01-01T00:00:00.000001'),\n ('sub', JsonObj(**{'b': 3, 'key': 'val', 'a': 1})),\n ('timedelta', 172800.0)]\n\n```python\nlist(parsed_data.dot_keys())\n```\n\n [('key',),\n ('list',),\n ('dt',),\n ('sub', 'b'),\n ('sub', 'key'),\n ('sub', 'a'),\n ('timedelta',)]\n\n```python\nlist(parsed_data.dot_items())\n```\n\n [(('key',), 'value'),\n (('list',), [1, 2, 3, 4, 5]),\n (('dt',), '1970-01-01T00:00:00.000001'),\n (('sub', 'b'), 3),\n (('sub', 'key'), 'val'),\n (('sub', 'a'), 1),\n (('timedelta',), 172800.0)]\n\n```python\nparsed_data[(\"sub\", \"key\")]\n```\n\n 'val'\n\n```python\nparsed_data.dot_lookup(\"sub.key\")\n```\n\n 'val'\n\n```python\n{**parsed_data}\n```\n\n {'key': 'value',\n 'list': [1, 2, 3, 4, 5],\n 'dt': '1970-01-01T00:00:00.000001',\n 'sub': JsonObj(**{'b': 3, 'key': 'val', 'a': 1}),\n 'timedelta': 172800.0}\n\n```python\n# fully eject\nparsed_data.eject()\n```\n\n {'key': 'value',\n 'list': [1, 2, 3, 4, 5],\n 'dt': '1970-01-01T00:00:00.000001',\n 'sub': {'b': 3, 'key': 'val', 'a': 1},\n 'timedelta': 172800.0}\n\n#### Protected keys\n\n`jsonbourne.JsonObj` protects against setting attributes like `'items'` through dot-notation.\n\n```python\nfrom jsonbourne import JSON\n\nj = JSON()\nj.key = \"value\"\ntry: # CANNOT set 'items' using dot-access\n j.items = [1, 2, 3, 4]\nexcept ValueError:\n pass\n# CAN set 'items' through key/item access\nj[\"items\"] = [1, 2, 3, 4]\nprint(j.__dict__)\nprint(j)\nj_items = j.items\nprint(\"items\", j_items)\n# Getting 'items' through dot-access returns the `items()` method\nassert j.items != [1, 2, 3, 4]\n# Getting 'items' with key-access returns the stored value\nassert j[\"items\"] == [1, 2, 3, 4]\n```\n\n {'_data': {'key': 'value', 'items': [1, 2, 3, 4]}}\n JsonObj(**{\n 'items': [1, 2, 3, 4], 'key': 'value'\n })\n items <bound method JsonObj.items of JsonObj(**{'key': 'value', 'items': [1, 2, 3, 4]})>\n\n### pydantic & jsonbourne\n\n- `from jsonbourne.pydantic import JsonBaseModel`\n- Allows for aliases when getting/setting attribute(s)\n- Supports `__post_init__` (like dataclasses)\n\n#### Basic usage:\n\n```python\nfrom jsonbourne import JsonObj\nfrom jsonbourne.pydantic import JsonBaseModel\n\n\nclass JsonSubObj(JsonBaseModel):\n herm: int\n\n def to_dict(self):\n return self.dict()\n\n def to_json(self, *args, **kwargs):\n return self.json()\n\n @classmethod\n def from_json(cls, json_string: str):\n return JsonSubObj(json.loads(json_string))\n\n\nclass JsonObjModel(JsonBaseModel):\n a: int\n b: int\n c: str\n d: JsonObj\n e: JsonSubObj\n\n #\n @property\n def a_property(self) -> str:\n return \"prop_value\"\n\n def to_json(self, *args, **kwargs):\n return self.json()\n\n @classmethod\n def from_json(cls, json_string: str):\n return cls(**json.loads(json_string))\n\n\nobj = JsonObjModel(\n **{\"a\": 1, \"b\": 2, \"c\": \"herm\", \"d\": {\"nested\": \"nestedval\"}, \"e\": {\"herm\": 2}}\n)\nobj\n```\n\n<pre>JsonObjModel(**{\n 'a': 1,\n 'b': 2,\n 'c': 'herm',\n 'd': JsonObj(**{'nested': 'nestedval'}),\n 'e': {'herm': 2}\n})</pre>\n\n```python\n# respects properties (which I don't think pydantic does(currently))\nobj.a_property\n```\n\n 'prop_value'\n\n---\n\n## JSON backend/lib\n\n**`jsonbourne` finds the best json-lib (python-rapidjson/orjson) it can!** On import `jsonbourne` gets to\nwork spying on your python env. `jsonbourne`, the most highly qualified json-CIA-agent, will import the best\npython-json library it can find; if `jsonbourne`'s cover is blown (meaning: the\nonly json library found is the python stdlib json), `jsonbourne` will fallback\nto\nthe python stdlib json.\n\n`jsonbourne` will look for the following json-packages in the following order:\n\n1. `rapidjson`\n2. `orjson`\n\n### Custom lib preferences\n\n```python\nfrom jsonbourne import import_json\n\njson = import_json((\"rapidjson\", \"orjson\")) # prefer rapidjson over orjson\nstring = json.dumps({\"a\": 1, \"b\": 2, \"c\": 3})\nprint(json)\nprint(string)\n```\n\n <class 'jsonbourne.jsonlib.RAPIDJSON'>\n {\"a\":1,\"b\":2,\"c\":3}\n\n### Installing better JSON lib:\n\n#### `orjson`\n\n- `pip install orjson` [pip]\n\n#### `rapidjson`/`python-rapidjson`\n\n- `pip install python-rapidjson` [pip]\n- `conda install -c anaconda python-rapidjson` [conda anaconda/defaults]\n- `conda install -c conda-forge python-rapidjson` [conda-forge]\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "EZPZ JSON",
"version": "0.29.0",
"project_urls": {
"Homepage": "https://github.com/dynamic-graphics-inc/dgpy-libs/tree/main/libs/jsonbourne",
"Repository": "https://github.com/dynamic-graphics-inc/dgpy-libs"
},
"split_keywords": [
"dgpy",
" pydantic",
" json",
" orjson",
" rapidjson"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "851f5f7b865b84e902c7cd081e6a8d68723d7108df019c57af84fe4c02f73790",
"md5": "8a6094fa861ab7f34cee89e915d436e7",
"sha256": "3571563f838a214dcbe680d54fc06c9fb841f82a648b615576e13d8855ae2dd0"
},
"downloads": -1,
"filename": "jsonbourne-0.29.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8a6094fa861ab7f34cee89e915d436e7",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 27472,
"upload_time": "2024-05-01T17:30:30",
"upload_time_iso_8601": "2024-05-01T17:30:30.335398Z",
"url": "https://files.pythonhosted.org/packages/85/1f/5f7b865b84e902c7cd081e6a8d68723d7108df019c57af84fe4c02f73790/jsonbourne-0.29.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8ed38c9b831e49658afc055a89283a1ea714b7a55d416426c4133655a1c05ab5",
"md5": "47c447918e1d8363e06318a7706ce669",
"sha256": "8d2efb1d44eec3796484243592a76f6e4c15208311da39de1fc4937faba5ea79"
},
"downloads": -1,
"filename": "jsonbourne-0.29.0.tar.gz",
"has_sig": false,
"md5_digest": "47c447918e1d8363e06318a7706ce669",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 25798,
"upload_time": "2024-05-01T17:30:32",
"upload_time_iso_8601": "2024-05-01T17:30:32.555464Z",
"url": "https://files.pythonhosted.org/packages/8e/d3/8c9b831e49658afc055a89283a1ea714b7a55d416426c4133655a1c05ab5/jsonbourne-0.29.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-01 17:30:32",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "dynamic-graphics-inc",
"github_project": "dgpy-libs",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "jsonbourne"
}