Merge branch 'master' of git://git.onelab.eu/myslice
authorLoic Baron <loic.baron@lip6.fr>
Thu, 26 Sep 2013 10:10:16 +0000 (12:10 +0200)
committerLoic Baron <loic.baron@lip6.fr>
Thu, 26 Sep 2013 10:10:16 +0000 (12:10 +0200)
Conflicts:
portal/templates/registration_view.html

14 files changed:
manifold/manifoldapi.py
manifold/manifoldproxy.py
manifold/util/misc.py
manifold/util/predicate.py
manifold/util/type.py
myslice/config.py
plugins/myplugin/static/js/myplugin.js
plugins/query_editor/__init__.py
plugins/query_editor/static/js/query_editor.js
portal/registrationview.py
portal/slicerequestview.py
portal/sliceview.py
portal/templates/registration_view.html
unfold/static/js/unfold-helper.js

index 3f4bd10..47cf4c9 100644 (file)
@@ -70,6 +70,7 @@ class ManifoldAPI:
                                                               output="%s answered %s"%(self.url,error)))
                 # otherwise
                 print "** MANIFOLD API ERROR **"
+                print "====> ERROR On ManifoldAPI.%s"%methodName,"auth",self.auth,"args",args,"kwds",kwds
                 import traceback
                 traceback.print_exc()
                 if debug: print "KO (unexpected exception)",error
index a63e4a8..6eb67c3 100644 (file)
@@ -3,13 +3,14 @@ import os.path
 
 # this is for django objects only
 #from django.core import serializers
-from django.http import HttpResponse, HttpResponseForbidden
+from django.http                import HttpResponse, HttpResponseForbidden
 
 #from manifold.manifoldquery import ManifoldQuery
-from manifold.core.query import Query
+from manifold.core.query        import Query
 from manifold.core.result_value import ResultValue
-from manifold.manifoldapi import ManifoldAPI
-from manifold.manifoldresult import ManifoldException
+from manifold.manifoldapi       import ManifoldAPI
+from manifold.manifoldresult    import ManifoldException
+from manifold.util.log          import Log
 
 debug=False
 debug=True
@@ -88,7 +89,6 @@ with the query passed using POST"""
         # for the benefit of the python code, manifoldAPI raises an exception if something is wrong
         # however in this case we want to propagate the complete manifold result to the js world
 
-
         result = manifold_api.forward(manifold_query.to_dict())
 
         # XXX TEMP HACK
index 4494dcf..2ec3d02 100644 (file)
@@ -1,8 +1,5 @@
 import os, glob, inspect
-
-
-# Define the inclusion operator
-class contains(type): pass
+from types import StringTypes
 
 def find_local_modules(filepath):
     modules = []
@@ -11,3 +8,59 @@ def find_local_modules(filepath):
         if name != '__init__':
             modules.append(name)
     return modules 
+
+def make_list(elt):
+    if not elt or isinstance(elt, list):
+        return elt
+    if isinstance(elt, StringTypes):
+        return [elt]
+    if isinstance(elt, (tuple, set, frozenset)):
+        return list(elt)
+
+
+# FROM: https://gist.github.com/techtonik/2151727
+# Public Domain, i.e. feel free to copy/paste
+# Considered a hack in Python 2
+
+import inspect
+def caller_name(skip=2):
+    """Get a name of a caller in the format module.class.method
+    
+       `skip` specifies how many levels of stack to skip while getting caller
+       name. skip=1 means "who calls me", skip=2 "who calls my caller" etc.
+       
+       An empty string is returned if skipped levels exceed stack height
+    """
+    stack = inspect.stack()
+    start = 0 + skip
+    if len(stack) < start + 1:
+      return ''
+    parentframe = stack[start][0]    
+    
+    name = []
+    module = inspect.getmodule(parentframe)
+    # `modname` can be None when frame is executed directly in console
+    # TODO(techtonik): consider using __main__
+    if module:
+        name.append(module.__name__)
+    # detect classname
+    if 'self' in parentframe.f_locals:
+        # I don't know any way to detect call from the object method
+        # XXX: there seems to be no way to detect static method call - it will
+        #      be just a function call
+        name.append(parentframe.f_locals['self'].__class__.__name__)
+    codename = parentframe.f_code.co_name
+    if codename != '<module>':  # top level usually
+        name.append( codename ) # function or a method
+    del parentframe
+    return ".".join(name)
+
+def is_sublist(x, y, shortcut=None):
+    if not shortcut: shortcut = []
+    if x == []: return (True, shortcut)
+    if y == []: return (False, None)
+    if x[0] == y[0]:
+        return is_sublist(x[1:],y[1:], shortcut)
+    else:
+        return is_sublist(x, y[1:], shortcut + [y[0]])
index 3b5ba80..fb32e4d 100644 (file)
@@ -1,14 +1,27 @@
-from types import StringTypes
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Class Predicate: 
+# Define a condition to join for example to Table instances.
+# If this condition involves several fields, you may define a
+# single Predicate using tuple of fields. 
+#
+# Copyright (C) UPMC Paris Universitas
+# Authors:
+#   Jordan AugĂ©       <jordan.auge@lip6.fr>
+#   Marc-Olivier Buob <marc-olivier.buob@lip6.fr>
+
+from types                      import StringTypes
+from manifold.util.type         import returns, accepts 
 
 from operator import (
     and_, or_, inv, add, mul, sub, mod, truediv, lt, le, ne, gt, ge, eq, neg
-    )
+)
 
 # Define the inclusion operators
 class contains(type): pass
 class included(type): pass
 
-
 # New modifier: { contains 
 class Predicate:
 
@@ -40,13 +53,17 @@ class Predicate:
 
     def __init__(self, *args, **kwargs):
         """
-        \brief Build a predicate (left, operator, right)
-        \param You can pass:
-            - three args (left, operator, right)
-            - one argument (list or tuple) containing three elements (variable, operator, value)
-            "operator" is a String defined in operators or in operators_short and refers
-                tMao a binary operation.
-            "left" and "right" refers to a variable/constant involved in the Predicate.
+        Build a Predicate instance.
+        Args: 
+            kwargs: You can pass:
+                - 3 args (left, operator, right)
+                    left: The left operand (it may be a String instance or a tuple)
+                    operator: See Predicate.operators, this is the binary operator
+                        involved in this Predicate. 
+                    right: The right value (it may be a String instance
+                        or a literal (String, numerical value, tuple...))
+                - 1 argument (list or tuple), containing three arguments
+                  (variable, operator, value)
         """
         if len(args) == 3:
             key, op, value = args
@@ -55,9 +72,9 @@ class Predicate:
         elif len(args) == 1 and isinstance(args[0], Predicate):
             key, op, value = args[0].get_tuple()
         else:
-            raise Exception, "Bad initializer for Predicate (args=%r)" % args
+            raise Exception, "Bad initializer for Predicate (args = %r)" % args
 
-        assert not isinstance(value, (frozenset, dict, set)), "Invalid value type (the only valid containers are tuples and lists) (type = %r)" % type(value)
+        assert not isinstance(value, (frozenset, dict, set)), "Invalid value type (type = %r)" % type(value)
         if isinstance(value, list):
             value = tuple(value)
 
@@ -76,28 +93,58 @@ class Predicate:
         else:
             self.value = value
 
+    @returns(StringTypes)
     def __str__(self):
+        """
+        Returns:
+            The '%s' representation of this Predicate.
+        """
         key, op, value = self.get_str_tuple()
         if isinstance(value, (tuple, list, set, frozenset)):
             value = [repr(v) for v in value]
             value = "[%s]" % ", ".join(value)
         return "%s %s %r" % (key, op, value) 
 
+    @returns(StringTypes)
     def __repr__(self):
+        """
+        Returns:
+            The '%r' representation of this Predicate.
+        """
         return "Predicate<%s %s %r>" % self.get_str_tuple()
 
     def __hash__(self):
+        """
+        Returns:
+            The hash of this Predicate (this allows to define set of
+            Predicate instances).
+        """
         return hash(self.get_tuple())
 
+    @returns(bool)
     def __eq__(self, predicate):
+        """
+        Returns:
+            True iif self == predicate.
+        """
         if not predicate:
             return False
         return self.get_tuple() == predicate.get_tuple()
 
     def get_key(self):
+        """
+        Returns:
+            The left operand of this Predicate. It may be a String
+            or a tuple of Strings.
+        """
         return self.key
     
     def set_key(self, key):
+        """
+        Set the left operand of this Predicate.
+        Params:
+            key: The new left operand.
+        """
         self.key = key
 
     def get_op(self):
@@ -112,7 +159,6 @@ class Predicate:
     def get_tuple(self):
         return (self.key, self.op, self.value)
 
-
     def get_str_op(self):
         op_str = [s for s, op in self.operators.iteritems() if op == self.op]
         return op_str[0]
index 5d7ab1e..1cc03b2 100644 (file)
@@ -60,9 +60,10 @@ def accepts(*types, **kw):
         debug = kw['debug']
     try:
         def decorator(f):
-            def newf(*args):
+            # XXX Missing full support of kwargs
+            def newf(*args, **kwargs):
                 if debug is 0:
-                    return f(*args)
+                    return f(*args, **kwargs)
                 assert len(args) == len(types)
                 argtypes = tuple(map(type, args))
                 if not compare_types(types, argtypes):
@@ -72,7 +73,7 @@ def accepts(*types, **kw):
                         print >> sys.stderr, 'TypeWarning: ', msg
                     elif debug is 2:
                         raise TypeError, msg
-                return f(*args)
+                return f(*args, **kwargs)
             newf.__name__ = f.__name__
             return newf
         return decorator
@@ -91,7 +92,7 @@ def compare_types(expected, actual):
         else:
             return actual == type(None) or actual in expected
     else:
-        return actual == type(None) or actual == expected or issubclass(actual, expected)
+        return actual == type(None) or actual == expected or isinstance(actual, expected) # issubclass(actual, expected)
 
 def returns(ret_type, **kw):
     '''Function decorator. Checks decorated function's return value
index c0e171b..d839462 100644 (file)
@@ -11,7 +11,9 @@ class Config:
 #    manifold_url = "http://manifold.pl.sophia.inria.fr:7080/"
 # the OpenLab-wide backend as managed by UPMC
 #   manifold_url = "http://dev.myslice.info:7080/" # development version
-    manifold_url = "http://test.myslice.info:7080/" #stable version
+#   manifold_url = "http://test.myslice.info:7080/" #stable version
+    manifold_url = "http://localhost:7080/" #stable version
+    
     # exporting these details to js
     @staticmethod
     def manifold_js_export ():
index da65c43..20f8573 100644 (file)
@@ -86,8 +86,7 @@
         // ... be sure to list all events here
 
         /* RECORD HANDLERS */
-        
-        on_record_received: function(record)
+        on_all_new_record: function(record)
         {
             //
         },
index 1626150..53adeae 100644 (file)
@@ -17,7 +17,7 @@ class QueryEditor(Plugin):
             ] ,
             'css_files': [
                 'css/query_editor.css',
-#                'css/jquery-ui.css',
+                'css/jquery-ui.css',
 #                'css/demo_page.css',
 #                'css/demo_table.css',
             ]
index 1e15a01..553dbc6 100644 (file)
         event_filter_added: function(op, suffix) {
             suffix = (typeof suffix === 'undefined') ? '' : manifold.separator + suffix;
             var self = this;
-            return function(e) {
+            return function(e, ui) {
                 var array = self.array_from_id(e.target.id);
                 var key   = self.field_from_id(array); // No need to remove suffix...
-                var value = e.target.value;
+
+                // using autocomplete ui
+                if(typeof(ui) != "undefined"){
+                    var value = ui.item.value;
+                }else{
+                    var value = e.target.value;
+                }
 
                 if (value) {
                     // XXX This should be handled by manifold
@@ -34,7 +40,7 @@
 
         init: function(options, element) {
             this._super(options, element);
-
+            console.log("init Query_Editor");
             this.listen_query(options.query_uuid);
 
             this.elts('queryeditor-auto-filter').change(this.event_filter_added('='));
@@ -82,7 +88,6 @@
                 ]
             });
 
-            var self = this;
             // Actions on the newly added fields
             this.elmt('table tbody td span').on('click', function() {
                 var nTr = this.parentNode.parentNode;
                 'padding-top'   : '0em',
                 'padding-bottom': '0em'
             });
+            
+            // autocomplete list of tags
+            this.availableTags = {};
 
         }, // init
 
 
         on_field_added: function(field)
         {
+            console.log("on_field_added : "+field);
             this.check_field(field);
         },
 
             this.uncheck_field(field);
         },
 
+        /* RECORD HANDLERS */
+        on_query_done: function()
+        {
+            //console.log("Query_Editor: query_done!");
+            //console.log(this.availableTags);
+        },
+        on_new_record: function(record)
+        {
+            //console.log("Query_Editor: new_record!");
+            //console.log(record);
+            availableTags = this.availableTags;           
+            jQuery.each(record,function(key,value){
+                value = get_value(value);
+                if(!availableTags.hasOwnProperty(key)){availableTags[key]=new Array();}
+                //availableTags[key].push(value);
+                var currentArray = availableTags[key];
+                if(value!=null){
+                    if(jQuery.inArray(value,currentArray)==-1){availableTags[key].push(value);}
+                }
+           });
+           this.availableTags = availableTags;
+           this.update_autocomplete(availableTags);
+        },
+
         /* Former code not used at the moment */
 
         print_field_description: function(field_header, div_id) 
             return output;
         },
 
+        update_autocomplete: function(availableTags)
+        {
+            var self = this;
+            var domid = this.options.plugin_uuid;
+            
+            jQuery.each(availableTags, function(key, value){
+                value.sort();
+                jQuery("#"+domid+"__field__"+key).autocomplete({
+                            source: value,
+                            selectFirst: true,
+                            minLength: 0, // allows to browse items with no value typed in
+                            select: self.event_filter_added('=')
+                });
+            });                
+        }, // update_autocomplete     
+
+/*
         update_autocomplete: function(e, rows, current_query)
         {
             var d = data;
                 });
             });                
         }, // update_autocomplete     
-
+*/
         fnFormatDetails: function( metaTable, nTr, div_id ) 
         {
             var aData = metaTable.fnGetData( nTr );
index f18726e..9867c36 100644 (file)
@@ -28,9 +28,10 @@ class RegistrationView (View):
 
     errors = []
 
-    authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
-    #authorities_query = Query.get('authority').select('authority_hrn')
+    #authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
+    authorities_query = Query.get('authority').select('authority_hrn')
     authorities = execute_query(request, authorities_query)
+    authorities = sorted(authorities)
 
     if request.method == 'POST':
         # We shall use a form here
index f92214e..6589e8a 100644 (file)
@@ -14,9 +14,10 @@ from myslice.viewutils           import topmenu_items, the_user
 class SliceRequestView (LoginRequiredAutoLogoutView):
 
     def authority_hrn_initial (self, request):
-        authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
-#        authorities_query = Query.get('authority').select('authority_hrn')
+#        authorities_query = Query.get('authority').filter_by('authority_hrn', 'included', ['ple.inria', 'ple.upmc']).select('name', 'authority_hrn')
+        authorities_query = Query.get('authority').select('authority_hrn')
         authorities = execute_query(request, authorities_query)
+        authorities = sorted(authorities)
         
         authority_hrn_tuples = [ (authority['authority_hrn'], authority['name'],) for authority in authorities ]
         return {'authority_hrn': authority_hrn_tuples}
index b265e79..97802f6 100644 (file)
@@ -24,7 +24,8 @@ from plugins.messages                import Messages
 tmp_default_slice='ple.upmc.myslicedemo'
 
 # temporary : turn off the users part to speed things up
-do_query_users=True
+#do_query_users=True
+do_query_users=False
 
 class SliceView (LoginRequiredAutoLogoutView):
 
@@ -32,6 +33,7 @@ class SliceView (LoginRequiredAutoLogoutView):
     
         page = Page(request)
         page.add_css_files ('css/slice-view.css')
+        page.add_js_files  ( [ "js/common.functions.js" ] )
         page.add_js_chunks ('$(function() { console.log("sliceview: jQuery version " + $.fn.jquery); });')
         page.add_js_chunks ('$(function() { console.log("sliceview: users turned %s"); });'%("on" if do_query_users else "off"))
         page.expose_js_metadata()
@@ -143,7 +145,7 @@ class SliceView (LoginRequiredAutoLogoutView):
 
         resources_query_editor = QueryEditor(
             page  = page,
-            query = sq_resource,
+            query = query_resource_all,
             title = "Select Columns",
             )
         resources_active_filters = ActiveFilters(
index 18759f4..71ef1b8 100644 (file)
@@ -24,7 +24,7 @@
 {% endif %}
    
 <div class="well">
 <form class="cmxform form-horizontal" id="registrationForm" method="post" action="" enctype="multipart/form-data" role="form">
+ <form class="cmxform form-horizontal" id="registrationForm" method="post" action="" enctype="multipart/form-data" role="form">
     <fieldset>
     {% csrf_token %}
     <div class="form-group">
@@ -47,7 +47,8 @@
        <select id="auth_list" name="authority_hrn" size="1" class="form-control" required>
          {% if authorities %}
          {% for authority in authorities %}
-         <option value="{{ authority.authority_hrn }}">{{authority.name}} ({{authority.authority_hrn}})</option>
+      <option value="{{ authority.authority_hrn }}"/>{{authority.authority_hrn}}</option>
+         <!-- <option value="{{ authority.authority_hrn }}">{{authority.name}} ({{authority.authority_hrn}})</option> -->
          {% endfor %}
          {% else %} <!-- should not happen -->
          <option value="test">No authority found !!! </option>
     </div>
   </fieldset>
   </form>  
+>>>>>>> abb43f86edd5a2888cb96ca92a58350db9e32fcf
 </div>
 
 {% endblock %}
index 8d75cc3..67524a1 100644 (file)
@@ -34,7 +34,11 @@ var unfold = {
     },
 
     escape_id: function(id) {
-        return id.replace( /(:|\.|\[|\])/g, "\\$1" );
+        if(typeof id != 'undefined'){
+            return id.replace( /(:|\.|\[|\])/g, "\\$1" );
+        }else{
+            return "fake-id";
+        }
     }
 
 } // global unfold