Skip to content
This repository was archived by the owner on Feb 23, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
venv/
yarn.lock
Pipfile.lock
17 changes: 17 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions client/src/views/NodeDetail.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<div v-if="nextIncoming" v-on:click="lastPage('incoming')">last</div>
</div>
<ul>
<li v-for="edge, index in incoming" :key="index">
<li v-for="(edge, index) in incoming" :key="index">
<router-link :to="`/${workspace}/graph/${graph}/node/${edge.airport}`">{{edge.airport}}</router-link>
</li>
</ul>
Expand All @@ -38,7 +38,7 @@
<div v-if="nextOutgoing" v-on:click="lastPage('outgoing')">last</div>
</div>
<ul>
<li v-for="edge, index in outgoing" :key="index">
<li v-for="(edge, index) in outgoing" :key="index">
<router-link :to="`/${workspace}/graph/${graph}/node/${edge.airport}`">{{edge.airport}}</router-link>
</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion multinet/multinet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 13 additions & 13 deletions multinet/multinet/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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 []
Expand Down Expand Up @@ -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

Expand All @@ -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:
Expand All @@ -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:
Expand Down
102 changes: 102 additions & 0 deletions multinet/multinet/multinet.gql
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 3 additions & 3 deletions multinet/multinet/resolvers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import logging
from girder import plugin, logprint
from types import *
from .types import *

from . import db

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down
111 changes: 7 additions & 104 deletions multinet/multinet/schema.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down