File: model.py

package info (click to toggle)
trac-tags 0.7%2Bsvn12392-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd, stretch
  • size: 324 kB
  • ctags: 268
  • sloc: python: 2,029; makefile: 2
file content (113 lines) | stat: -rw-r--r-- 3,155 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2012 Steffen Hoffmann <hoff.st@web.de>
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution.

from trac.resource import Resource
from trac.util.compat import groupby


# Public functions (not yet)


# Utility functions

def tag_resource(env, realm, id, new_id=None, tags=None, db=None):
    """Change recorded tags for a Trac resource.

    This function combines delete, reparent and set actions now, but it could
    possibly be still a bit more efficient.
    """
    db = _get_db(env, db)
    cursor = db.cursor()

    if new_id:
        cursor.execute("""
            UPDATE tags
               SET name=%s
             WHERE tagspace=%s
               AND name=%s
        """, (new_id, realm, id))
    else:
        # DEVEL: Work out the difference instead of stupid delete/re-insertion.
        cursor.execute("""
            DELETE FROM tags
             WHERE tagspace=%s
               AND name=%s
        """, (realm, id))
    if tags:
        cursor.executemany("""
            INSERT INTO tags
                   (tagspace, name, tag)
            VALUES (%s,%s,%s)
        """, [(realm, id, tag) for tag in tags])
    db.commit()

def tagged_resources(env, perm_check, perm, realm, tags=None, filter=None,
                     db=None):
    """Return Trac resources including their associated tags.

    This is currently known to be a major performance hog.
    """
    db = _get_db(env, db)
    cursor = db.cursor()

    args = [realm]
    sql = """
        SELECT DISTINCT name
          FROM tags
         WHERE tagspace=%s"""
    if filter:
        sql += ''.join([" AND %s" % f for f in filter])
    if tags:
        sql += " AND tags.tag IN (%s)" % ','.join(['%s' for tag in tags])
        args += tags
    sql += " ORDER by name"
    cursor.execute(sql, args)

    # Inlined permission check for efficiency.
    resources = {}
    for name, in cursor:
        resource = Resource(realm, name)
        if perm_check(perm(resource), 'view'):
            resources[resource.id] = resource
    if not resources:
        return

    args = [realm] + resources.keys()
    # DEVEL: Is this going to be excruciatingly slow?
    #        The explicite resource ID list might even grow beyond some limit.
    sql = """
        SELECT DISTINCT name, tag
          FROM tags
         WHERE tagspace=%%s
           AND name IN (%s)
         ORDER BY name
    """ % ', '.join(['%s' for resource in resources])
    cursor.execute(sql, args)

    for name, tags in groupby(cursor, lambda row: row[0]):
        resource = resources[name]
        yield resource, set([tag[1] for tag in tags])

def resource_tags(env, realm, id, db=None):
    """Return all tags for a Trac resource by realm and ID."""
    db = _get_db(env, db)
    cursor = db.cursor()

    cursor.execute("""
        SELECT tag
          FROM tags
         WHERE tagspace=%s
           AND name=%s
    """, (realm, id))
    for row in cursor:
        yield row[0]

# Internal functions

def _get_db(env, db=None):
    return db or env.get_db_cnx()