Merge branch 'mysql'
This commit is contained in:
commit
a8787d0ff2
|
@ -20,7 +20,7 @@ ADD . /tmp/code/
|
||||||
COPY --from=0 /tmp/code/styles/dist/style.css /tmp/code/styles/dist/style.css
|
COPY --from=0 /tmp/code/styles/dist/style.css /tmp/code/styles/dist/style.css
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y python3-pip sudo
|
apt-get install -y python3-pip sudo git
|
||||||
|
|
||||||
RUN pip3 install -U pip && \
|
RUN pip3 install -U pip && \
|
||||||
cd /tmp/code && \
|
cd /tmp/code && \
|
||||||
|
@ -28,8 +28,6 @@ RUN pip3 install -U pip && \
|
||||||
python3 setup.py install && \
|
python3 setup.py install && \
|
||||||
useradd --uid 1000 app
|
useradd --uid 1000 app
|
||||||
|
|
||||||
VOLUME /data/
|
|
||||||
|
|
||||||
ADD start /start
|
ADD start /start
|
||||||
|
|
||||||
ENTRYPOINT ["/start"]
|
ENTRYPOINT ["/start"]
|
||||||
|
|
|
@ -8,6 +8,9 @@ import tempfile
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
APPNAME = "npcli"
|
APPNAME = "npcli"
|
||||||
CONFDIR = user_config_dir(APPNAME)
|
CONFDIR = user_config_dir(APPNAME)
|
||||||
CONFPATH = os.path.join(CONFDIR, "conf.json")
|
CONFPATH = os.path.join(CONFDIR, "conf.json")
|
||||||
|
@ -74,6 +77,9 @@ def main():
|
||||||
|
|
||||||
spr_dump = spr_action.add_parser("dump", help="dump the database")
|
spr_dump = spr_action.add_parser("dump", help="dump the database")
|
||||||
|
|
||||||
|
spr_import = spr_action.add_parser("import", help="import a database dump")
|
||||||
|
spr_import.add_argument("fname", help="db dump yaml file to import")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
r = requests.session()
|
r = requests.session()
|
||||||
|
|
||||||
|
@ -131,6 +137,21 @@ def main():
|
||||||
|
|
||||||
print(yaml.dump(dump, default_flow_style=False))
|
print(yaml.dump(dump, default_flow_style=False))
|
||||||
|
|
||||||
|
elif args.action == "import":
|
||||||
|
with open(args.fname) as f:
|
||||||
|
dump = yaml.load(f)
|
||||||
|
|
||||||
|
for clsname in dump["classes"]:
|
||||||
|
r.put(args.host.rstrip("/") + "/api/class/" + clsname).raise_for_status()
|
||||||
|
|
||||||
|
# just make the nodes first
|
||||||
|
for nodename, nodebody in dump["nodes"].items():
|
||||||
|
putnode(nodename, yaml.dump({"body": {}, "classes": {}, "parents": []})).raise_for_status()
|
||||||
|
|
||||||
|
# then fill out node bodies to avoid missing parent ordering issues
|
||||||
|
for nodename, nodebody in dump["nodes"].items():
|
||||||
|
putnode(nodename, yaml.dump(nodebody)).raise_for_status()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -3,10 +3,10 @@ import cherrypy
|
||||||
import logging
|
import logging
|
||||||
from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment
|
from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment
|
||||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||||
from nodepupper.common import pwhash
|
|
||||||
import math
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
import math
|
||||||
import yaml
|
import yaml
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
|
||||||
|
@ -206,7 +206,8 @@ class ClassesApi(object):
|
||||||
|
|
||||||
def PUT(self, cls):
|
def PUT(self, cls):
|
||||||
with self.nodes.db.transaction() as c:
|
with self.nodes.db.transaction() as c:
|
||||||
c.root.classes[cls] = NClass(cls)
|
if cls not in c.root.classes:
|
||||||
|
c.root.classes[cls] = NClass(cls)
|
||||||
|
|
||||||
def DELETE(self, cls):
|
def DELETE(self, cls):
|
||||||
with self.nodes.db.transaction() as c:
|
with self.nodes.db.transaction() as c:
|
||||||
|
@ -278,7 +279,8 @@ def main():
|
||||||
parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on")
|
parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on")
|
||||||
# parser.add_argument('-l', '--library', default="./library", help="library path")
|
# parser.add_argument('-l', '--library', default="./library", help="library path")
|
||||||
# parser.add_argument('-c', '--cache', default="./cache", help="cache path")
|
# parser.add_argument('-c', '--cache', default="./cache", help="cache path")
|
||||||
parser.add_argument('-s', '--database', default="./pupper.db", help="path to persistent sqlite database")
|
parser.add_argument('-s', '--database', default=os.environ.get('DATABASE_URI', None),
|
||||||
|
help="mysql:// connection uri")
|
||||||
parser.add_argument('--debug', action="store_true", help="enable development options")
|
parser.add_argument('--debug', action="store_true", help="enable development options")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -286,6 +288,10 @@ def main():
|
||||||
logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING,
|
logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING,
|
||||||
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
|
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
|
||||||
|
|
||||||
|
if not args.database:
|
||||||
|
print("--database or $DATABASE_URI is required")
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
library = NodeOps(args.database)
|
library = NodeOps(args.database)
|
||||||
|
|
||||||
tpl_dir = os.path.join(APPROOT, "templates") if not args.debug else "templates"
|
tpl_dir = os.path.join(APPROOT, "templates") if not args.debug else "templates"
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
from urllib.parse import urlparse
|
||||||
import ZODB
|
import ZODB
|
||||||
import ZODB.FileStorage
|
from relstorage.storage import RelStorage
|
||||||
|
from relstorage.options import Options
|
||||||
|
from relstorage.adapters.mysql import MySQLAdapter
|
||||||
import persistent
|
import persistent
|
||||||
import persistent.list
|
import persistent.list
|
||||||
import persistent.mapping
|
import persistent.mapping
|
||||||
|
@ -40,8 +43,12 @@ class NClassAttachment(persistent.Persistent):
|
||||||
|
|
||||||
|
|
||||||
class NodeOps(object):
|
class NodeOps(object):
|
||||||
def __init__(self, db_path):
|
def __init__(self, db_uri):
|
||||||
self.storage = ZODB.FileStorage.FileStorage(db_path)
|
uri = urlparse(db_uri)
|
||||||
|
|
||||||
|
self.mysql = MySQLAdapter(host=uri.hostname, user=uri.username, passwd=uri.password, db=uri.path[1:],
|
||||||
|
options=Options(keep_history=False))
|
||||||
|
self.storage = RelStorage(adapter=self.mysql)
|
||||||
self.db = ZODB.DB(self.storage)
|
self.db = ZODB.DB(self.storage)
|
||||||
|
|
||||||
with self.db.transaction() as c:
|
with self.db.transaction() as c:
|
||||||
|
|
|
@ -1,26 +1,35 @@
|
||||||
appdirs==1.4.3
|
appdirs==1.4.3
|
||||||
|
asn1crypto==0.24.0
|
||||||
backports.functools-lru-cache==1.5
|
backports.functools-lru-cache==1.5
|
||||||
BTrees==4.5.1
|
BTrees==4.5.1
|
||||||
certifi==2018.11.29
|
certifi==2018.11.29
|
||||||
|
cffi==1.12.2
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
cheroot==6.5.2
|
cheroot==6.5.2
|
||||||
CherryPy==18.0.1
|
CherryPy==18.0.1
|
||||||
|
cryptography==2.6.1
|
||||||
idna==2.8
|
idna==2.8
|
||||||
jaraco.functools==1.20
|
jaraco.functools==1.20
|
||||||
Jinja2==2.10
|
Jinja2==2.10
|
||||||
MarkupSafe==1.0
|
MarkupSafe==1.0
|
||||||
more-itertools==4.3.0
|
more-itertools==4.3.0
|
||||||
|
perfmetrics==2.0
|
||||||
persistent==4.4.2
|
persistent==4.4.2
|
||||||
portend==2.3
|
portend==2.3
|
||||||
|
pycparser==2.19
|
||||||
|
PyMySQL==0.9.3
|
||||||
pytz==2018.5
|
pytz==2018.5
|
||||||
PyYAML==3.13
|
PyYAML==3.13
|
||||||
|
-e git+https://git.davepedu.com/dave/relstorage.git@5ae138b71a0eeb740208e61cfd1662c49738ee45#egg=RelStorage
|
||||||
requests==2.21.0
|
requests==2.21.0
|
||||||
six==1.11.0
|
six==1.11.0
|
||||||
tempora==1.13
|
tempora==1.13
|
||||||
transaction==2.2.1
|
transaction==2.4.0
|
||||||
urllib3==1.24.1
|
urllib3==1.24.1
|
||||||
zc.lockfile==1.3.0
|
zc.lockfile==1.3.0
|
||||||
ZConfig==3.3.0
|
ZConfig==3.3.0
|
||||||
ZODB==5.4.0
|
zdaemon==4.3
|
||||||
|
ZEO==5.2.1
|
||||||
|
ZODB==5.5.1
|
||||||
zodbpickle==1.0.2
|
zodbpickle==1.0.2
|
||||||
zope.interface==4.5.0
|
zope.interface==4.5.0
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -4,9 +4,9 @@ from setuptools import setup
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.0.1"
|
__version__ = "0.0.2"
|
||||||
with open(os.path.join(os.path.dirname(__file__), "requirements.txt")) as f:
|
with open(os.path.join(os.path.dirname(__file__), "requirements.txt")) as f:
|
||||||
__requirements__ = [line.strip() for line in f.readlines()]
|
__requirements__ = [line.strip() for line in f.readlines() if not line.startswith("-")]
|
||||||
|
|
||||||
|
|
||||||
setup(name='nodepupper',
|
setup(name='nodepupper',
|
||||||
|
|
Loading…
Reference in New Issue