From 4ac51514d28ae41d1013305a9519c3d1e8b437ef Mon Sep 17 00:00:00 2001 From: Roni Choudhury Date: Mon, 22 Apr 2019 12:13:51 -0400 Subject: [PATCH 1/6] Fix v-for syntax --- client/src/views/NodeDetail.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/views/NodeDetail.vue b/client/src/views/NodeDetail.vue index 0ae34a2e..d9efb508 100644 --- a/client/src/views/NodeDetail.vue +++ b/client/src/views/NodeDetail.vue @@ -22,7 +22,7 @@
last
@@ -38,7 +38,7 @@
last
From 3ea3eb335b04a90e6d246969c916c78075b1601b Mon Sep 17 00:00:00 2001 From: Roni Choudhury Date: Mon, 22 Apr 2019 15:17:10 -0400 Subject: [PATCH 2/6] Spin graphql spec into its own file --- multinet/multinet/multinet.gql | 102 ++++++++++++++++++++++++++++++ multinet/multinet/schema.py | 111 +++------------------------------ 2 files changed, 109 insertions(+), 104 deletions(-) create mode 100644 multinet/multinet/multinet.gql diff --git a/multinet/multinet/multinet.gql b/multinet/multinet/multinet.gql new file mode 100644 index 00000000..7773ee44 --- /dev/null +++ b/multinet/multinet/multinet.gql @@ -0,0 +1,102 @@ +type Attribute { + # the key is the table name followed by the column name delimited by a slash, eg table/col + key: String! + # json representation of the value + value: String! +} + +# type Property { +# label: String! +# key: String! +# } + +# type EntityType { +# name: String! +# properties: [Property!]! +# } + +interface Entity { + # this is the id of the entity in all tables it's associated with + key: String! + type: String! + properties (keys: [String!]): [Attribute!] +} + +type Node implements Entity { + key: String! + type: String! + outgoing (limit: Int, offset: Int): EdgeList! + incoming (limit: Int, offset: Int): EdgeList! + properties (keys: [String!]): [Attribute!] +} + +type Edge implements Entity { + key: String! + type: String! + source: Node! + target: Node! + properties (keys: [String!]): [Attribute!] +} + +type Row { + key: String! + columns (keys: [String!]): [Attribute!]! +} + +type NodeList { + total: Int! + nodes (offset: Int, limit: Int): [Node!]! +} + +type EdgeList { + total: Int! + edges (offset: Int, limit: Int): [Edge!]! +} + +type RowList { + total: Int! + rows (offset: Int, limit: Int): [Row!]! +} + +type Table { + name: String! + primaryKey: String! + # a list of key strings as they would appear in Attribute + fields: [String!]! + rows: RowList! +} + +type Graph { + name: String! + nodeTypes: [String!]! + edgeTypes: [String!]! + nodes: NodeList! + edges: EdgeList! +} + +type Workspace { + name: String! + tables: [Table!]! + graphs: [Graph!]! +} + +type Query { + nodes (workspace: String!, graph: String!, nodeType: String, key: String, search: String): NodeList! + edges (workspace: String!, graph: String!, edgeType: String, key: String, search: String): EdgeList! + rows (workspace: String!, table: String!, key: String, search: String): RowList! + + workspaces (name: String): [Workspace!]! + graphs (workspace: String!, name: String): [Graph!]! + tables (workspace: String!, name: String): [Table!]! +} + +type Mutation { + workspace (name: String!): String! + graph (workspace: String!, name: String!, nodeTypes: [String!]!, edgeTypes: [String!]!): Graph! + table (workspace: String!, name: String!, fields: [String!]!, primaryKey: String): Table! +} + +schema { + query: Query + mutation: Mutation +} diff --git a/multinet/multinet/schema.py b/multinet/multinet/schema.py index 2eed375a..dacdbd80 100644 --- a/multinet/multinet/schema.py +++ b/multinet/multinet/schema.py @@ -1,112 +1,15 @@ +import os.path + from graphql import build_ast_schema from graphql.language.parser import parse from . import resolvers -schema = build_ast_schema(parse(""" - type Attribute { - # the key is the table name followed by the column name delimited by a slash, eg table/col - key: String! - # json representation of the value - value: String! - } - - # type Property { - # label: String! - # key: String! - # } - - # type EntityType { - # name: String! - # properties: [Property!]! - # } - - interface Entity { - # this is the id of the entity in all tables it's associated with - key: String! - type: String! - properties (keys: [String!]): [Attribute!] - } - - type Node implements Entity { - key: String! - type: String! - outgoing (limit: Int, offset: Int): EdgeList! - incoming (limit: Int, offset: Int): EdgeList! - properties (keys: [String!]): [Attribute!] - } - - type Edge implements Entity { - key: String! - type: String! - source: Node! - target: Node! - properties (keys: [String!]): [Attribute!] - } - - type Row { - key: String! - columns (keys: [String!]): [Attribute!]! - } - - type NodeList { - total: Int! - nodes (offset: Int, limit: Int): [Node!]! - } - - type EdgeList { - total: Int! - edges (offset: Int, limit: Int): [Edge!]! - } - - type RowList { - total: Int! - rows (offset: Int, limit: Int): [Row!]! - } - - type Table { - name: String! - primaryKey: String! - # a list of key strings as they would appear in Attribute - fields: [String!]! - rows: RowList! - } - - type Graph { - name: String! - nodeTypes: [String!]! - edgeTypes: [String!]! - nodes: NodeList! - edges: EdgeList! - } - - type Workspace { - name: String! - tables: [Table!]! - graphs: [Graph!]! - } - - type Query { - nodes (workspace: String!, graph: String!, nodeType: String, key: String, search: String): NodeList! - edges (workspace: String!, graph: String!, edgeType: String, key: String, search: String): EdgeList! - rows (workspace: String!, table: String!, key: String, search: String): RowList! - - workspaces (name: String): [Workspace!]! - graphs (workspace: String!, name: String): [Graph!]! - tables (workspace: String!, name: String): [Table!]! - } - - type Mutation { - workspace (name: String!): String! - graph (workspace: String!, name: String!, nodeTypes: [String!]!, edgeTypes: [String!]!): Graph! - table (workspace: String!, name: String!, fields: [String!]!, primaryKey: String): Table! - } - - schema { - query: Query - mutation: Mutation - } -""")) +schema_text = None +with open(os.path.join(os.path.dirname(__file__), 'multinet.gql')) as f: + schema_text = f.read() + +schema = build_ast_schema(parse(schema_text)) fields = schema.get_type('Query').fields fields['nodes'].resolver = resolvers.query_nodes From 9a0c1a0ad4165f86065c60c995595ea14774fb74 Mon Sep 17 00:00:00 2001 From: Roni Choudhury Date: Mon, 22 Apr 2019 15:18:43 -0400 Subject: [PATCH 3/6] Python3 fixes --- multinet/multinet/__init__.py | 2 +- multinet/multinet/db.py | 2 +- multinet/multinet/resolvers.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/multinet/multinet/__init__.py b/multinet/multinet/__init__.py index f7423333..343c75ed 100644 --- a/multinet/multinet/__init__.py +++ b/multinet/multinet/__init__.py @@ -50,7 +50,7 @@ def graphql(self, params): ) def bulk(self, params, workspace=None, table=None): logprint('Bulk Loading', level=logging.INFO) - rows = csv.DictReader(cherrypy.request.body) + rows = csv.DictReader(cherrypy.request.body.read().decode('utf8')) workspace = db.db(workspace) if workspace.has_collection(table): table = workspace.collection(table) diff --git a/multinet/multinet/db.py b/multinet/multinet/db.py index a92f6154..bc3a08fb 100644 --- a/multinet/multinet/db.py +++ b/multinet/multinet/db.py @@ -3,7 +3,7 @@ from girder import logprint from arango import ArangoClient -from types import * +from .types import * def with_client(fun): def wrapper(*args, **kwargs): diff --git a/multinet/multinet/resolvers.py b/multinet/multinet/resolvers.py index 24c3de9a..a166bf39 100644 --- a/multinet/multinet/resolvers.py +++ b/multinet/multinet/resolvers.py @@ -1,7 +1,7 @@ import os import logging from girder import plugin, logprint -from types import * +from .types import * from . import db @@ -95,7 +95,7 @@ def nodeIncoming(node, info): return RealizedQuery(db.incoming(node)) def attributes(entity, info, keys=None): - return [(key, value) for key, value in entity.data.iteritems() if (keys is None) or (key in keys)] + return [(key, value) for key, value in entity.data.items() if (keys is None) or (key in keys)] # MUTATIONS def create_workspace(root, info, name): From 35f430bef7e2c362113ff08d577eb0a08600ac87 Mon Sep 17 00:00:00 2001 From: Roni Choudhury Date: Mon, 22 Apr 2019 15:19:17 -0400 Subject: [PATCH 4/6] Fix calling sequence type errors --- multinet/multinet/db.py | 24 ++++++++++++------------ multinet/multinet/resolvers.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/multinet/multinet/db.py b/multinet/multinet/db.py index bc3a08fb..b88263e3 100644 --- a/multinet/multinet/db.py +++ b/multinet/multinet/db.py @@ -46,10 +46,10 @@ def workspace_graphs(workspace, arango=None): return [graph['name'] for graph in space.graphs()] @with_client -def table_fields(table, arango=None): - workspace = db(table.workspace, arango=arango) - if workspace.has_collection(table.table): - sample = workspace.collection(table.table).random() +def table_fields(query, arango=None): + workspace = db(query.workspace, arango=arango) + if workspace.has_collection(query.table): + sample = workspace.collection(query.table).random() return sample.keys() else: return [] @@ -135,16 +135,16 @@ def create_graph(graph, node_types, edge_types, arango=None): graph.delete_edge_definition(table, purge=False) for table in graph.vertex_collections(): - if table not in node_tables: + if table not in node_types: graph.delete_vertex_collection(table) @with_client -def table(table, arango=None): - workspace = db(table.workspace, arango=arango) - if workspace.has_collection(table.table): - return workspace.collection(table.table) +def table(query, arango=None): + workspace = db(query.workspace, arango=arango) + if workspace.has_collection(query.table): + return workspace.collection(query.table) elif create: - return workspace.create_collection(table.table) + return workspace.create_collection(query.table) else: return None @@ -159,7 +159,7 @@ def graph(graph, create=False, arango=None): return None def countRows(query): - collection = table(query.table) + collection = table(query) if query.id: return 1 elif query.search: @@ -168,7 +168,7 @@ def countRows(query): return collection.count() def fetchRows(query, cursor): - collection = table(query.table) + collection = table(query) if query.id: return [collection.get(query.id)] elif query.search: diff --git a/multinet/multinet/resolvers.py b/multinet/multinet/resolvers.py index a166bf39..194004db 100644 --- a/multinet/multinet/resolvers.py +++ b/multinet/multinet/resolvers.py @@ -50,7 +50,7 @@ def rows(query, info, offset=0, limit=10): return db.fetchRows(query, Cursor(offset, limit)) def table_rows(table, info): - return RowQuery(table, None, None) + return RowQuery(table.workspace, table.table, None, None) def workspace_name(workspace, info): return workspace From 3eef5950d4d17295628241ad1af334d4b705301b Mon Sep 17 00:00:00 2001 From: Mark Dewey Date: Mon, 22 Apr 2019 13:43:56 -0600 Subject: [PATCH 5/6] Adding Pipfile to enable pipenv. --- .gitignore | 1 + Pipfile | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 Pipfile diff --git a/.gitignore b/.gitignore index 1e29df53..fcddae1a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ venv/ yarn.lock +Pipfile.lock diff --git a/Pipfile b/Pipfile new file mode 100644 index 00000000..5d01805b --- /dev/null +++ b/Pipfile @@ -0,0 +1,17 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] + +[packages] +multinet = {path = "./multinet",editable = true} +python-arango = "*" +graphql-core = "*" + +[requires] +python_version = "3.7" + +[pipenv] +allow_prereleases = true From cc09647fcf5037bc4e5ba0a4183cc03e6ed04645 Mon Sep 17 00:00:00 2001 From: Mark Dewey Date: Tue, 23 Apr 2019 14:05:01 -0600 Subject: [PATCH 6/6] Updates to the readme file based on current development practices. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb887368..1f3c4934 100644 --- a/README.md +++ b/README.md @@ -9,11 +9,11 @@ Follow the instructions at [multinet-server-poc](https://github.com/multinet-app ### Set Up Girder 1. Clone this repository: `git clone https://github.com/multinet-app/multinet-girder; cd multinet-girder` -2. Create and activate a Python virtual environment: `virtualenv venv; source -./venv/bin/activate` -3. Perform an editable install of the plugin package: `pip install -e multinet` +2. Start the mongo and arango databases using docker-compose: `MULTINET_ROOT_PASSWORD=yourSecretPassword docker-compose up -d` +2. Use pipenv to create a virtual environment and install the dependencies: `pipenv install` +3. Start the pipenv shell to set up girder and run the websever: `pipenv shell` 4. Build the Girder web client: `girder build` -5. Serve the Girder client: `girder serve --database +5. Serve the Girder client: `MULTINET_ROOT_PASSWORD=yourSecretPassword girder serve --database mongodb://localhost:27017/multinet --port 9090` 6. Open the Girder client and register a user (which will become an admin user): http://localhost:9090