Commits

Anonymous committed 5418b3d

Committing version 1.2.3. Please read CHANGES and README files for details

Comments (0)

Files changed (7)

trac-dev/gviz/__init__.py

     from proto import GViz_0_5
     from stdfmt import GVizJsonEncoder, GVizHtmlEncoder, GVizCSVEncoder
     from ticket import *
+    from wiki import *
     from ig import *
-    from wiki import *
     msg = 'Ok'
 except Exception, exc:
+#    raise
     msg = "IG: Exception %s raised: '%s'" % (exc.__class__.__name__, str(exc))

trac-dev/gviz/api.py

     """
     message = ''
 
+class ITracLinksHandler(Interface):
+    """Interface implemented by those classes being
+    TracLinks providers registered under the namespaces managed by
+    this plugin.
+    """
+    def get_link_resolvers(self):
+        """Return an iterable over (namespace, formatter) tuples.
+        Namespaces value must be tuples.
+        
+        Each formatter should be a function of the form
+        fmt(formatter, ns, target, label), and should
+        return some HTML fragment.
+        The `label` is already HTML escaped, whereas the `target` is not.
+        """
+
 
 # TODO : Implement the different data source providers
 

trac-dev/gviz/ig/api.py

         @return a sequence containing all the available border ids
         """
 
-class IGadgetTracLinksResolver(Interface):
-    """Interface implemented by those classes being
-    TracLinks providers registered under the `gadget` namespace.
-    """
-    def get_link_resolvers(self):
-        """Return an iterable over (namespace, formatter) tuples.
-        Namespaces value must be tuples.
-        
-        Each formatter should be a function of the form
-        fmt(formatter, ns, target, label), and should
-        return some HTML fragment.
-        The `label` is already HTML escaped, whereas the `target` is not.
-        """
-
 class GadgetBordersManager(Component):
     """Component responsible for managing gadget borders.
     """

trac-dev/gviz/ig/web_ui.py

 from os import makedirs
 
 from api import IGadgetBorderImgStore, BORDER_IMAGES, \
-        IGadgetBorderProvider, IGadgetTracLinksResolver
+        IGadgetBorderProvider
+from tracgviz.api import ITracLinksHandler
+
 try:
     from tracgviz.util import send_response, send_std_error_response
 except ImportError:
-    # Installability issue :(
+    # Installation issue :(
     from util import send_response, send_std_error_response
 
 class GadgetsBorderModule(Component):
     """
     implements(# IPermissionRequestor, \
             IRequestHandler, ITemplateProvider, IGadgetBorderProvider, \
-            IGadgetTracLinksResolver)
+            ITracLinksHandler)
     stores = ExtensionPoint(IGadgetBorderImgStore)
     
     store_name = Option('gadgets', 'border_img_store', \
         """
         return self.store.enum_img_borders()
 
-    # IGadgetTracLinksResolver methods
+    # ITracLinksHandler methods
     def _format_link(self, formatter, ns, border_id, label):
-        title = border_id + " (gadget border)"
+        title = border_id + " (Gadget border)"
         if not label:
             label = title
         url = self.get_border_spec(border_id)
         return some HTML fragment.
         The `label` is already HTML escaped, whereas the `target` is not.
         """
-        yield (('border', 'image'), self._format_link)
+        yield (('gadget', 'border', 'image'), self._format_link)

trac-dev/gviz/ig/wiki.py

 with other component elements.
 """
 
-__all__ = ('GadgetLinksDispatcher', 'iGoogleGadgetMacro')
+__all__ = 'LinksTreeDispatcher', 'iGoogleGadgetMacro'
 
 from trac.core import Interface, Component, ExtensionPoint, \
         implements, TracError
 from urlparse import urlunparse
 from urllib import urlencode
 
-from api import IGadgetTracLinksResolver
+from tracgviz.api import ITracLinksHandler
 
 __metaclass__ = type
 
-class GadgetLinksDispatcher(Component):
+class LinksTreeDispatcher(Component):
     """A class used to dispatch TracLinks resolution requests to the 
     providers registered under the `gadget` namespace.
     """
     implements(IWikiSyntaxProvider)
-    resolvers = ExtensionPoint(IGadgetTracLinksResolver)
+    resolvers = ExtensionPoint(ITracLinksHandler)
     
     # IWikiSyntaxProvider methods
     def get_wiki_syntax(self):
     
     def _format_link(self, formatter, ns, target, label):
         parts = tuple(target.split(':'))
-        for ns, f in (lr for x in self.resolvers \
-                        for lr in x.get_link_resolvers()):
-            
-            if all(x == y for x, y in zip(parts, ns)) and \
-                    len(parts) >= len(ns):
-                target = ':'.join(parts[len(ns):])
+        self.log.debug('IG: Processing TracLinks expression %s', target)
+        for _ns, f in ([_ns, f] for x in self.resolvers \
+                        for _ns, f in x.get_link_resolvers() \
+                        if ns == _ns[0]):
+            self.log.debug('IG: Matching namespace %s', _ns)
+            _ns = _ns[1:]
+            if all(x == y for x, y in zip(parts, _ns)) and \
+                    len(parts) >= len(_ns):
+                target = ':'.join(parts[len(_ns):])
                 break;
         else:
             return tag.a(label, class_='missing attachment', rel='nofollow')
-        return f(formatter, ns, target, label)
+        return f(formatter, _ns, target, label)
         
     def get_link_resolvers(self):
         """Return an iterable over (namespace, formatter) tuples.
         The `label` is already HTML escaped, whereas the `target` is not.
         """
         yield ('gadget', self._format_link)
+        yield ('gviz', self._format_link)
 
 class TracLinksFormatter(Formatter):
     """A wiki formatter which pays attention to nothing but trac 

trac-dev/gviz/setup.py

+#!/usr/bin/env python
+
+# Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+try:
+    from setuptools import setup
+except ImportError:
+    from distutils.core import setup
+
+from __init__ import __doc__ as DESC
+
+versions = [
+    (1, 0, 0),
+    (1, 1, 0),
+    (1, 2, 0),
+    (1, 2, 1),
+    (1, 2, 2),
+    (1, 2, 3),
+    ]
+    
+latest = '.'.join(str(x) for x in versions[-1])
+
+status = {
+            'planning' :  "Development Status :: 1 - Planning",
+            'pre-alpha' : "Development Status :: 2 - Pre-Alpha",
+            'alpha' :     "Development Status :: 3 - Alpha",
+            'beta' :      "Development Status :: 4 - Beta",
+            'stable' :    "Development Status :: 5 - Production/Stable",
+            'mature' :    "Development Status :: 6 - Mature",
+            'inactive' :  "Development Status :: 7 - Inactive"
+         }
+dev_status = status["alpha"]
+
+cats = [
+    dev_status,
+    "Environment :: Plugins",
+    "Environment :: Web Environment",
+    "Framework :: Trac",
+    "Intended Audience :: Developers",
+    "Intended Audience :: Information Technology",
+    "Intended Audience :: Other Audience",
+    "Intended Audience :: System Administrators",
+    "License :: OSI Approved :: Apache Software License",
+    "Natural Language :: English",
+    "Natural Language :: Spanish",
+    "Operating System :: OS Independent",
+    "Programming Language :: Python :: 2.5",
+    "Programming Language :: Python",
+    "Topic :: Database",
+    "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries",
+    "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
+    "Topic :: Internet :: WWW/HTTP :: WSGI",
+    "Topic :: Software Development :: Bug Tracking",
+    "Topic :: Software Development :: Libraries :: Application Frameworks",
+    "Topic :: Software Development :: Libraries :: Python Modules",
+    "Topic :: Software Development :: User Interfaces",
+    "Topic :: Software Development :: Widget Sets"
+    ]
+
+# Be compatible with older versions of Python
+from sys import version
+if version < '2.2.3':
+    from distutils.dist import DistributionMetadata
+    DistributionMetadata.classifiers = None
+    DistributionMetadata.download_url = None
+
+# Add the change log to the package description.
+chglog = None
+try:
+    from os.path import dirname, join
+    chglog = open(join(dirname(__file__), "CHANGES"))
+    DESC+= ('\n\n' + chglog.read())
+finally:
+    if chglog:
+        chglog.close()
+
+PKG = ['tracgviz', 'tracgviz.ig']
+
+ENTRY_POINTS = """
+               [trac.plugins]
+               tracgviz = tracgviz
+               """
+
+setup(
+	name='TracGViz',
+	version=latest,
+	description=DESC.split('\n', 1)[0],
+	author='Olemis Lang',
+	author_email='olemis@gmail.com',
+	maintainer='Olemis Lang',
+	maintainer_email='olemis@gmail.com',
+	url='https://opensvn.csie.org/traccgi/swlcu/wiki/En/Devel/TracGViz',
+	download_url='https://sourceforge.net/project/downloading.php?group_id=256921&filename=TracGViz-1.2.2.tar.gz',
+	requires = ['trac', 'tracrpc', 'gviz_api'],
+	package_dir = {
+	        'tracgviz' : '.',
+	        'tracgviz.ig' : './ig'
+	        },
+	packages= PKG,
+	package_data={
+		'tracgviz': ['templates/*', 'htdocs/*', 
+		    'messages/es/LC_MESSAGES/*', 'CHANGES', 'COPYRIGHT', 
+                    'NOTICE', 'README', 'TODO'],
+		'tracgviz.ig': ['templates/*', 'htdocs/*']
+		},
+	provides = ['tracgviz (%s)' % (latest,), 
+	            'tracgviz.ig (%s)' % (latest,)],
+	obsoletes = ['tracgviz (>=%s.0.0, <%s)' % \
+	                                    (versions[-1][0], latest),
+                'tracgviz.ig (>=%s.0.0, <%s)' % \
+	                                    (versions[-1][0], latest),],
+	entry_points = ENTRY_POINTS,
+	classifiers = cats,
+	long_description= DESC
+	)

trac-dev/gviz/wiki.py

 Licensed under the Apache License, Version 2.0 
 """
 
-__all__ = ('GVizDataSource',)
+__all__ = 'GVizProviderListMacro', 'GoogleDocsConnector', \
+            'GoogleVizGadgets', 'GoogleAppsConnector'
 
 from trac.core import Interface, Component, ExtensionPoint, \
         implements, TracError
 from trac.mimeview.api import Context
 from trac.util import get_pkginfo
 from trac.web.api import IRequestHandler, RequestDone
+from trac.web.href import Href
 from pkg_resources import resource_string, resource_filename
 from trac.env import IEnvironmentSetupParticipant
 from trac.perm import IPermissionRequestor
 from itertools import chain
 from urlparse import urlunparse
 from urllib import urlencode
+from cgi import parse_qs
+from re import compile
 
-from api import TracGVizSystem, gviz_api
+from api import TracGVizSystem, gviz_api, ITracLinksHandler
 
 __metaclass__ = type
     
                          (self._provider_doc(p) for p in providers), \
                          '')
             return Markup(doc)
+
+#-------------------------------------
+#   WikiFormatting & Google services
+#-------------------------------------
+
+class GoogleDocsConnector(Component):
+    """Provide shortcuts to the features found in Google Spreadsheets 
+    being related to Google Visualization API.
+    
+    Syntax -> 
+    gviz:google:sheet:<sheet_id>[:<top_cell>-<bottom_cell>][?headers=<number>]
+    
+    Example(s) ->
+    - gviz:google:sheet:12345:B12-U37?headers=1
+      http://spreadsheets.google.com/tq?headers=1&range=B12%3AU37&key=12345
+    """
+    implements(ITracLinksHandler)
+    
+    # ITracLinksHandler methods
+    def _format_link(self, formatter, ns, sheet_info, label):
+        path, query, fragment = formatter.split_link(sheet_info)
+        try:
+            id, range = path.rsplit(':', 1)
+            start, end = range.split('-')
+            range = start + ':' + end
+        except ValueError:
+            id = path
+            range = None
+        self.log.debug('IG: Spreadsheet parameters %s', query)
+        try:
+            query = query[1:]
+        except ValueError:
+            pass
+        else:
+            headers = parse_qs(query).get('headers')
+        
+        title = "Google spreadsheet # %s" % (id,)
+        if range is not None:
+            title+= " (in range %s)" % (start + '-' + end,)
+        if not label:
+            label = title
+        url = Href('http://spreadsheets.google.com/tq')
+        url = url(key=id, range=range, headers=headers)
+        return tag.a(label, class_='wiki', href= url, title=title)
+    
+    def get_link_resolvers(self):
+        """Return an iterable over (namespace, formatter) tuples.
+
+        Each formatter should be a function of the form
+        fmt(formatter, ns, target, label), and should
+        return some HTML fragment.
+        The `label` is already HTML escaped, whereas the `target` is not.
+        """
+        yield (('gviz', 'google', 'sheet'), self._format_link)
+
+class GoogleVizGadgets(Component):
+    """Provide shortcuts based on WikiFormatting so as to specify 
+    URLs for (standard) Google Visualization Gadgets.
+    
+    Syntax -> 
+    gadget:google:modules:<chart_name>
+    
+    Example(s) ->
+    - gadget:google:modules:line-chart
+      http://www.google.com/ig/modules/line-chart.xml
+    """
+    implements(ITracLinksHandler)
+    
+    # ITracLinksHandler methods
+    def _format_link(self, formatter, ns, viz_name, label):
+        title = "Google's Official Visualization: %s" % (viz_name,)
+        url = 'http://www.google.com/ig/modules/%s.xml' % (viz_name,)
+        return tag.a(label, class_='wiki', href= url, title=title)
+    
+    def get_link_resolvers(self):
+        """Return an iterable over (namespace, formatter) tuples.
+
+        Each formatter should be a function of the form
+        fmt(formatter, ns, target, label), and should
+        return some HTML fragment.
+        The `label` is already HTML escaped, whereas the `target` is not.
+        """
+        yield (('gadget', 'google', 'modules'), self._format_link)
+
+class GoogleAppsConnector(Component):
+    """Provide shortcuts to the visualization URL for specific 
+    data sources defined for your domain and made available via Google 
+    Apps Visualization API.
+    
+    Syntax -> 
+    gviz:google:apps:<report_key>@<report_date>:<domain>[?tq=<query>]
+    
+    Example(s) ->
+    - gviz:google:apps:asdfa014mm129anpsmdasdas123@2008-08-31:example.com?tq=select rdate,count_7_day_actives where count_7_day_actives > 100
+      https://www.google.com/a/cpanel/example.com/ReportGviz?reportKey=asdfa014mm129anpsmdasdas123&reportDate=2008-08-31&tq=
+    """
+    implements(ITracLinksHandler)
+    
+    PATH_LINK_RE = compile(r"([^@:]+)"     # report id
+                              r"@(\d\d\d\d-\d\d-\d\d)" # report date
+                              r":(.+)$" # domain
+                              )
+    
+    # ITracLinksHandler methods
+    def _format_link(self, formatter, ns, report_info, label):
+        path, query, fragment = formatter.split_link(report_info)
+        match = self.PATH_LINK_RE.match(path)
+        if match:
+            report, date, domain = match.groups()
+        else:
+            raise TracError("Invalid syntax or missing fields in %s ." \
+                            "Syntax -> gviz:google:apps:<report_key>" \
+                            "@<report_date>:<domain>[?tq=<query>]" % \
+                                (report_info,))
+        try:
+            query = query[1:]
+        except ValueError:
+            pass
+        else:
+            query = parse_qs(query).get('tq')
+        
+        title = "Google Apps Report # %s at %s for domain %s" % \
+                    (report, date, domain)
+        if query is not None:
+            title+= " (with query)"
+        if not label:
+            label = title
+        url = Href('https://www.google.com/a/cpanel/')
+        url = url(domain, 'ReportGviz', reportKey=report, 
+                    reportDate=date, tq=query)
+        return tag.a(label, class_='wiki', href= url, title=title)
+    
+    def get_link_resolvers(self):
+        """Return an iterable over (namespace, formatter) tuples.
+
+        Each formatter should be a function of the form
+        fmt(formatter, ns, target, label), and should
+        return some HTML fragment.
+        The `label` is already HTML escaped, whereas the `target` is not.
+        """
+        yield (('gviz', 'google', 'apps'), self._format_link)
+