##// END OF EJS Templates
merged with default
marcink -
r470:935dddee merge celery
parent child Browse files
Show More
1 NO CONTENT: new file 100644, binary diff hidden
@@ -1,74 +1,74
1 1 """Pylons environment configuration"""
2 2 from mako.lookup import TemplateLookup
3 3 from pylons.configuration import PylonsConfig
4 4 from pylons.error import handle_mako_error
5 5 from pylons_app.config.routing import make_map
6 6 from pylons_app.lib.auth import set_available_permissions, set_base_path
7 7 from pylons_app.lib.utils import repo2db_mapper, make_ui, set_hg_app_config
8 8 from pylons_app.model import init_model
9 9 from pylons_app.model.hg_model import _get_repos_cached_initial
10 10 from sqlalchemy import engine_from_config
11 11 import logging
12 12 import os
13 13 import pylons_app.lib.app_globals as app_globals
14 14 import pylons_app.lib.helpers
15 15
16 16 log = logging.getLogger(__name__)
17 17
18 18 def load_environment(global_conf, app_conf, initial=False):
19 19 """Configure the Pylons environment via the ``pylons.config``
20 20 object
21 21 """
22 22 config = PylonsConfig()
23 23
24 24 # Pylons paths
25 25 root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
26 26 paths = dict(root=root,
27 27 controllers=os.path.join(root, 'controllers'),
28 28 static_files=os.path.join(root, 'public'),
29 29 templates=[os.path.join(root, 'templates')])
30 30
31 31 # Initialize config with the basic options
32 32 config.init_app(global_conf, app_conf, package='pylons_app', paths=paths)
33 33
34 34 config['routes.map'] = make_map(config)
35 35 config['pylons.app_globals'] = app_globals.Globals(config)
36 36 config['pylons.h'] = pylons_app.lib.helpers
37 37
38 38 # Setup cache object as early as possible
39 39 import pylons
40 40 pylons.cache._push_object(config['pylons.app_globals'].cache)
41 41
42 42 # Create the Mako TemplateLookup, with the default auto-escaping
43 43 config['pylons.app_globals'].mako_lookup = TemplateLookup(
44 44 directories=paths['templates'],
45 45 error_handler=handle_mako_error,
46 46 module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
47 47 input_encoding='utf-8', default_filters=['escape'],
48 48 imports=['from webhelpers.html import escape'])
49 49
50 50 #sets the c attribute access when don't existing attribute are accessed
51 51 config['pylons.strict_tmpl_context'] = True
52
52 test = os.path.split(config['__file__'])[-1] == 'tests.ini'
53 53 #MULTIPLE DB configs
54 54 # Setup the SQLAlchemy database engine
55 if config['debug'] and os.path.split(config['__file__'])[-1] != 'tests.ini':
55 if config['debug'] and not test:
56 56 #use query time debugging.
57 57 from pylons_app.lib.timerproxy import TimerProxy
58 58 sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.',
59 59 proxy=TimerProxy())
60 60 else:
61 61 sa_engine_db1 = engine_from_config(config, 'sqlalchemy.db1.')
62 62
63 63 init_model(sa_engine_db1)
64 64 #init baseui
65 65 config['pylons.app_globals'].baseui = make_ui('db')
66 66
67 67 repo2db_mapper(_get_repos_cached_initial(config['pylons.app_globals'], initial))
68 68 set_available_permissions(config)
69 69 set_base_path(config)
70 70 set_hg_app_config(config)
71 71 # CONFIGURATION OPTIONS HERE (note: all config options will override
72 72 # any Pylons config options)
73 73
74 74 return config
@@ -1,136 +1,138
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 # changeset controller for pylons
4 4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 5 # This program is free software; you can redistribute it and/or
6 6 # modify it under the terms of the GNU General Public License
7 7 # as published by the Free Software Foundation; version 2
8 8 # of the License or (at your opinion) any later version of the license.
9 9 #
10 10 # This program is distributed in the hope that it will be useful,
11 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 # GNU General Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License
16 16 # along with this program; if not, write to the Free Software
17 17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 18 # MA 02110-1301, USA.
19 19 """
20 20 Created on April 25, 2010
21 21 changeset controller for pylons
22 22 @author: marcink
23 23 """
24 24 from pylons import tmpl_context as c, url, request, response
25 25 from pylons.controllers.util import redirect
26 26 from pylons_app.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
27 27 from pylons_app.lib.base import BaseController, render
28 28 from pylons_app.model.hg_model import HgModel
29 29 from vcs.exceptions import RepositoryError
30 30 from vcs.nodes import FileNode
31 31 from vcs.utils import diffs as differ
32 32 import logging
33 33 import traceback
34 34
35 35 log = logging.getLogger(__name__)
36 36
37 37 class ChangesetController(BaseController):
38 38
39 39 @LoginRequired()
40 40 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
41 41 'repository.admin')
42 42 def __before__(self):
43 43 super(ChangesetController, self).__before__()
44 44
45 45 def index(self, revision):
46 46 hg_model = HgModel()
47 47 try:
48 48 c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
49 49 except RepositoryError:
50 50 log.error(traceback.format_exc())
51 51 return redirect(url('hg_home'))
52 52 else:
53 53 try:
54 54 c.changeset_old = c.changeset.parents[0]
55 55 except IndexError:
56 56 c.changeset_old = None
57 57 c.changes = []
58 58
59 59 for node in c.changeset.added:
60 60 filenode_old = FileNode(node.path, '')
61 61 if filenode_old.is_binary or node.is_binary:
62 62 diff = 'binary file'
63 63 else:
64 64 f_udiff = differ.get_udiff(filenode_old, node)
65 65 diff = differ.DiffProcessor(f_udiff).as_html()
66 66
67 67 cs1 = None
68 68 cs2 = node.last_changeset.raw_id
69 69 c.changes.append(('added', node, diff, cs1, cs2))
70 70
71 71 for node in c.changeset.changed:
72 72 filenode_old = c.changeset_old.get_node(node.path)
73 73 if filenode_old.is_binary or node.is_binary:
74 74 diff = 'binary file'
75 75 else:
76 76 f_udiff = differ.get_udiff(filenode_old, node)
77 77 diff = differ.DiffProcessor(f_udiff).as_html()
78 78
79 79 cs1 = filenode_old.last_changeset.raw_id
80 80 cs2 = node.last_changeset.raw_id
81 81 c.changes.append(('changed', node, diff, cs1, cs2))
82 82
83 83 for node in c.changeset.removed:
84 84 c.changes.append(('removed', node, None, None, None))
85 85
86 86 return render('changeset/changeset.html')
87 87
88 88 def raw_changeset(self,revision):
89 89
90 90 hg_model = HgModel()
91 method = request.GET.get('diff','show')
91 92 try:
92 93 c.changeset = hg_model.get_repo(c.repo_name).get_changeset(revision)
93 94 except RepositoryError:
94 95 log.error(traceback.format_exc())
95 96 return redirect(url('hg_home'))
96 97 else:
97 98 try:
98 99 c.changeset_old = c.changeset.parents[0]
99 100 except IndexError:
100 101 c.changeset_old = None
101 102 c.changes = []
102 103
103 104 for node in c.changeset.added:
104 105 filenode_old = FileNode(node.path, '')
105 106 if filenode_old.is_binary or node.is_binary:
106 107 diff = 'binary file'
107 108 else:
108 109 f_udiff = differ.get_udiff(filenode_old, node)
109 110 diff = differ.DiffProcessor(f_udiff).raw_diff()
110 111
111 112 cs1 = None
112 113 cs2 = node.last_changeset.raw_id
113 114 c.changes.append(('added', node, diff, cs1, cs2))
114 115
115 116 for node in c.changeset.changed:
116 117 filenode_old = c.changeset_old.get_node(node.path)
117 118 if filenode_old.is_binary or node.is_binary:
118 119 diff = 'binary file'
119 120 else:
120 121 f_udiff = differ.get_udiff(filenode_old, node)
121 122 diff = differ.DiffProcessor(f_udiff).raw_diff()
122 123
123 124 cs1 = filenode_old.last_changeset.raw_id
124 125 cs2 = node.last_changeset.raw_id
125 126 c.changes.append(('changed', node, diff, cs1, cs2))
126 127
127 128 response.content_type = 'text/plain'
128
129 if method == 'download':
130 response.content_disposition = 'attachment; filename=%s.patch' % revision
129 131 parent = True if len(c.changeset.parents) > 0 else False
130 132 c.parent_tmpl = 'Parent %s' % c.changeset.parents[0]._hex if parent else ''
131 133
132 134 c.diffs = ''
133 135 for x in c.changes:
134 136 c.diffs += x[2]
135 137
136 138 return render('changeset/raw_changeset.html')
@@ -1,94 +1,106
1 1 <%inherit file="/base/base.html"/>
2 2
3 3 <%def name="title()">
4 4 ${_('Changeset')}
5 5 </%def>
6 6
7 7 <%def name="breadcrumbs_links()">
8 8 ${h.link_to(u'Home',h.url('/'))}
9 9 &raquo;
10 10 ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))}
11 11 &raquo;
12 12 ${_('Changeset')} - r${c.changeset.revision}:${c.changeset.raw_id}
13 13 </%def>
14 14
15 15 <%def name="page_nav()">
16 16 ${self.menu('changelog')}
17 17 </%def>
18 18
19 19 <%def name="main()">
20 20 <div class="box">
21 21 <!-- box / title -->
22 22 <div class="title">
23 23 ${self.breadcrumbs()}
24 24 </div>
25 25 <div class="table">
26 <div id="body" class="diffblock">
27 <div class="code-header">
28 <div>
29 ${_('Changeset')} - r${c.changeset.revision}:${c.changeset.raw_id}
30 &raquo; <span>${h.link_to(_('raw diff'),
31 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='show'))}</span>
32 &raquo; <span>${h.link_to(_('download diff'),
33 h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download'))}</span>
34 </div>
35 </div>
36 </div>
37
26 38 <div id="changeset_content">
27 39 <div class="container">
28 40 <div class="left">
29 41 <div class="date">${_('Date')}: ${c.changeset.date}</div>
30 42 <div class="author">${_('Author')}: ${c.changeset.author}</div>
31 43 <div class="message">${h.wrap_paragraphs(c.changeset.message)}</div>
32 44 </div>
33 45 <div class="right">
34 46 <span class="logtags">
35 47 <span class="branchtag">${c.changeset.branch}</span>
36 48 %for tag in c.changeset.tags:
37 49 <span class="tagtag">${tag}</span>
38 50 %endfor
39 51 </span>
40 52 %if len(c.changeset.parents)>1:
41 53 <div class="merge">
42 54 ${_('merge')}
43 55 <img alt="merge" src="/images/icons/arrow_join.png">
44 56 </div>
45 57 %endif
46 58 %for p_cs in reversed(c.changeset.parents):
47 59 <div class="parent">${_('Parent')} ${p_cs.revision}: ${h.link_to(p_cs.raw_id,
48 60 h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}
49 61 </div>
50 62 %endfor
51 63 </div>
52 64 </div>
53 65 <span style="font-size:1.1em;font-weight: bold">${_('Files affected')}</span>
54 66 <div class="cs_files">
55 67 %for change,filenode,diff,cs1,cs2 in c.changes:
56 68 <div class="cs_${change}">${h.link_to(filenode.path,h.url.current(anchor='CHANGE-%s'%filenode.path))}</div>
57 69 %endfor
58 70 </div>
59 71 </div>
60 72
61 73 %for change,filenode,diff,cs1,cs2 in c.changes:
62 74 %if change !='removed':
63 75 <div style="clear:both;height:10px"></div>
64 76 <div id="body" class="diffblock">
65 77 <div id="${'CHANGE-%s'%filenode.path}" class="code-header">
66 78 <div>
67 79 <span>
68 80 ${h.link_to_if(change!='removed',filenode.path,h.url('files_home',repo_name=c.repo_name,
69 81 revision=filenode.changeset.raw_id,f_path=filenode.path))}
70 82 </span>
71 83 %if 1:
72 84 &raquo; <span>${h.link_to(_('diff'),
73 85 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='diff'))}</span>
74 86 &raquo; <span>${h.link_to(_('raw diff'),
75 87 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='raw'))}</span>
76 88 &raquo; <span>${h.link_to(_('download diff'),
77 89 h.url('files_diff_home',repo_name=c.repo_name,f_path=filenode.path,diff2=cs2,diff1=cs1,diff='download'))}</span>
78 90 %endif
79 91 </div>
80 92 </div>
81 93 <div class="code-body">
82 94 %if diff:
83 95 ${diff|n}
84 96 %else:
85 97 ${_('No changes in this file')}
86 98 %endif
87 99 </div>
88 100 </div>
89 101 %endif
90 102 %endfor
91 103 </div>
92 104 </div>
93 105
94 106 </%def> No newline at end of file
@@ -1,8 +1,8
1 1 # HG changeset patch
2 # User ${c.changeset.author}
2 # User ${c.changeset.author|n}
3 3 # Date ${"%d %d" % c.changeset._ctx.date()}
4 4 # Node ID ${c.changeset._hex}
5 5 # ${c.parent_tmpl}
6 6 ${c.changeset.message}
7 7
8 8 ${c.diffs|n} No newline at end of file
@@ -1,46 +1,45
1 1 """Pylons application test package
2 2
3 3 This package assumes the Pylons environment is already loaded, such as
4 4 when this script is imported from the `nosetests --with-pylons=test.ini`
5 5 command.
6 6
7 7 This module initializes the application via ``websetup`` (`paster
8 8 setup-app`) and provides the base testing objects.
9 9 """
10 10 from unittest import TestCase
11 11
12 12 from paste.deploy import loadapp
13 13 from paste.script.appinstall import SetupCommand
14 14 from pylons import config, url
15 15 from routes.util import URLGenerator
16 16 from webtest import TestApp
17 17 import os
18 18 from pylons_app.model import meta
19 19 import pylons.test
20 20
21 21 __all__ = ['environ', 'url', 'TestController']
22 22
23 23 # Invoke websetup with the current config file
24 24 SetupCommand('setup-app').run([pylons.test.pylonsapp.config['__file__']])
25 25
26 26 environ = {}
27 27
28 28 class TestController(TestCase):
29 29
30 30 def __init__(self, *args, **kwargs):
31 31 wsgiapp = pylons.test.pylonsapp
32 32 config = wsgiapp.config
33 33 self.app = TestApp(wsgiapp)
34 self.session = session
35 34 url._push_object(URLGenerator(config['routes.map'], environ))
36 35 self.sa = meta.Session
37 36 TestCase.__init__(self, *args, **kwargs)
38 37
39 38
40 39 def log_user(self):
41 40 response = self.app.post(url(controller='login', action='index'),
42 41 {'username':'test_admin',
43 42 'password':'test'})
44 43 assert response.status == '302 Found', 'Wrong response code from login got %s' % response.status
45 44 assert response.session['hg_app_user'].username == 'test_admin', 'wrong logged in user'
46 45 return response.follow() No newline at end of file
@@ -1,15 +1,29
1 1 from pylons_app.tests import *
2 from pylons_app.lib.indexers import IDX_LOCATION
3 import os
4 from nose.plugins.skip import SkipTest
2 5
3 6 class TestSearchController(TestController):
4 7
5 8 def test_index(self):
6 9 self.log_user()
7 10 response = self.app.get(url(controller='search', action='index'))
8 11 print response.body
9 12 assert 'class="small" id="q" name="q" type="text"' in response.body,'Search box content error'
10 13 # Test response...
11 14
12 15 def test_empty_search(self):
16
17 if os.path.isdir(IDX_LOCATION):
18 raise SkipTest('skipped due to existing index')
19 else:
20 self.log_user()
21 response = self.app.get(url(controller='search', action='index'),{'q':'vcs_test'})
22 assert 'There is no index to search in. Please run whoosh indexer' in response.body,'No error message about empty index'
23
24 def test_normal_search(self):
13 25 self.log_user()
14 response = self.app.get(url(controller='search', action='index'),{'q':'vcs_test'})
15 assert 'There is no index to search in. Please run whoosh indexer' in response.body,'No error message about empty index' No newline at end of file
26 response = self.app.get(url(controller='search', action='index'),{'q':'def+repo'})
27 print response.body
28 assert '9 results' in response.body,'no message about proper search results'
29
@@ -1,44 +1,47
1 1 """Setup the pylons_app application"""
2 2
3 3 from os.path import dirname as dn, join as jn
4 4 from pylons_app.config.environment import load_environment
5 5 from pylons_app.lib.db_manage import DbManage
6 6 import datetime
7 7 from time import mktime
8 8 import logging
9 9 import os
10 10 import sys
11 import shutil
11 import tarfile
12
12 13 log = logging.getLogger(__name__)
13 14
14 15 ROOT = dn(dn(os.path.realpath(__file__)))
15 16 sys.path.append(ROOT)
16 17
17 18 def setup_app(command, conf, vars):
18 19 """Place any commands to setup pylons_app here"""
19 20 log_sql = True
20 21 tests = False
21 22
22 23 dbname = os.path.split(conf['sqlalchemy.db1.url'])[-1]
23 24 filename = os.path.split(conf.filename)[-1]
24 25
25 26 if filename == 'tests.ini':
26 27 uniq_suffix = str(int(mktime(datetime.datetime.now().timetuple())))
27 28 REPO_TEST_PATH = '/tmp/hg_app_test_%s' % uniq_suffix
28 29
29 30 if not os.path.isdir(REPO_TEST_PATH):
30 31 os.mkdir(REPO_TEST_PATH)
31 from_ = '/home/marcink/workspace-python/vcs'
32 shutil.copytree(from_, os.path.join(REPO_TEST_PATH,'vcs_test'))
32 cur_dir = dn(os.path.abspath(__file__))
33 tar = tarfile.open(jn(cur_dir,'tests',"vcs_test.tar.gz"))
34 tar.extractall(REPO_TEST_PATH)
35 tar.close()
33 36
34 37 tests = True
35 38
36 39 dbmanage = DbManage(log_sql, dbname, tests)
37 40 dbmanage.create_tables(override=True)
38 41 dbmanage.config_prompt(REPO_TEST_PATH)
39 42 dbmanage.create_default_user()
40 43 dbmanage.admin_prompt()
41 44 dbmanage.create_permissions()
42 45 dbmanage.populate_default_permissions()
43 46 load_environment(conf.global_conf, conf.local_conf, initial=True)
44 47
General Comments 0
You need to be logged in to leave comments. Login now