initial
This commit is contained in:
parent
df5ed9c047
commit
95767ae684
118
.gitignore
vendored
Normal file
118
.gitignore
vendored
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
README.rst
|
||||||
|
|
||||||
|
.vagrant
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
env/
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit tests / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*,cover
|
||||||
|
.hypothesis/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IPython Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# dotenv
|
||||||
|
.env
|
||||||
|
envfile
|
||||||
|
|
||||||
|
# virtualenv
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# Vim
|
||||||
|
Session.vim
|
||||||
|
|
||||||
|
# Pycharm
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# sqlite db for testing
|
||||||
|
local.db
|
||||||
|
/tests/fast-test.sh
|
||||||
|
/tests/fastest-test.sh
|
||||||
|
/tests/sbds-install.sh
|
||||||
|
/tests/test.sh
|
||||||
|
/tests/sync.sh
|
||||||
|
/tests/failed_blocks/
|
||||||
|
tests/failed_blocks/
|
||||||
|
/envdir/
|
||||||
|
/sbds.egg-info/
|
||||||
|
/envd/
|
||||||
|
/tests/envdir-to-envfile.sh
|
||||||
|
/deploy/
|
||||||
|
/test.py
|
||||||
|
|
||||||
|
.DS_Store
|
34
Dockerfile
Normal file
34
Dockerfile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
FROM phusion/baseimage:0.9.19
|
||||||
|
|
||||||
|
# Standard stuff
|
||||||
|
ENV LANG en_US.UTF-8
|
||||||
|
ENV LC_ALL en_US.UTF-8
|
||||||
|
|
||||||
|
# Stuff for building steem-python
|
||||||
|
ARG BUILD_ROOT=/build
|
||||||
|
|
||||||
|
# Now we install the essentials
|
||||||
|
RUN \
|
||||||
|
apt-get update && \
|
||||||
|
apt-get install -y python3-pip
|
||||||
|
|
||||||
|
# This updates the distro-provided pip
|
||||||
|
RUN pip3 install --upgrade pip
|
||||||
|
|
||||||
|
RUN mkdir ${BUILD_ROOT}
|
||||||
|
|
||||||
|
COPY Makefile ${BUILD_ROOT}/
|
||||||
|
COPY Pipfile ${BUILD_ROOT}/
|
||||||
|
COPY Pipfile.lock ${BUILD_ROOT}/
|
||||||
|
|
||||||
|
WORKDIR ${BUILD_ROOT}
|
||||||
|
|
||||||
|
RUN pip3 install --upgrade pip && \
|
||||||
|
pip3 install --upgrade pipenv && \
|
||||||
|
pipenv install --three --dev && \
|
||||||
|
pipenv install .
|
||||||
|
|
||||||
|
COPY . ${BUILD_ROOT}
|
||||||
|
|
||||||
|
# run tests
|
||||||
|
RUN pipenv run py.test
|
28
Pipfile
Normal file
28
Pipfile
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
[[source]]
|
||||||
|
|
||||||
|
url = "https://pypi.python.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
name = "pypi"
|
||||||
|
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
|
||||||
|
attrdict = "*"
|
||||||
|
appdirs = "*"
|
||||||
|
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
"pep8" = "*"
|
||||||
|
pytest = "*"
|
||||||
|
"pytest-pep8" = "*"
|
||||||
|
pytest-pylint = "*"
|
||||||
|
yapf = "*"
|
||||||
|
"autopep8" = "*"
|
||||||
|
"flake8" = "*"
|
||||||
|
"pytest-flake8" = "*"
|
||||||
|
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
|
||||||
|
python_version = "3.6"
|
243
Pipfile.lock
generated
Normal file
243
Pipfile.lock
generated
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "0cff184f2ce33ae5643e32fe505945779e8c9ae2e91b46c1c38f5938bf42050e"
|
||||||
|
},
|
||||||
|
"host-environment-markers": {
|
||||||
|
"implementation_name": "cpython",
|
||||||
|
"implementation_version": "3.6.4",
|
||||||
|
"os_name": "posix",
|
||||||
|
"platform_machine": "x86_64",
|
||||||
|
"platform_python_implementation": "CPython",
|
||||||
|
"platform_release": "17.3.0",
|
||||||
|
"platform_system": "Darwin",
|
||||||
|
"platform_version": "Darwin Kernel Version 17.3.0: Thu Nov 9 18:09:22 PST 2017; root:xnu-4570.31.3~1/RELEASE_X86_64",
|
||||||
|
"python_full_version": "3.6.4",
|
||||||
|
"python_version": "3.6",
|
||||||
|
"sys_platform": "darwin"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.6"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.python.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"appdirs": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e",
|
||||||
|
"sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"
|
||||||
|
],
|
||||||
|
"version": "==1.4.3"
|
||||||
|
},
|
||||||
|
"attrdict": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:86aeb6d3809e0344409f8148d7cac9eabce5f0b577c160b5e90d10df3f8d2ad3"
|
||||||
|
],
|
||||||
|
"version": "==2.0.0"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
|
||||||
|
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
|
||||||
|
],
|
||||||
|
"version": "==1.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {
|
||||||
|
"apipkg": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:65d2aa68b28e7d31233bb2ba8eb31cda40e4671f8ac2d6b241e358c9652a74b9",
|
||||||
|
"sha256:2e38399dbe842891fe85392601aab8f40a8f4cc5a9053c326de35a1cc0297ac6"
|
||||||
|
],
|
||||||
|
"version": "==1.4"
|
||||||
|
},
|
||||||
|
"astroid": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:db5cfc9af6e0b60cd07c19478fb54021fc20d2d189882fbcbc94fc69a8aecc58",
|
||||||
|
"sha256:f0a0e386dbca9f93ea9f3ea6f32b37a24720502b7baa9cb17c3976a680d43a06"
|
||||||
|
],
|
||||||
|
"version": "==1.6.1"
|
||||||
|
},
|
||||||
|
"attrs": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a17a9573a6f475c99b551c0e0a812707ddda1ec9653bed04c13841404ed6f450",
|
||||||
|
"sha256:1c7960ccfd6a005cd9f7ba884e6316b5e430a3f1a6c37c5f87d8b43f83b54ec9"
|
||||||
|
],
|
||||||
|
"version": "==17.4.0"
|
||||||
|
},
|
||||||
|
"autopep8": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:c7be71ab0cb2f50c9c22c82f0c9acaafc6f57492c3fbfee9790c415005c2b9a5"
|
||||||
|
],
|
||||||
|
"version": "==1.3.4"
|
||||||
|
},
|
||||||
|
"execnet": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:fc155a6b553c66c838d1a22dba1dc9f5f505c43285a878c6f74a79c024750b83",
|
||||||
|
"sha256:a7a84d5fa07a089186a329528f127c9d73b9de57f1a1131b82bb5320ee651f6a"
|
||||||
|
],
|
||||||
|
"version": "==1.5.0"
|
||||||
|
},
|
||||||
|
"flake8": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37",
|
||||||
|
"sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0"
|
||||||
|
],
|
||||||
|
"version": "==3.5.0"
|
||||||
|
},
|
||||||
|
"isort": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:cd5d3fc2c16006b567a17193edf4ed9830d9454cbeb5a42ac80b36ea00c23db4",
|
||||||
|
"sha256:79f46172d3a4e2e53e7016e663cc7a8b538bec525c36675fcfd2767df30b3983"
|
||||||
|
],
|
||||||
|
"version": "==4.2.15"
|
||||||
|
},
|
||||||
|
"lazy-object-proxy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:209615b0fe4624d79e50220ce3310ca1a9445fd8e6d3572a896e7f9146bbf019",
|
||||||
|
"sha256:1b668120716eb7ee21d8a38815e5eb3bb8211117d9a90b0f8e21722c0758cc39",
|
||||||
|
"sha256:cb924aa3e4a3fb644d0c463cad5bc2572649a6a3f68a7f8e4fbe44aaa6d77e4c",
|
||||||
|
"sha256:2c1b21b44ac9beb0fc848d3993924147ba45c4ebc24be19825e57aabbe74a99e",
|
||||||
|
"sha256:320ffd3de9699d3892048baee45ebfbbf9388a7d65d832d7e580243ade426d2b",
|
||||||
|
"sha256:2df72ab12046a3496a92476020a1a0abf78b2a7db9ff4dc2036b8dd980203ae6",
|
||||||
|
"sha256:27ea6fd1c02dcc78172a82fc37fcc0992a94e4cecf53cb6d73f11749825bd98b",
|
||||||
|
"sha256:e5b9e8f6bda48460b7b143c3821b21b452cb3a835e6bbd5dd33aa0c8d3f5137d",
|
||||||
|
"sha256:7661d401d60d8bf15bb5da39e4dd72f5d764c5aff5a86ef52a042506e3e970ff",
|
||||||
|
"sha256:61a6cf00dcb1a7f0c773ed4acc509cb636af2d6337a08f362413c76b2b47a8dd",
|
||||||
|
"sha256:bd6292f565ca46dee4e737ebcc20742e3b5be2b01556dafe169f6c65d088875f",
|
||||||
|
"sha256:933947e8b4fbe617a51528b09851685138b49d511af0b6c0da2539115d6d4514",
|
||||||
|
"sha256:d0fc7a286feac9077ec52a927fc9fe8fe2fabab95426722be4c953c9a8bede92",
|
||||||
|
"sha256:7f3a2d740291f7f2c111d86a1c4851b70fb000a6c8883a59660d95ad57b9df35",
|
||||||
|
"sha256:5276db7ff62bb7b52f77f1f51ed58850e315154249aceb42e7f4c611f0f847ff",
|
||||||
|
"sha256:94223d7f060301b3a8c09c9b3bc3294b56b2188e7d8179c762a1cda72c979252",
|
||||||
|
"sha256:6ae6c4cb59f199d8827c5a07546b2ab7e85d262acaccaacd49b62f53f7c456f7",
|
||||||
|
"sha256:f460d1ceb0e4a5dcb2a652db0904224f367c9b3c1470d5a7683c0480e582468b",
|
||||||
|
"sha256:e81ebf6c5ee9684be8f2c87563880f93eedd56dd2b6146d8a725b50b7e5adb0f",
|
||||||
|
"sha256:81304b7d8e9c824d058087dcb89144842c8e0dea6d281c031f59f0acf66963d4",
|
||||||
|
"sha256:ddc34786490a6e4ec0a855d401034cbd1242ef186c20d79d2166d6a4bd449577",
|
||||||
|
"sha256:7bd527f36a605c914efca5d3d014170b2cb184723e423d26b1fb2fd9108e264d",
|
||||||
|
"sha256:ab3ca49afcb47058393b0122428358d2fbe0408cf99f1b58b295cfeb4ed39109",
|
||||||
|
"sha256:7cb54db3535c8686ea12e9535eb087d32421184eacc6939ef15ef50f83a5e7e2",
|
||||||
|
"sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33",
|
||||||
|
"sha256:e34b155e36fa9da7e1b7c738ed7767fc9491a62ec6af70fe9da4a057759edc2d",
|
||||||
|
"sha256:50e3b9a464d5d08cc5227413db0d1c4707b6172e4d4d915c1c70e4de0bbff1f5",
|
||||||
|
"sha256:27bf62cb2b1a2068d443ff7097ee33393f8483b570b475db8ebf7e1cba64f088",
|
||||||
|
"sha256:eb91be369f945f10d3a49f5f9be8b3d0b93a4c2be8f8a5b83b0571b8123e0a7a"
|
||||||
|
],
|
||||||
|
"version": "==1.3.1"
|
||||||
|
},
|
||||||
|
"mccabe": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
|
||||||
|
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
|
||||||
|
],
|
||||||
|
"version": "==0.6.1"
|
||||||
|
},
|
||||||
|
"pep8": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:b22cfae5db09833bb9bd7c8463b53e1a9c9b39f12e304a8d0bba729c501827ee",
|
||||||
|
"sha256:fe249b52e20498e59e0b5c5256aa52ee99fc295b26ec9eaa85776ffdb9fe6374"
|
||||||
|
],
|
||||||
|
"version": "==1.7.1"
|
||||||
|
},
|
||||||
|
"pluggy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff"
|
||||||
|
],
|
||||||
|
"version": "==0.6.0"
|
||||||
|
},
|
||||||
|
"py": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:8cca5c229d225f8c1e3085be4fcf306090b00850fefad892f9d96c7b6e2f310f",
|
||||||
|
"sha256:ca18943e28235417756316bfada6cd96b23ce60dd532642690dcfdaba988a76d"
|
||||||
|
],
|
||||||
|
"version": "==1.5.2"
|
||||||
|
},
|
||||||
|
"pycodestyle": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9",
|
||||||
|
"sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766"
|
||||||
|
],
|
||||||
|
"version": "==2.3.1"
|
||||||
|
},
|
||||||
|
"pyflakes": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f",
|
||||||
|
"sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805"
|
||||||
|
],
|
||||||
|
"version": "==1.6.0"
|
||||||
|
},
|
||||||
|
"pylint": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:156839bedaa798febee72893beef00c650c2e7abafb5586fc7a6a56be7f80412",
|
||||||
|
"sha256:4fe3b99da7e789545327b75548cee6b511e4faa98afe268130fea1af4b5ec022"
|
||||||
|
],
|
||||||
|
"version": "==1.8.2"
|
||||||
|
},
|
||||||
|
"pytest": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:b84878865558194630c6147f44bdaef27222a9f153bbd4a08908b16bf285e0b1",
|
||||||
|
"sha256:53548280ede7818f4dc2ad96608b9f08ae2cc2ca3874f2ceb6f97e3583f25bc4"
|
||||||
|
],
|
||||||
|
"version": "==3.3.2"
|
||||||
|
},
|
||||||
|
"pytest-cache": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:be7468edd4d3d83f1e844959fd6e3fd28e77a481440a7118d430130ea31b07a9"
|
||||||
|
],
|
||||||
|
"version": "==1.0"
|
||||||
|
},
|
||||||
|
"pytest-flake8": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:e67686645860009cf1f9a5016e110234b4a2c4584711d62ba753ed651ab9ab28",
|
||||||
|
"sha256:e716072d07a557defdd5c4141984569731e292961370a5663c1697283aa16200"
|
||||||
|
],
|
||||||
|
"version": "==0.9.1"
|
||||||
|
},
|
||||||
|
"pytest-pep8": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:032ef7e5fa3ac30f4458c73e05bb67b0f036a8a5cb418a534b3170f89f120318"
|
||||||
|
],
|
||||||
|
"version": "==1.0.6"
|
||||||
|
},
|
||||||
|
"pytest-pylint": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:9b8ca25823b2f39e89d8170453f5282e57b973395060e838ced5f8c09271ca65",
|
||||||
|
"sha256:2efaf761472637df9a8f4a3f4fac37f8ce433d70957c5f5767c4be322a42a3d2",
|
||||||
|
"sha256:9f38725b22967a56724115c9df0a93dda37fea71dd5495fb1354b82e3d938d0d",
|
||||||
|
"sha256:85da6403c69eb715b9703df640818f337603f2cac947f932b033588851aaaf16",
|
||||||
|
"sha256:b85763dc36757bfb736b07fecb4f67a0892dcb00868e01f150c7424f608bd62e",
|
||||||
|
"sha256:ec63f7c4c05331654ab54fda8e68b8a11512009d506a8e35ee9b6d40a359356d",
|
||||||
|
"sha256:2bb26948f0355d14b274742153a6b4daa51e6d60481143bfd7f025699a27210d"
|
||||||
|
],
|
||||||
|
"version": "==0.7.1"
|
||||||
|
},
|
||||||
|
"six": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb",
|
||||||
|
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9"
|
||||||
|
],
|
||||||
|
"version": "==1.11.0"
|
||||||
|
},
|
||||||
|
"wrapt": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6"
|
||||||
|
],
|
||||||
|
"version": "==1.10.11"
|
||||||
|
},
|
||||||
|
"yapf": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:a0bbc8ed274609f9c7575a5d69056fa393e26a778b3e070a72f4998b8e90c3cd",
|
||||||
|
"sha256:bd19f246be7193ad2acdc04702b92315f1ae28d49c82f6671afdeefe9d32f468"
|
||||||
|
],
|
||||||
|
"version": "==0.20.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
README.markdown
Normal file
40
README.markdown
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# jsondict
|
||||||
|
|
||||||
|
This is a python package called jsondict that wraps a dict to
|
||||||
|
provide dumb json file backed persistence.
|
||||||
|
|
||||||
|
It also returns a default of `None` for missing keys instead of KeyError,
|
||||||
|
because an exception for an undefined key is annoying, so it's sort of like
|
||||||
|
a defaultdict.
|
||||||
|
|
||||||
|
It's not general purpose, and it's not for large amounts of data. It's
|
||||||
|
just sort of like a standard dictionary that you don't need to worry about
|
||||||
|
reading/saving to disk. It's naive and inefficient but perfect for
|
||||||
|
application configs and whatnot. Don't be silly and put more than a few
|
||||||
|
kilobytes in this, the whole file is written out every update and the whole
|
||||||
|
file is re-read and re-parsed every read.
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
pip3 install --upgrade pipenv
|
||||||
|
git clone https://github.com/sneak/jsondict.git
|
||||||
|
cd jsondict
|
||||||
|
pipenv install --three .
|
||||||
|
```
|
||||||
|
|
||||||
|
# Other Info
|
||||||
|
|
||||||
|
Right now it's only tested on python3. Python2 support is desired.
|
||||||
|
|
||||||
|
# Author
|
||||||
|
|
||||||
|
Jeffrey Paul <sneak@sneak.berlin>
|
||||||
|
|
||||||
|
# See Also
|
||||||
|
|
||||||
|
* [attrdict](https://github.com/bcj/AttrDict)
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
MIT
|
11
circle.yml
Normal file
11
circle.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
machine:
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
override:
|
||||||
|
- echo "Ignore CircleCI detected dependencies"
|
||||||
|
|
||||||
|
test:
|
||||||
|
override:
|
||||||
|
- docker build -t sneak/persistentattrdict .
|
63
jsondict/__init__.py
Normal file
63
jsondict/__init__.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
from attrdict import AttrDict
|
||||||
|
import json
|
||||||
|
import os.path
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
class JsonDict(object):
|
||||||
|
def __init__(self,persistence=None):
|
||||||
|
# TODO: either filename or file-like object
|
||||||
|
# for now, just filename
|
||||||
|
self._persistence = persistence
|
||||||
|
self._wrapped = dict()
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
self._reread()
|
||||||
|
return len(self._wrapped)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
self._reread()
|
||||||
|
return self._wrapped.keys()
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
self._reread()
|
||||||
|
return self._wrapped.values()
|
||||||
|
|
||||||
|
def __setitem__(self, key, item):
|
||||||
|
self._wrapped[key] = item
|
||||||
|
self._commit()
|
||||||
|
return item
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
del self._wrapped[key]
|
||||||
|
self._commit()
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
self._reread()
|
||||||
|
if key in self._wrapped:
|
||||||
|
return self._wrapped[key]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _commit(self):
|
||||||
|
serialized = json.dumps(self._wrapped)
|
||||||
|
atomic_write(self._persistence, serialized)
|
||||||
|
|
||||||
|
def _reread(self):
|
||||||
|
with open(self._persistence, 'rb') as fd:
|
||||||
|
self._wrapped = json.load(fd)
|
||||||
|
|
||||||
|
#def PersistentAppAttrDict(appname):
|
||||||
|
#configfilename = appdirs.user_data_dir(appname,appname) + "appconfig.json"
|
||||||
|
#open
|
||||||
|
|
||||||
|
def atomic_write(fn,content):
|
||||||
|
filedir = os.path.dirname(os.path.abspath(fn))
|
||||||
|
if not os.path.exists(filedir):
|
||||||
|
os.makedirs(filedir)
|
||||||
|
(tempfd, tempfn) = tempfile.mkstemp(dir=filedir)
|
||||||
|
tempfh = os.fdopen(tempfd, 'w')
|
||||||
|
tempfh.write(content)
|
||||||
|
tempfh.close()
|
||||||
|
os.rename(tempfn,fn)
|
18
setup.cfg
Normal file
18
setup.cfg
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
[metadata]
|
||||||
|
description-file=README.markdown
|
||||||
|
[aliases]
|
||||||
|
test=pytest
|
||||||
|
|
||||||
|
[tool:pytest]
|
||||||
|
norecursedirs=dist docs build .tox deploy
|
||||||
|
addopts = --pep8 --flake8
|
||||||
|
testpaths = tests
|
||||||
|
|
||||||
|
[yapf]
|
||||||
|
indent_width = 4
|
||||||
|
column_limit = 77
|
||||||
|
based_on_style = pep8
|
||||||
|
spaces_before_comment = 2
|
||||||
|
split_before_logical_operator = true
|
||||||
|
dedent_closing_brackets = true
|
||||||
|
i18n_comment = NOQA
|
36
setup.py
Normal file
36
setup.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from pipenv.project import Project
|
||||||
|
from pipenv.utils import convert_deps_to_pip
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
import sys
|
||||||
|
|
||||||
|
pfile = Project(chdir=False).parsed_pipfile
|
||||||
|
requirements = convert_deps_to_pip(pfile['packages'], r=False)
|
||||||
|
test_requirements = convert_deps_to_pip(pfile['dev-packages'], r=False)
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='jsondict',
|
||||||
|
version='0.0.1',
|
||||||
|
description='dumb json persistence for a dict with defaults',
|
||||||
|
long_description=open('README.markdown','r').read(),
|
||||||
|
keywords=['persistence', 'json', 'datastructure'],
|
||||||
|
license='MIT',
|
||||||
|
url='https://github.com/sneak/jsondict',
|
||||||
|
maintainer='Jeffrey Paul',
|
||||||
|
maintainer_email='sneak@sneak.berlin',
|
||||||
|
packages=find_packages(),
|
||||||
|
setup_requires=[
|
||||||
|
'pytest-runner',
|
||||||
|
'pipenv',
|
||||||
|
],
|
||||||
|
tests_require=test_requirements,
|
||||||
|
install_requires=requirements,
|
||||||
|
classifiers=[
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'License :: OSI Approved :: MIT License',
|
||||||
|
'Natural Language :: English',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Topic :: Software Development :: Libraries',
|
||||||
|
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||||
|
'Development Status :: 4 - Beta'
|
||||||
|
])
|
3
tests/__init__.py
Normal file
3
tests/__init__.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from logging import getLogger
|
||||||
|
|
||||||
|
getLogger('flake8').propagate = False
|
11
tests/test_import.py
Normal file
11
tests/test_import.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, os.path.abspath('..'))
|
||||||
|
|
||||||
|
from jsondict import JsonDict # noqa
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=unused-import,unused-variable
|
||||||
|
def test_import():
|
||||||
|
_ = JsonDict() # noqa
|
40
tests/test_pdd.py
Normal file
40
tests/test_pdd.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from jsondict import JsonDict, atomic_write
|
||||||
|
import json
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class Testcases(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_atomic_write(self):
|
||||||
|
ts = "this is my test string"
|
||||||
|
tfn = '/tmp/pad_test.txt'
|
||||||
|
atomic_write(tfn, ts)
|
||||||
|
with open(tfn, 'r') as fh:
|
||||||
|
self.assertEqual(fh.read(), ts)
|
||||||
|
|
||||||
|
def test_persistence(self):
|
||||||
|
tfn = '/tmp/pad_test.json'
|
||||||
|
mypdd = JsonDict(persistence=tfn)
|
||||||
|
mypdd['testattr'] = 'loldongs'
|
||||||
|
|
||||||
|
with open(tfn, 'r') as fh:
|
||||||
|
x = json.load(fh)
|
||||||
|
|
||||||
|
self.assertEqual(x['testattr'], 'loldongs')
|
||||||
|
|
||||||
|
del mypdd['testattr']
|
||||||
|
|
||||||
|
self.assertEqual(mypdd['testattr'], None)
|
||||||
|
|
||||||
|
def test_read(self):
|
||||||
|
tfn = '/tmp/pad_test.json'
|
||||||
|
mypdd = JsonDict(persistence=tfn)
|
||||||
|
mypdd['testattr'] = 'loldongs'
|
||||||
|
|
||||||
|
with open(tfn, 'w') as fh:
|
||||||
|
json.dump({'testattr': 'notloldongs'}, fh)
|
||||||
|
|
||||||
|
self.assertNotEqual(mypdd['testattr'], 'loldongs')
|
||||||
|
|
||||||
|
self.assertEqual(mypdd['nonexist'], None)
|
Loading…
Reference in New Issue
Block a user