from django.contrib.auth.models import User
-from manifold.manifoldapi import ManifoldAPI
+from manifold.manifoldapi import ManifoldAPI, ManifoldResult
# Name my backend 'ManifoldBackend'
class ManifoldBackend:
auth = {'AuthMethod': 'password', 'Username': username, 'AuthString': password}
api = ManifoldAPI(auth)
# Authenticate user and get session key
- session = api.GetSession()
- if not session :
- return None
+ session_result = api.GetSession()
+ session = session_result.ok_value()
+ if not session:
+ print "GetSession failed",session_result.error()
+ return
+ print 'DEALING with session',session
#self.session = session
# Change GetSession() at some point to return expires as well
expires = time.time() + (24 * 60 * 60)
self.api = api
# Get account details
- person = api.GetPersons(auth)[0]
- self.person = person
+ persons_result = api.GetPersons(auth)
+ persons = persons_result.ok_value()
+ if not persons:
+ print "GetPersons failed",persons_result.error()
+ return
+ person = persons[0]
request.session['manifold'] = {'auth': api.auth, 'person': person, 'expires': expires}
except:
},
asynchroneous_success : function (data, query, id) {
+ if (manifold.asynchroneous_debug) console.log ("received manifold result with code " + data.code);
+ // xxx should have a nicer declaration of that enum in sync with the python code somehow
+ if (data.code == 1) {
+ alert("Your session has expired, please log in again");
+ window.location="/logout/";
+ return;
+ } elif (data.code != 0) {
+ alert("Error received from manifold backend at " + MANIFOLD_URL + " [" + data.output + "]");
+ return;
+ }
+ data=data.value;
if (data) {
if (!!id) {
/* Directly inform the requestor */
from myslice.config import Config
-debug=True
+from manifoldresult import ManifoldResult, ManifoldCode
-class SessionExpired (Exception):
- def __init__ (self,message):
- self.message=message
- def __repr__ (self):
- return "<SessionExpired: %s>"%self.message
+debug=False
+debug=True
class ManifoldAPI:
self.url = config.manifold_url
self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
+ def __repr__ (self): return "ManifoldAPI[%s]"%self.url
+
def __getattr__(self, methodName):
def func(*args, **kwds):
+ if (debug):
+ print "entering ManifoldAPI.%s"%methodName,
+ print "args",args,
+ print "kwds",kwds
try:
result=getattr(self.server, methodName)(self.auth, *args, **kwds)
if debug:
print '===> backend call',methodName, self.auth, self.url,'->',
- if not result: print "no/empty result"
+ if not result: print "[no/empty result]"
elif isinstance (result,str): print "result is '%s'"%result
elif isinstance (result,list): print "result is a %d-elts list"%len(result)
- else: print "dont know how to display result"
- return result
+ else: print "[dont know how to display result]"
+ return ManifoldResult (code=ManifoldCode.SUCCESS, value=result)
except xmlrpclib.Fault, error:
### xxx this is very rough for now
# until we have some agreement about how the API calls should return error conditions
# in some less unpolite way than this anoanymous exception, we assume it's a problem with the session
# that needs to be refreshed
+ if debug: print "Session Expired"
if error.faultCode == 8002:
reason="most likely your session has expired"
reason += " (the manifold API has no unambiguous error reporting mechanism yet)"
- raise SessionExpired(reason)
+ return ManifoldResult (code=ManifoldCode.SESSION_EXPIRED, output=reason)
except Exception,error:
print "ManifoldAPI: unexpected exception",error
- raise
+ return ManifoldResult (code=ManifoldResult.UNKNOWN_ERROR, output="%s"%error)
return func
def send_manifold_query (self, manifold_query):
(action,subject)= (manifold_query.action,manifold_query.subject)
if action=='get':
# use self.Get rather than self.server.Get so we catch exceptions as per __getattr__
- return self.Get(self.auth, subject, manifold_query.filters, {}, manifold_query.fields)
+ return self.Get(subject, manifold_query.filters, {}, manifold_query.fields)
# xxx...
else:
print "WARNING: ManifoldAPI.send_manifold_query: only 'get' implemented for now"
from django.http import HttpResponse, HttpResponseForbidden
from manifold.manifoldquery import ManifoldQuery
-from manifold.manifoldapi import ManifoldAPI, SessionExpired
+from manifold.manifoldapi import ManifoldAPI
debug=False
debug=True
# actually forward
manifold_api= ManifoldAPI(auth=manifold_api_session_auth)
if debug: print 'manifoldproxy.proxy: sending to backend', manifold_query
- # xxx we should embed the values inside a geni-like wrapper
- try:
- answer=manifold_api.send_manifold_query (manifold_query)
- if debug:
- try: print "received answer from backend with %d rows"%len(answer)
- except: print "received answer from backend - can't say len"
- except SessionExpired,error:
- answer=[ error.message ]
+ answer=manifold_api.send_manifold_query (manifold_query)
+ if debug: print 'manifoldproxy.proxy: received from backend with code', answer['code']
json_answer=json.dumps(answer)
if (debug):
with (file(offline_filename,"w")) as f:
--- /dev/null
+def enum(*sequential, **named):
+ enums = dict(zip(sequential, range(len(sequential))), **named)
+ return type('Enum', (), enums)
+
+ManifoldCode = enum (
+ SUCCESS=0,
+ SESSION_EXPIRED=1,
+ OTHERS=2,
+)
+
+# being a dict this can be used with json.dumps
+class ManifoldResult (dict):
+ def __init__ (self, code=ManifoldCode.SUCCESS, value=None, output=""):
+ self['code']=code
+ self['value']=value
+ self['output']=output
+
+ def from_json (self, json_string):
+ d=json.dumps(json_string)
+ for k in ['code','value','output']:
+ self[k]=d[k]
+
+ # this returns None if there's a problem, the value otherwise
+ def ok_value (self):
+ if self['code']==ManifoldCode.SUCCESS:
+ return self['value']
+
+ def error (self):
+ return "code=%s -- %s"%(self['code'],self['output'])
+
import json
+from manifold.manifoldresult import ManifoldResult
from manifold.manifoldapi import ManifoldAPI
+debug=False
+debug=True
+
# turn this on if you want to work offline
work_offline=False
#work_offline=True
'column.resource_type', 'column.value_type',
'column.allowed_values', 'column.platforms.platform',
'column.platforms.platform_url']
- results = manifold_api.Get('metadata:table', [], [], fields)
- self.hash_by_subject = dict ( [ (result['table'], result) for result in results ] )
+ rows_result = manifold_api.Get('metadata:table', [], [], fields)
+ rows = rows_result.ok_value()
+ if not rows:
+ print "Failed to retrieve metadata",rows_result.error()
+ self.hash_by_subject = dict ( [ (row['table'], row) for row in rows ] )
# save for next time we use offline mode
- with file(offline_filename,'w') as f:
- f.write(json.dumps(self.hash_by_subject))
+ if debug:
+ with file(offline_filename,'w') as f:
+ f.write(json.dumps(self.hash_by_subject))
def to_json(self):
return json.dumps(self.hash_by_subject)
--- /dev/null
+<?php
+
+
+class DataTables extends Plugin
+{
+
+ /* Knowing the uuid of a query, we could get the results with Plugins */
+ /* Same for async */
+ public function render_content()
+ //$plugin_uuid, $options)
+ {
+
+ //Plugins::add_js('/DataTables/jquery.dataTables.js');
+ Plugins::add_js('//ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.3/jquery.dataTables.js');
+ Plugins::add_js('/DataTables/DataTables.js');
+ //Plugins::add_css('/DataTables/DataTables.css');
+ //Plugins::add_css('/DataTables/demo_table.css');
+ Plugins::add_css('/DataTables/demo_table_jui.css');
+
+ $uuid = $this->uuid;
+
+ $results = Array();
+ $async = 1;
+
+
+ /* XXX required field in options : query_uuid */
+
+
+ $query = Plugins::get_query_by_uuid($this->params['query_uuid']);
+ $is_unique = Plugins::get_key_filter($query);
+ $method_keys = Plugins::get_default_fields($query->method, $is_unique);
+ //$method_keys = Plugins::query_get_default_keys($options['query_uuid']);
+ //$fields = Plugins::query_get_fields($options['query_uuid']);
+ //$all_headers = $_SESSION['metadata']['nodes']['columns'];
+ //$fields = $all_headers;
+
+ $fields = Plugins::metadata_get_fields($query->method);
+
+ /*
+ * @author: lbaron
+ * date: 2012-05-29
+ * debug columns QueryEditor to DataTables
+ *
+ */
+ // Problem: field names are differents between
+ // $_SESSION['metadata']['nodes']['columns']
+ // JSON values
+ //$fields[]="arch"; // architecture in Session metadata
+ //$fields[]="astype"; // as_type in Session metadata
+ $fields['platform'] = Array('column' => 'platform');
+ $fields['platform_longname'] = Array('column' => 'platform_longname');
+
+ //----------------------------------
+
+ $out = Array();
+ $out[] = "<table class='display' id='table-$uuid'>";
+ $out[] = "<thead><tr>";
+
+ foreach ($method_keys as $f) {
+ $out[] = "<th>$f</th>";
+ }
+
+ /* We put defaults fields (should be keys) at the beginning, and don't repeat them afterwards */
+ foreach ($fields as $key=>$f) {
+ if((array_search($f['column'], $method_keys)) === false)
+ $out[] = "<th>".$f['column']."</th>";
+ }
+
+ if (array_key_exists('checkboxes', $this->params) && ($this->params['checkboxes'])) {
+ $out[] = "<th>+/-</th>";
+ }
+ $out[] = "</tr></thead>";
+ $out[] = "<tbody>";
+
+ /* This might be done asynchronously */
+ if (!$async) {
+ $query = Plugins::get_query_by_uuid($this->params['query_uuid']);
+ foreach ($results as $r) {
+ $out[] = "<tr>";
+ foreach ($fields as $f) {
+ $out[] = "<td>";
+ $out[] = Plugins::render_element($query, $r[$f], $f); // XXX was query->method
+ $out[] = "</td>";
+ }
+ if (array_key_exists('checkboxes', $this->params) && ($this->params['checkboxes'])) {
+ $out[] = "<td>[X]</td>";
+ }
+ $out[] = "</tr>";
+ }
+ }
+
+
+ if ($async) {
+ /* setup datatables */
+ /* TODO:
+ * - fixed row for key columns
+ * - uniform row height
+ * - how to make some columns disappear
+ * - how to udpate some columns based on keys
+ */
+ }
+ $out[] = "</tbody>";
+ $out[] = "</table>";
+ return implode($out);
+ }
+}
+
+Plugins::register_plugin(
+ 'DataTables', /* plugin name */
+ 'DataTables', /* class name */
+ Array(
+ 'method' => '*',
+ 'fields' => Array()
+ )
+ /* XXX dependencies */
+);
--- /dev/null
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * General page setup
+ */
+#dt_example {
+ font: 80%/1.45em "Lucida Grande", Verdana, Arial, Helvetica, sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #333;
+ background-color: #fff;
+}
+
+
+#dt_example #container {
+ width: 800px;
+ margin: 30px auto;
+ padding: 0;
+}
+
+
+#dt_example #footer {
+ margin: 50px auto 0 auto;
+ padding: 0;
+}
+
+#dt_example #demo {
+ margin: 30px auto 0 auto;
+}
+
+#dt_example .demo_jui {
+ margin: 30px auto 0 auto;
+}
+
+#dt_example .big {
+ font-size: 1.3em;
+ font-weight: bold;
+ line-height: 1.6em;
+ color: #4E6CA3;
+}
+
+#dt_example .spacer {
+ height: 20px;
+ clear: both;
+}
+
+#dt_example .clear {
+ clear: both;
+}
+
+#dt_example pre {
+ padding: 15px;
+ background-color: #F5F5F5;
+ border: 1px solid #CCCCCC;
+}
+
+#dt_example h1 {
+ margin-top: 2em;
+ font-size: 1.3em;
+ font-weight: normal;
+ line-height: 1.6em;
+ color: #4E6CA3;
+ border-bottom: 1px solid #B0BED9;
+ clear: both;
+}
+
+#dt_example h2 {
+ font-size: 1.2em;
+ font-weight: normal;
+ line-height: 1.6em;
+ color: #4E6CA3;
+ clear: both;
+}
+
+#dt_example a {
+ color: #0063DC;
+ text-decoration: none;
+}
+
+#dt_example a:hover {
+ text-decoration: underline;
+}
+
+#dt_example ul {
+ color: #4E6CA3;
+}
+
+.css_right {
+ float: right;
+}
+
+.css_left {
+ float: left;
+}
\ No newline at end of file