source: peerreviewplugin/tags/0.12/3.1/codereview/tracgenericclass/util.py

Last change on this file was 16451, checked in by Ryan J Ollos, 6 years ago

Fix indentation

File size: 11.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2010-2015 Roberto Longobardi
4#
5# This file is part of the Test Manager plugin for Trac.
6#
7# This software is licensed as described in the file COPYING, which
8# you should have received as part of this distribution. The terms
9# are also available at:
10#   https://trac-hacks.org/wiki/TestManagerForTracPluginLicense
11#
12# Author: Roberto Longobardi <otrebor.dev@gmail.com>
13#
14
15import os
16import re
17import shutil
18import sys
19import traceback
20
21from datetime import datetime
22
23from trac.core import *
24from trac.db import with_transaction
25
26
27def formatExceptionInfo(maxTBlevel=5):
28    cla, exc, trbk = sys.exc_info()
29    excName = cla.__name__
30
31    try:
32        excArgs = exc.__dict__["args"]
33    except KeyError:
34        excArgs = "<no args>"
35
36    excTb = traceback.format_tb(trbk, maxTBlevel)
37
38    tracestring = ""
39    for step in excTb:
40        tracestring += step + "\n"
41
42    return "Error name: %s\nArgs: %s\nTraceback:\n%s" % (excName, excArgs, tracestring)
43
44
45checked_utimestamp = False
46has_utimestamp = False
47checked_compatibility = False
48has_read_db = False
49
50def to_any_timestamp(date_obj):
51    global checked_utimestamp
52    global has_utimestamp
53
54    if not checked_utimestamp:
55        check_utimestamp()
56
57    if has_utimestamp:
58        from trac.util.datefmt import to_utimestamp
59        return to_utimestamp(date_obj)
60    else:
61        # Trac 0.11
62        from trac.util.datefmt import to_timestamp
63        return to_timestamp(date_obj)
64
65def from_any_timestamp(ts):
66    global checked_utimestamp
67    global has_utimestamp
68
69    if not checked_utimestamp:
70        check_utimestamp()
71
72    if has_utimestamp:
73        from trac.util.datefmt import from_utimestamp
74        return from_utimestamp(ts)
75    else:
76        # Trac 0.11
77        from trac.util.datefmt import utc
78        return datetime.fromtimestamp(ts, utc)
79
80def get_db(env, db=None):
81    raise TracError('get_db function is deprecated!')
82
83def get_db_for_write(env, db=None):
84    raise TracError('get_db_for_write function is deprecated!')
85
86def check_utimestamp():
87    global checked_utimestamp
88    global has_utimestamp
89
90    try:
91        from trac.util.datefmt import to_utimestamp, from_utimestamp
92        has_utimestamp = True
93    except:
94        # Trac 0.11
95        has_utimestamp = False
96
97    checked_utimestamp = True
98
99def check_compatibility(env):
100    global checked_compatibility
101    global has_read_db
102
103    try:
104        if env.get_read_db():
105            has_read_db = True
106    except:
107        # Trac 0.11
108        has_read_db = False
109
110    checked_compatibility = True
111
112def to_list(params=[]):
113    result = []
114
115    for i in params:
116        if isinstance(i, list):
117            for v in i:
118                result.append(v)
119        else:
120            result.append(i)
121
122    return tuple(result)
123
124
125def get_dictionary_from_string(str):
126    result = {}
127
128    sub = str.partition('{')[2].rpartition('}')[0]
129    tokens = sub.split(",")
130
131    for tok in tokens:
132        name = remove_quotes(tok.partition(':')[0])
133        value = remove_quotes(tok.partition(':')[2])
134
135        result[name] = value
136
137    return result
138
139
140def get_string_from_dictionary(dictionary, values=None):
141    if values is None:
142        values = dictionary
143
144    result = '{'
145    for i, k in enumerate(dictionary):
146        # TODO: send a patch for the following line
147        # result += "'"+k+"':'"+values[k]+"'"  # old code not working for int values
148        result += "'%s':'%s'" % (k, values[k])
149        if i < len(dictionary)-1:
150            result += ","
151
152    result += '}'
153
154    return result
155
156
157def remove_quotes(str, quote='\''):
158    return str.partition(quote)[2].rpartition(quote)[0]
159
160
161def compatible_domain_functions(domain, function_name_list):
162    return lambda x: x, lambda x: x, lambda x: x, lambda x: x
163
164def get_timestamp_db_type():
165    global checked_utimestamp
166    global has_utimestamp
167
168    if not checked_utimestamp:
169        check_utimestamp()
170
171    if has_utimestamp:
172        return 'int64'
173    else:
174        # Trac 0.11
175        return 'int'
176
177def upload_file_to_subdir(env, req, subdir, param_name, target_filename):
178    upload = param_name
179
180    if isinstance(upload, unicode) or not upload.filename:
181        raise TracError('You must provide a file.')
182
183    txt_filename = upload.filename.replace('\\', '/').replace(':', '/')
184    txt_filename = os.path.basename(txt_filename)
185    if not txt_filename:
186        raise TracError('You must provide a file.')
187
188    target_dir = os.path.join(env.path, 'upload', subdir)
189
190    if not os.access(target_dir, os.F_OK):
191        os.makedirs(target_dir)
192
193    target_path = os.path.join(target_dir, target_filename)
194
195    try:
196        target_file = open(target_path, 'w')
197        shutil.copyfileobj(upload.file, target_file)
198    finally:
199        target_file.close()
200
201
202def db_insert_or_ignore(env, tablename, propname, value, db=None):
203    if db_get_config_property(env, tablename, propname, db) is None:
204        db_set_config_property(env, tablename, propname, value, db)
205
206def db_get_config_property(env, tablename, propname, db=None):
207    if not db:
208        db = env.get_read_db()
209
210    cursor = db.cursor()
211
212    sql = "SELECT value FROM %s WHERE propname=%%s" % tablename
213    row = None
214
215    try:
216        cursor.execute(sql, (propname,))
217        row = cursor.fetchone()
218    except:
219        pass
220
221    if not row or len(row) == 0:
222        return None
223
224    return row[0]
225
226def db_set_config_property(env, tablename, propname, value, db=None):
227    @env.with_transaction(db)
228    def do_db_set_config_property(db):
229        cursor = db.cursor()
230
231        sql = "SELECT COUNT(*) FROM %s WHERE propname = %%s" % tablename
232        cursor.execute(sql, (propname,))
233
234        row = cursor.fetchone()
235        if row is not None and int(row[0]) > 0:
236            cursor.execute("""
237                           UPDATE %s
238                               SET value = %%s
239                               WHERE propname = %%s
240                           """ % tablename, (str(value), propname))
241        else:
242            cursor.execute("""
243                           INSERT INTO %s (propname,value)
244                               VALUES (%%s,%%s)
245                           """ % tablename, (propname, str(value)))
246
247    return True
248
249def list_available_tables(dburi, cursor):
250    if dburi.startswith('sqlite:'):
251        query = """
252            SELECT name FROM sqlite_master
253            WHERE type='table' AND NOT name='sqlite_sequence'
254            """
255    elif dburi.startswith('postgres:'):
256        query = """
257            SELECT tablename FROM pg_tables
258            WHERE schemaname = ANY (current_schemas(false))
259            """
260    elif dburi.startswith('mysql:'):
261        query = "SHOW TABLES"
262    else:
263        raise TracError('Unsupported %s database' % dburi.split(':')[0])
264    cursor.execute(query)
265
266    return sorted([row[0] for row in cursor])
267
268def fix_base_location(req):
269    return req.href('/').rstrip('/')
270
271
272## {{{ http://code.activestate.com/recipes/550804/ (r2)
273# The list of symbols that are included by default in the generated
274# function's environment
275SAFE_SYMBOLS = ["list", "dict", "tuple", "set", "long", "float", "object",
276                "bool", "callable", "True", "False", "dir",
277                "frozenset", "getattr", "hasattr", "abs", "cmp", "complex",
278                "divmod", "id", "pow", "round", "slice", "vars",
279                "hash", "hex", "int", "isinstance", "issubclass", "len",
280                "map", "filter", "max", "min", "oct", "chr", "ord", "range",
281                "reduce", "repr", "str", "type", "zip", "xrange", "None",
282                "Exception", "KeyboardInterrupt"]
283# Also add the standard exceptions
284__bi = __builtins__
285if type(__bi) is not dict:
286    __bi = __bi.__dict__
287for k in __bi:
288    if k.endswith("Error") or k.endswith("Warning"):
289        SAFE_SYMBOLS.append(k)
290del __bi
291
292def createFunctionFromString(sourceCode, args="", additional_symbols=dict()):
293    """
294    Create a python function from the given source code
295
296    \param sourceCode A python string containing the core of the
297    function. Might include the return statement (or not), definition of
298    local functions, classes, etc. Indentation matters !
299
300    \param args The string representing the arguments to put in the function's
301    prototype, such as "a, b", or "a=12, b",
302    or "a=12, b=dict(akey=42, another=5)"
303
304    \param additional_symbols A dictionary variable name =>
305    variable/funcion/object to include in the generated function's
306    closure
307
308    The sourceCode will be executed in a restricted environment,
309    containing only the python builtins that are harmless (such as map,
310    hasattr, etc.). To allow the function to access other modules or
311    functions or objects, use the additional_symbols parameter. For
312    example, to allow the source code to access the re and sys modules,
313    as well as a global function F named afunction in the sourceCode and
314    an object OoO named ooo in the sourceCode, specify:
315        additional_symbols = dict(re=re, sys=sys, afunction=F, ooo=OoO)
316
317    \return A python function implementing the source code. It can be
318    recursive: the (internal) name of the function being defined is:
319    __TheFunction__. Its docstring is the initial sourceCode string.
320
321    Tests show that the resulting function does not have any calling
322    time overhead (-3% to +3%, probably due to system preemption aleas)
323    compared to normal python function calls.
324    """
325    # Include the sourcecode as the code of a function __TheFunction__:
326    s = "def __TheFunction__(%s):\n" % args
327    s += "\t" + "\n\t".join(sourceCode.split('\n')) + "\n"
328
329    # Byte-compilation (optional)
330    byteCode = compile(s, "<string>", 'exec')
331
332    # Setup the local and global dictionaries of the execution
333    # environment for __TheFunction__
334    bis   = dict() # builtins
335    globs = dict()
336    locs  = dict()
337
338    # Setup a standard-compatible python environment
339    bis["locals"]  = lambda: locs
340    bis["globals"] = lambda: globs
341    globs["__builtins__"] = bis
342    globs["__name__"] = "SUBENV"
343    globs["__doc__"] = sourceCode
344
345    # Determine how the __builtins__ dictionary should be accessed
346    if type(__builtins__) is dict:
347        bi_dict = __builtins__
348    else:
349        bi_dict = __builtins__.__dict__
350
351    # Include the safe symbols
352    for k in SAFE_SYMBOLS:
353        # try from current locals
354        try:
355            locs[k] = locals()[k]
356            continue
357        except KeyError:
358            pass
359        # Try from globals
360        try:
361            globs[k] = globals()[k]
362            continue
363        except KeyError:
364            pass
365        # Try from builtins
366        try:
367            bis[k] = bi_dict[k]
368        except KeyError:
369            # Symbol not available anywhere: silently ignored
370            pass
371
372    # Include the symbols added by the caller, in the globals dictionary
373    globs.update(additional_symbols)
374
375    # Finally execute the def __TheFunction__ statement:
376    eval(byteCode, globs, locs)
377    # As a result, the function is defined as the item __TheFunction__
378    # in the locals dictionary
379    fct = locs["__TheFunction__"]
380    # Attach the function to the globals so that it can be recursive
381    del locs["__TheFunction__"]
382    globs["__TheFunction__"] = fct
383    # Attach the actual source code to the docstring
384    fct.__doc__ = sourceCode
385    return fct
386## end of http://code.activestate.com/recipes/550804/ }}}
387
388# Example:
389#
390# import sys, re
391#
392# f = createFunction("print a\nprint b", "a=3, b=4",
393#                    additional_symbols = dict(re=re, sys=sys,
394#                                              afunction=F, ooo=OoO))
395# f()
396# f(12)
397# f(b=7, a=8)
398# f(9, 10)
Note: See TracBrowser for help on using the repository browser.