On Thu, Apr 23, 2015 at 12:52 PM, Ronan Dunklau <ronan.dunk...@dalibo.com> wrote:
> Le jeudi 23 avril 2015 10:53:48 Ashesh Vashi a écrit : > > > Hi Dave/Ronan, > > > > > > On Mon, Apr 20, 2015 at 4:10 PM, Dave Page <dp...@pgadmin.org> wrote: > > > > On Mon, Apr 20, 2015 at 10:52 AM, Ronan Dunklau > > > > > > > > <ronan.dunk...@dalibo.com> wrote: > > > > >> Ronan; can you update the test, help and about modules as well > please? > > > > > > > > > > Done, please find attached a new patch for that. Ashesh, once you're > > > > > > > > done with > > > > > > > > > what you are doing now, feel free to ask me for any help needed to > > > > > > > > integrate > > > > > > > > > this after the fact. > > > > > > > > Thanks. > > > > > > Thanks - It looks good to me. > > > (And, attached patch is based on that.) > > > > > > Maybe I'm missing something, but it seems like a "generate_browser_node" > function is missing: > > > > File > "/home/ro/projets/pgadmin4/web/pgadmin/browser/server_groups/__init__.py", > line 21, in <module> > > from pgadmin.browser.utils import generate_browser_node > > ImportError: cannot import name generate_browser_node > > > > > > It also brought to my attention that I should have removed the only > function (register_modules) from pgadmin.browser.utils. > Yeah - it is missing. Please find a separate patch for the utils. Actually - you removed the web/pgadmin/browser/utils.py, hence - when I made the patch on top of yours, git detected the file as new file, and did not include the diff for it. The attached patch is only for utils file. -- Thanks & Regards, Ashesh Vashi EnterpriseDB INDIA: Enterprise PostgreSQL Company <http://www.enterprisedb.com> *http://www.linkedin.com/in/asheshvashi* <http://www.linkedin.com/in/asheshvashi> > > Thank you for integrating my work into your patch ! > > > -- > > Ronan Dunklau > > http://dalibo.com - http://dalibo.org >
diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py new file mode 100644 index 0000000..ec9858a --- /dev/null +++ b/web/pgadmin/browser/utils.py @@ -0,0 +1,181 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2015, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +"""Browser helper utilities""" + +from flask import request +from flask.views import View, MethodViewType, with_metaclass + + +def generate_browser_node(node_id, label, icon, inode, node_type): + return { + "id": "%s/%s" % (node_type, node_id), + "label": label, + "icon": icon, + "inode": inode, + "_type": node_type, + "refid": node_id + } + + +class NodeView(with_metaclass(MethodViewType, View)): + """ + A PostgreSQL Object has so many operaions/functions apart from CRUD + (Create, Read, Update, Delete): + i.e. + - Reversed Engineered SQL + - Modified Query for parameter while editing object attributes + i.e. ALTER TABLE ... + - Statistics of the objects + - List of dependents + - List of dependencies + - Listing of the children object types for the certain node + It will used by the browser tree to get the children nodes + + This class can be inherited to achieve the diffrent routes for each of the + object types/collections. + + OPERATION | URL | Method + ---------------+------------------------+-------- + List | /obj/[Parent URL]/ | GET + Properties | /obj/[Parent URL]/id | GET + Create | /obj/[Parent URL]/ | POST + Delete | /obj/[Parent URL]/id | DELETE + Update | /obj/[Parent URL]/id | PUT + + SQL (Reversed | /sql/[Parent URL]/id | GET + Engineering) | + SQL (Modified | /sql/[Parent URL]/id | POST + Properties) | + + Statistics | /stats/[Parent URL]/id | GET + Dependencies | /deps/[Parent URL]/id | GET + Dependents | /deps/[Parent URL]/id | POST + + Children Nodes | /nodes/[Parent URL]/id | GET + + NOTE: + Parent URL can be seen as the path to identify the particular node. + + i.e. + In order to identify the TABLE object, we need server -> database -> schema + information. + """ + operations = { + 'obj': [ + {'get': 'properties', 'delete': 'delete', 'put': 'update'}, + {'get': 'list', 'post': 'create'} + ], + 'nodes': [{'get': 'nodes'}, {}], + 'sql': [{'get': 'sql', 'post': 'modified_sql'}, {}], + 'stats': [{'get': 'statistics'}, {}], + 'deps': [{'get': 'dependencies', 'post': 'dependents'}, {}] + } + + + @classmethod + def generate_ops(cls): + cmds = [] + for op in cls.operations: + idx=0 + for ops in cls.operations[op]: + meths = [] + for meth in ops: + meths.append(meth.upper()) + if len(meths) > 0: + cmds.append({'cmd': op, 'req':idx==0, 'methods': meths}) + idx+=1 + + return cmds + + + # Inherited class needs to modify these parameters + node_type = None + # This must be an array object with attributes (type and id) + parent_ids = [] + # This must be an array object with attributes (type and id) + ids = [] + + + @classmethod + def get_node_urls(cls): + assert cls.node_type is not None, "Please set the node_type for this class (%r)" % cls + common_url = '/' + for p in cls.parent_ids: + common_url += '<' + p['type'] + ":" + p['id'] + '>/' + + id_url = common_url + idx = 0 + for p in cls.ids: + id_url += '/<' if idx == 1 else '<' + p['type'] + ":" + p['id'] + '>' + idx += 1 + + return id_url, common_url + + + def __init__(self, cmd): + self.cmd = cmd; + + + # Check the existance of all the required arguments from parent_ids + # and return combination of has parent arguments, and has id arguments + def check_args(self, *args, **kwargs): + has_id = has_args = True + for p in self.parent_ids: + if p['id'] not in kwargs: + has_args = False + break + + for p in self.ids: + if p['id'] not in kwargs: + has_id = False + break + + return has_args, has_id and has_args + + + def dispatch_request(self, *args, **kwargs): + meth = request.method.lower() + if meth == 'head': + meth = 'get' + + assert self.cmd in NodeView.operations, \ + "Unimplemented Command (%s) for Node View" % self.cmd + has_args, has_id = self.check_args(*args, **kwargs) + + assert (has_id and meth in NodeView.operations[self.cmd][0]) \ + or (not has_id and meth in NodeView.operations[self.cmd][1]), \ + "Unimplemented method (%s) for command (%s), which %s an id" \ + % (meth, self.cmd, 'requires' if has_id else 'does not require') + + meth = NodeView.operations[self.cmd][0][meth] if has_id else \ + NodeView.operations[self.cmd][1][meth] + + method = getattr(self, meth, None) + + assert method is not None, \ + "Unimplemented method (%s) for this url (%u)" % \ + (meth, request.path) + + return method(*args, **kwargs) + + + @classmethod + def register_node_view(cls, blueprint): + id_url, url = cls.get_node_urls() + + commands = cls.generate_ops() + + for c in commands: + blueprint.add_url_rule( + '/%s%s' % (c['cmd'], id_url if c['req'] else url), + view_func=cls.as_view( + '%s%s' % (c['cmd'], '_id' if c['req'] else ''), + cmd=c['cmd']), + methods=c['methods'])
-- Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers