Skip to content

Commit

Permalink
Conform to PEP8
Browse files Browse the repository at this point in the history
  • Loading branch information
rjollos committed May 11, 2018
1 parent 7026a9f commit fa7cdff
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 131 deletions.
10 changes: 2 additions & 8 deletions code_comments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
from code_comments import comment
from code_comments import comment_macro
from code_comments import comments
from code_comments import db
from code_comments import notification
from code_comments import subscription
from code_comments import ticket_event_listener
from code_comments import web
import pkg_resources
pkg_resources.require('Trac >= 1.2')
2 changes: 2 additions & 0 deletions code_comments/api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

from trac.core import Component, ExtensionPoint, Interface


Expand Down
76 changes: 46 additions & 30 deletions code_comments/comment.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import re
# -*- coding: utf-8 -*-

import hashlib
import json
import locale
import re

import trac.wiki.formatter
from trac.mimeview.api import Context
from time import strftime, localtime
from code_comments import db
from trac.util import Markup
from trac.web.href import Href
from trac.test import EnvironmentStub, Mock, MockPerm
from trac.test import Mock, MockPerm

try:
import json
except ImportError:
import simplejson as json

try:
import hashlib
md5_hexdigest = lambda s: hashlib.md5(s).hexdigest()
except ImportError:
import md5
md5_hexdigest = lambda s: md5.new(s).hexdigest()
def md5_hexdigest(s):
return hashlib.md5(s).hexdigest()


VERSION = 1


class Comment:
columns = [column.name for column in db.schema['code_comments'].columns]

Expand All @@ -40,7 +37,7 @@ def __init__(self, req, env, data):
self.req = req
if self._empty('version'):
self.version = VERSION
if self._empty( 'path' ):
if self._empty('path'):
self.path = ''
self.html = format_to_html(self.req, self.env, self.text)
email = self.email_map().get(self.author, 'baba@baba.net')
Expand All @@ -64,17 +61,25 @@ def email_map(self):
return Comment._email_map

def validate(self):
missing = [column_name for column_name in self.required if self._empty(column_name)]
missing = [
column_name
for column_name in self.required if self._empty(column_name)
]
if missing:
raise ValueError("Comment column(s) missing: %s" % ', '.join(missing))
raise ValueError("Comment column(s) missing: %s"
% ', '.join(missing))

def href(self):
if self.is_comment_to_file:
href = self.req.href.browser(self.path, rev=self.revision, codecomment=self.id)
href = self.req.href.browser(self.path, rev=self.revision,
codecomment=self.id)
elif self.is_comment_to_changeset:
href = self.req.href.changeset(self.revision, codecomment=self.id)
elif self.is_comment_to_attachment:
href = self.req.href('/attachment/ticket/%d/%s' % (self.attachment_ticket, self.attachment_filename), codecomment=self.id)
href = self.req.href('/attachment/ticket/%d/%s'
% (self.attachment_ticket,
self.attachment_filename),
codecomment=self.id)
if self.line and not self.is_comment_to_changeset:
href += '#L' + str(self.line)
return href
Expand All @@ -96,7 +101,8 @@ def link_text(self):

def changeset_link_text(self):
if 0 != self.line:
return 'Changeset @%d#L%d (in %s)' % ( self.revision, self.line, self.path )
return 'Changeset @%d#L%d (in %s)' % (self.revision, self.line,
self.path)
else:
return 'Changeset @%s' % self.revision

Expand All @@ -109,8 +115,8 @@ def trac_link(self):
return 'source:' + self.link_text()

def attachment_info(self):
info = { 'ticket': None, 'filename': None }
if not self.path.startswith( 'attachment' ):
info = {'ticket': None, 'filename': None}
if not self.path.startswith('attachment'):
return info
match = re.match(r'attachment:/ticket/(\d+)/(.*)', self.path)
if not match:
Expand All @@ -124,17 +130,20 @@ def path_link_tag(self):

def formatted_date(self):
encoding = locale.getlocale()[1] if locale.getlocale()[1] else 'utf-8'
return strftime('%d %b %Y, %H:%M', localtime(self.time)).decode(encoding)
return strftime('%d %b %Y, %H:%M',
localtime(self.time)).decode(encoding)

def get_ticket_relations(self):
relations = set()
db = self.env.get_db_cnx()
cursor = db.cursor()
query = """SELECT ticket FROM ticket_custom WHERE name = 'code_comment_relation' AND
(value LIKE '%(comment_id)d' OR
value LIKE '%(comment_id)d,%%' OR
value LIKE '%%,%(comment_id)d' OR value LIKE '%%,%(comment_id)d,%%')""" % {'comment_id': self.id}
query = """
SELECT ticket FROM ticket_custom
WHERE name = 'code_comment_relation' AND
(VALUE LIKE '%(comment_id)d' OR
VALUE LIKE '%(comment_id)d,%%' OR
VALUE LIKE '%%,%(comment_id)d' OR
VALUE LIKE '%%,%(comment_id)d,%%')
""" % {'comment_id': self.id}
result = {}

@self.env.with_transaction()
def get_ticket_ids(db):
cursor = db.cursor()
Expand All @@ -153,17 +162,24 @@ def delete_comment(db):
cursor = db.cursor()
cursor.execute("DELETE FROM code_comments WHERE id=%s", [self.id])


class CommentJSONEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, Comment):
for_json = dict([(name, getattr(o, name)) for name in o.__dict__ if isinstance(getattr(o, name), (basestring, int, list, dict))])
for_json = dict([
(name, getattr(o, name))
for name in o.__dict__
if isinstance(getattr(o, name), (basestring, int, list, dict))
])
for_json['formatted_date'] = o.formatted_date()
for_json['permalink'] = o.href()
return for_json
else:
return json.JSONEncoder.default(self, o)


def format_to_html(req, env, text):
req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'), authname='anonymous', perm=MockPerm(), args={})
req = Mock(href=Href('/'), abs_href=Href('http://www.example.com/'),
authname='anonymous', perm=MockPerm(), args={})
context = Context.from_request(req)
return trac.wiki.formatter.format_to_html(env, context, text)
9 changes: 6 additions & 3 deletions code_comments/comment_macro.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
# -*- coding: utf-8 -*-

from code_comments.comments import Comments
from genshi.builder import tag
from trac.wiki.macros import WikiMacroBase


class CodeCommentLinkMacro(WikiMacroBase):
"""CodeCommentLink macro.
This macro is used to embed a comment link in a ticket or wiki page:
[[CodeCommentLink(5)]]
where the number in the parentheses is the comment ID.
"""

revision = "$Rev$"
url = "$URL$"
re = r'\[\[CodeCommentLink\((\d+)\)\]\]'

def expand_macro(self, formatter, name, text, args):
try:
comment = Comments(formatter.req, formatter.env).by_id(text)
return tag.a(comment.link_text(), href=comment.href())
except:
return ''
return ''
58 changes: 40 additions & 18 deletions code_comments/comments.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# -*- coding: utf-8 -*-

import os.path
from time import time

from code_comments.api import CodeCommentSystem
from code_comments.comment import Comment


class Comments:

FILTER_MAX_PATH_DEPTH = 2
Expand All @@ -22,28 +26,37 @@ def get_filter_values(self):
}

def get_all_paths(self, comments):
get_directory = lambda path: '/'.join(os.path.split(path)[0].split('/')[:self.FILTER_MAX_PATH_DEPTH])
return sorted(set([get_directory(comment.path) for comment in comments if get_directory(comment.path)]))
def get_directory(path):
parts = os.path.split(path)[0].split('/')
return '/'.join(parts[:self.FILTER_MAX_PATH_DEPTH])
paths = [
get_directory(comment.path)
for comment in comments if get_directory(comment.path)
]
return sorted(set(paths))

def get_all_comment_authors(self, comments):
return sorted(list(set([comment.author for comment in comments])))

def select(self, *query):
result = {}

@self.env.with_transaction()
def get_comments(db):
cursor = db.cursor()
cursor.execute(*query)
result['comments'] = cursor.fetchall()
return [self.comment_from_row(row) for row in result['comments']]

def count(self, args = {}):
conditions_str, values = self.get_condition_str_and_corresponding_values(args)
def count(self, args={}):
conditions_str, values = \
self.get_condition_str_and_corresponding_values(args)
where = ''
if conditions_str:
where = 'WHERE '+conditions_str
where = 'WHERE ' + conditions_str
query = 'SELECT COUNT(*) FROM code_comments ' + where
result = {}

@self.env.with_transaction()
def get_comment_count(db):
cursor = db.cursor()
Expand All @@ -58,22 +71,26 @@ def by_id(self, id):
return self.select("SELECT * FROM code_comments WHERE id=%s", [id])[0]

def assert_name(self, name):
if not name in Comment.columns:
if name not in Comment.columns:
raise ValueError("Column '%s' doesn't exist." % name)

def search(self, args, order = 'ASC', per_page = None, page = 1, order_by = 'time'):
def search(self, args, order='ASC', per_page=None, page=1,
order_by='time'):
if order_by not in self.valid_sorting_methods:
order_by = 'time'
conditions_str, values = self.get_condition_str_and_corresponding_values(args)
conditions_str, values = \
self.get_condition_str_and_corresponding_values(args)
where = ''
limit = ''
if conditions_str:
where = 'WHERE '+conditions_str
where = 'WHERE ' + conditions_str
if order != 'ASC':
order = 'DESC'
if per_page:
limit = ' LIMIT %d OFFSET %d' % (per_page, (page - 1)*per_page)
return self.select('SELECT * FROM code_comments ' + where + ' ORDER BY ' + order_by + ' ' + order + limit, values)
limit = ' LIMIT %d OFFSET %d' % (per_page, (page - 1) * per_page)
return self.select('SELECT * FROM code_comments ' + where +
' ORDER BY ' + order_by + ' ' + order + limit,
values)

def get_condition_str_and_corresponding_values(self, args):
conditions = []
Expand All @@ -88,18 +105,20 @@ def get_condition_str_and_corresponding_values(self, args):
name = name.replace('__lt', '')
conditions.append(name + ' < %s')
elif name.endswith('__prefix'):
values.append(args[name].replace('%', '\\%').replace('_', '\\_') + '%')
values.append(
args[name].replace('%', '\\%').replace('_', '\\_') + '%')
name = name.replace('__prefix', '')
conditions.append(name + ' LIKE %s')
elif name.endswith('__in'):
items = [item.strip() for item in args[name].split(',')]
name = name.replace('__in', '')
for item in items:
values.append(item)
conditions.append(name + ' IN (' + ','.join(['%s']*len(items)) + ')')
conditions.append(
name + ' IN (' + ','.join(['%s'] * len(items)) + ')')
else:
conditions.append(name + ' = %s')
# don't let SQL injections in - make sure the name is an existing comment column
# Prevent SQL injections: make sure name is an existing column
self.assert_name(name)
conditions_str = ' AND '.join(conditions)
return conditions_str, values
Expand All @@ -108,14 +127,17 @@ def create(self, args):
comment = Comment(self.req, self.env, args)
comment.validate()
comment.time = int(time())
column_names_to_insert = [column_name for column_name in comment.columns if column_name != 'id']
values = [getattr(comment, column_name) for column_name in column_names_to_insert]
column_names_to_insert = [n for n in comment.columns if n != 'id']
values = [getattr(comment, n) for n in column_names_to_insert]
comment_id = [None]

@self.env.with_transaction()
def insert_comment(db):
cursor = db.cursor()
sql = "INSERT INTO code_comments (%s) values(%s)" % (', '.join(column_names_to_insert), ', '.join(['%s'] * len(values)))
self.env.log.debug(sql)
sql = """
INSERT INTO code_comments (%s) VALUES(%s)
""" % (', '.join(column_names_to_insert),
', '.join(['%s'] * len(values)))
cursor.execute(sql, values)
comment_id[0] = db.get_last_id(cursor, 'code_comments')

Expand Down
19 changes: 12 additions & 7 deletions code_comments/db.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

from trac.core import Component, implements
from trac.db.schema import Table, Column, Index
from trac.env import IEnvironmentSetupParticipant
Expand Down Expand Up @@ -132,19 +134,22 @@ def upgrade_environment(self, db):
if current_ver == 0:
create_tables(self.env, db)
else:
while current_ver+1 <= db_version:
upgrade_map[current_ver+1](self.env, db)
while current_ver + 1 <= db_version:
upgrade_map[current_ver + 1](self.env, db)
current_ver += 1
cursor = db.cursor()
cursor.execute(
"UPDATE system SET value=%s WHERE name='code_comments_schema_version'",
str(db_version))
cursor.execute("""
UPDATE system SET value=%s
WHERE name='code_comments_schema_version'
""", str(db_version))

def _get_version(self, db):
cursor = db.cursor()
try:
sql = "SELECT value FROM system WHERE name='code_comments_schema_version'"
cursor.execute(sql)
cursor.execute("""
SELECT value FROM system
WHERE name='code_comments_schema_version'
""")
for row in cursor:
return int(row[0])
return 0
Expand Down
2 changes: 1 addition & 1 deletion code_comments/htdocs/backbone-min.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions code_comments/notification.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

from trac.config import BoolOption
from trac.core import Component, implements
from trac.notification import NotifyEmail
Expand Down
Loading

0 comments on commit fa7cdff

Please sign in to comment.