You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2015/04/15 22:03:47 UTC

[1/9] allura git commit: Make svn changed paths order deterministic

Repository: allura
Updated Branches:
  refs/heads/db/7870 b4f7cabc7 -> e70acd57c (forced update)


Make svn changed paths order deterministic


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/747cad09
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/747cad09
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/747cad09

Branch: refs/heads/db/7870
Commit: 747cad09101ce4b92622a042ead4c1727b4170cd
Parents: 33dcb08
Author: Igor Bondarenko <je...@gmail.com>
Authored: Thu Apr 9 18:49:05 2015 +0300
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Thu Apr 9 18:49:05 2015 +0300

----------------------------------------------------------------------
 ForgeSVN/forgesvn/model/svn.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/747cad09/ForgeSVN/forgesvn/model/svn.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index cf70b7d..4594a2f 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -22,6 +22,7 @@ import string
 import logging
 import subprocess
 import time
+import operator as op
 from subprocess import Popen, PIPE
 from hashlib import sha1
 from cStringIO import StringIO
@@ -801,7 +802,7 @@ class SVNImplementation(M.RepositoryImplementation):
             return result
         if len(log_info) == 0:
             return result
-        paths = log_info[0].changed_paths
+        paths = sorted(log_info[0].changed_paths, key=op.itemgetter('path'))
         result['total'] = len(paths)
         for p in paths[start:end]:
             if p['copyfrom_path'] is not None:


[9/9] allura git commit: [#7870] Make test.ini inherit from development.ini, update tests. And:

Posted by br...@apache.org.
[#7870] Make test.ini inherit from development.ini, update tests.  And:

* specify only the settings needed in test.ini
* remove tool_test section from development.ini (part of test.ini)
* remove unnecessary entry points


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e70acd57
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e70acd57
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e70acd57

Branch: refs/heads/db/7870
Commit: e70acd57cec5abb24cd82bf08b5026e48deeb2a6
Parents: 1cc9b76
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Apr 9 18:34:47 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Apr 15 16:03:17 2015 -0400

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_auth.py     |   4 +-
 .../tests/functional/test_neighborhood.py       |   2 +-
 .../tests/functional/test_user_profile.py       |   4 +-
 Allura/allura/tests/test_globals.py             |   2 +-
 Allura/allura/tests/unit/test_app.py            |   4 +-
 .../tests/unit/test_ldap_auth_provider.py       |  10 +-
 Allura/allura/websetup/bootstrap.py             |   1 -
 Allura/development.ini                          |  87 ++++-----
 Allura/setup.py                                 |  12 +-
 Allura/test.ini                                 | 181 ++++++-------------
 .../forgegit/tests/model/test_repository.py     |   6 +-
 .../forgesvn/tests/model/test_repository.py     |   8 +-
 .../forgetracker/tests/functional/test_root.py  |   2 +-
 .../tests/unit/test_root_controller.py          |   9 +-
 14 files changed, 125 insertions(+), 207 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index f288b0b..0f9a8ee 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -771,8 +771,8 @@ class TestAuth(TestController):
         r = self.app.get('/auth/logout')
         r = self.app.post('/auth/do_login', params=dict(
             username='test-user', password='foo',
-            return_to='https://localhost/foo'))
-        assert_equal(r.location, 'https://localhost/foo')
+            return_to='http://localhost:8080/foo'))
+        assert_equal(r.location, 'http://localhost:8080/foo')
 
         r = self.app.get('/auth/logout')
         r = self.app.post('/auth/do_login', params=dict(

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/functional/test_neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 332a60b..afe4dc6 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -281,7 +281,7 @@ class TestNeighborhood(TestController):
                           extra_environ=dict(username='root'))
         r = self.app.get('/adobe/adobe-1/admin/overview',
                          extra_environ=dict(username='root'))
-        assert "_add_tracking('nbhd', 'U-123456');" in r
+        assert "_add_tracking('nbhd', 'U-123456');" in r, r
         assert "_add_tracking('proj', 'U-654321');" in r
         # analytics not allowed
         neighborhood = M.Neighborhood.query.get(name='Adobe')

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/functional/test_user_profile.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_user_profile.py b/Allura/allura/tests/functional/test_user_profile.py
index a3ea741..c539baf 100644
--- a/Allura/allura/tests/functional/test_user_profile.py
+++ b/Allura/allura/tests/functional/test_user_profile.py
@@ -80,7 +80,7 @@ class TestUserProfile(TestController):
 
         sendsimplemail.post.assert_called_once_with(
             cc=User.by_username('test-admin').get_pref('email_address'),
-            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
+            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost:8080/u/test-admin/profile/send_message\n',
             toaddr=User.by_username('test-user').get_pref('email_address'),
             fromaddr=User.by_username('test-admin').get_pref('email_address'),
             reply_to=User.by_username('test-admin').get_pref('email_address'),
@@ -93,7 +93,7 @@ class TestUserProfile(TestController):
 
         sendsimplemail.post.assert_called_once_with(
             cc=None,
-            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost/u/test-admin/profile/send_message\n',
+            text=u'test message\n\n---\n\nThis message was sent to you via the Allura web mail form.  You may reply to this message directly, or send a message to Test Admin at http://localhost:8080/u/test-admin/profile/send_message\n',
             toaddr=User.by_username('test-user').get_pref('email_address'),
             fromaddr=User.by_username('test-admin').get_pref('email_address'),
             reply_to=User.by_username('test-admin').get_pref('email_address'),

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/test_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_globals.py b/Allura/allura/tests/test_globals.py
index 6920f6d..ca04652 100644
--- a/Allura/allura/tests/test_globals.py
+++ b/Allura/allura/tests/test_globals.py
@@ -430,7 +430,7 @@ Some text in a regular paragraph
     for i in range(10):
         print i
 ''')
-    assert 'http://localhost/' in g.forge_markdown(email=True).convert('[Home]')
+    assert_in('http://localhost:8080/', g.forge_markdown(email=True).convert('[Home]'))
     assert 'class="codehilite"' in g.markdown.convert('''
 ~~~~
 def foo(): pass

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/unit/test_app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 95c56c5..eca1ae7 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -17,6 +17,8 @@
 
 from unittest import TestCase
 
+from nose.tools import assert_equal
+
 from allura.app import Application
 from allura import model
 from allura.tests.unit import WithDatabase
@@ -100,7 +102,7 @@ class TestAppDefaults(WithDatabase):
 
     def test_email_address(self):
         self.app.url = '/p/project/mount-point/'
-        assert self.app.email_address == 'mount-point@project.p.in.localhost'
+        assert_equal(self.app.email_address, 'mount-point@project.p.in.localhost')
 
 
 def install_app():

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/tests/unit/test_ldap_auth_provider.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_ldap_auth_provider.py b/Allura/allura/tests/unit/test_ldap_auth_provider.py
index 1dc4bf3..7d7f5b5 100644
--- a/Allura/allura/tests/unit/test_ldap_auth_provider.py
+++ b/Allura/allura/tests/unit/test_ldap_auth_provider.py
@@ -53,7 +53,7 @@ class TestLdapAuthenticationProvider(object):
         self.provider._encode_password = Mock(return_value='new-pass-hash')
         ldap.dn.escape_dn_chars = lambda x: x
 
-        dn = 'uid=%s,ou=users,dc=sf,dc=net' % user.username
+        dn = 'uid=%s,ou=people,dc=localdomain' % user.username
         self.provider.set_password(user, 'old-pass', 'new-pass')
         ldap.initialize.assert_called_once_with('ldaps://localhost/')
         connection = ldap.initialize.return_value
@@ -74,7 +74,7 @@ class TestLdapAuthenticationProvider(object):
 
         self.provider._login()
 
-        dn = 'uid=%s,ou=users,dc=sf,dc=net' % params['username']
+        dn = 'uid=%s,ou=people,dc=localdomain' % params['username']
         ldap.initialize.assert_called_once_with('ldaps://localhost/')
         connection = ldap.initialize.return_value
         connection.bind_s.called_once_with(dn, 'test-password')
@@ -90,7 +90,7 @@ class TestLdapAuthenticationProvider(object):
         self.provider.request.method = 'POST'
         self.provider.request.body = '&'.join(['%s=%s' % (k,v) for k,v in params.iteritems()])
         ldap.dn.escape_dn_chars = lambda x: x
-        dn = 'uid=%s,ou=users,dc=sf,dc=net' % params['username']
+        dn = 'uid=%s,ou=people,dc=localdomain' % params['username']
         conn = ldap.initialize.return_value
         conn.search_s.return_value = [(dn, {'cn': [u'åℒƒ'.encode('utf-8')]})]
 
@@ -117,11 +117,11 @@ class TestLdapAuthenticationProvider(object):
         ThreadLocalORMSession.flush_all()
         assert_not_equal(M.User.query.get(username=user_doc['username']), None)
 
-        dn = 'uid=%s,ou=users,dc=sf,dc=net' % user_doc['username']
+        dn = 'uid=%s,ou=people,dc=localdomain' % user_doc['username']
         ldap.initialize.assert_called_once_with('ldaps://localhost/')
         connection = ldap.initialize.return_value
         connection.bind_s.called_once_with(
-            'cn=site,ou=admin,dc=sf,dc=net',
+            'cn=admin,dc=localdomain',
             'admin-password')
         connection.add_s.assert_called_once_with(dn, modlist.addModlist.return_value)
         connection.unbind_s.assert_called_once()

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/allura/websetup/bootstrap.py
----------------------------------------------------------------------
diff --git a/Allura/allura/websetup/bootstrap.py b/Allura/allura/websetup/bootstrap.py
index bb89995..ed76c15 100644
--- a/Allura/allura/websetup/bootstrap.py
+++ b/Allura/allura/websetup/bootstrap.py
@@ -90,7 +90,6 @@ def bootstrap(command, conf, vars):
     # Clean up all old stuff
     ThreadLocalORMSession.close_all()
     c.user = c.project = c.app = None
-    database = conf.get('db_prefix', '') + 'project:test'
     wipe_database()
     try:
         g.solr.delete(q='*:*')

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 4a4f18c..b7e0b95 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -28,17 +28,22 @@
 ; More settings should be changed for good performance in a production site (no autoreload, no debugging, etc)
 ;
 ; You may copy this file to make a new configuration file (e.g. production.ini)
-; Just use the new file name instead of development.ini for any paster commands you run.
+; Or inherit from this file by starting your .ini file like this:
+;    [app:main]
+;    use = config:development.ini#main
+; Then just use the new file name instead of development.ini for any paster commands you run.
 
 
-; TODO:
-; remove test config
-; clarify debug settings
-
 [DEFAULT]
+; this section is for a few settings that are shared with error handling middleware
+
+; WARNING: *THE LINE BELOW MUST BE CHANGED ON A PRODUCTION ENVIRONMENT*
+; Debug mode will enable the interactive debugging tool, allowing ANYONE to
+; execute malicious code after an exception is raised.
 debug = true
-; Uncomment and replace with the address which should receive any error reports
+; If you want to receive an email for every unhandled HTTP 500 error, set your email address here:
 ;email_to = you@yourdomain.com
+error_email_from = paste@localhost
 
 ; SMTP settings for outgoing mail
 smtp_tls = false
@@ -49,22 +54,21 @@ smtp_timeout = 10
 smtp_server = localhost
 smtp_port = 8826
 ; Reply-To and From address often used in email notifications:
-forgemail.return_path = noreply@sf.net
+forgemail.return_path = noreply@localhost
 
-error_email_from = paste@localhost
-; Used to uniquify references to static resources, can be a timestamp or any unique value
-; This should be updated each time you deploy (or make significant changes, like new tools, new css)
-build_key=1276635823
 
+;
+; Settings for `paster serve` command
+;
 [server:main]
 use = egg:Paste#http
 host = 0.0.0.0
 port = 8080
 
-[filter-app:profile]
-use=egg:keas.profile#profiler
-next=main
 
+;
+; The main allura settings
+;
 [app:main]
 use = egg:Allura
 full_stack = true
@@ -74,7 +78,13 @@ site_name = Allura
 ; Change these to your website's domain
 domain = localhost
 base_url = http://localhost:8080
+forgemail.url = http://localhost:8080
 
+; Used to uniquify references to static resources, can be a timestamp or any unique value
+; This should be updated each time you deploy (or make significant changes, like new tools, new css)
+build_key=1276635823
+
+; Used by Turbogears / Pylons in some cases.  Not particularly relevant for Allura.
 cache_dir = %(here)s/data
 
 ; Cache Neighborhood objects for N seconds (speeds up requests).
@@ -125,11 +135,12 @@ auth.max_password_len = 30
 
 ; if using LDAP, also run `pip install python-ldap` in your Allura environment
 
-auth.ldap.server = ldap://localhost
+auth.ldap.server = ldaps://localhost/
 auth.ldap.suffix = ou=people,dc=localdomain
 auth.ldap.admin_dn = cn=admin,dc=localdomain
 auth.ldap.admin_password = secret
 auth.ldap.schroot_name = scm
+auth.ldap.use_schroot = false
 auth.ldap.password.algorithm = 6
 auth.ldap.password.rounds = 6000
 auth.ldap.password.salt_len = 16
@@ -187,7 +198,7 @@ webhook.retry = 60 120 240
 ; Option format: webhook.<hook type>.limit,
 ; all '-' in hook type must be changed to '_'
 ; e.g. for repo-push webhook:
-webhook.repo_push.limit = 10
+webhook.repo_push.limit = 30
 ; Limit max number of hooks that can be created for given project/app
 ; Option name format: same as above.
 ; Value format: json dict, where keys are app names (as appears in
@@ -380,9 +391,7 @@ forgemail.host = 0.0.0.0
 forgemail.port = 8825
 ; domain suffix for your mail, change this.  You also need to route *.*.*.forgemail.domain to the above host/port via
 ; your mail and DNS configuration
-forgemail.domain = .in.sf.net
-; probably unused?
-forgemail.url = http://localhost:8080
+forgemail.domain = .in.localhost
 
 ; Specify the number of projects allowed to be created by a user
 ; depending on the age of their user account.
@@ -395,11 +404,6 @@ forgemail.url = http://localhost:8080
 ; set this to "false" if you are deploying to production and want performance improvements
 auto_reload_templates = true
 
-; WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
-; Debug mode will enable the interactive debugging tool, allowing ANYONE to
-; execute malicious code after an exception is raised.
-;set debug = false
-
 ; How frequently users can send messages
 user_message.time_interval = 3600
 user_message.max_messages = 20
@@ -457,43 +461,30 @@ short_url.url_pattern = {base_url}/{nbhd}/{project}/{mount_point}/{short_name}
 userstats.count_lines_of_code = true
 
 
-; Setup for tool testing
-[app:tool_test]
-use = egg:Allura
-override_root=basetest_project_root ; TurboGears will use controllers/basetest_project_root.py as root controller
-full_stack = true
-
-cache_dir = %(here)s/data
-beaker.session.key = allura
-beaker.session.type = cookie
-beaker.session.validate_key = 714bfe3612c42390726f
-
-; Ming setup
-ming.main.uri = mongo://127.0.0.1:27017/allura:test
-
-; Forgemail server
-forgemail.host = 0.0.0.0
-forgemail.port = 8825
-forgemail.domain = .in.sf.net
-forgemail.return_path = noreply@sourceforge.net
-forgemail.url = http://localhost:8080
+;
+; Optional settings for profiling with https://pypi.python.org/pypi/keas.profile
+;
+[filter-app:profile]
+use=egg:keas.profile#profiler
+next=main
 
-auth.method = local
-registration.method = local
 
+;
 ; setup for the taskd background daemon request controller
+;
 [app:task]
 use = main
 override_root = task ; TurboGears will use controllers/task.py as root controller
 
 
 
-
+;
 ; Logging configuration
+;
 ; Add additional loggers, handlers, formatters here
 ; Uses python's logging config file format
 ; http://docs.python.org/lib/logging-config-fileformat.html
-
+;
 [loggers]
 keys = root, allura, sqlalchemy, paste, pylons, taskdstatus, timermiddleware, tmw_details
 

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/setup.py
----------------------------------------------------------------------
diff --git a/Allura/setup.py b/Allura/setup.py
index e44c0c2..f2213b3 100644
--- a/Allura/setup.py
+++ b/Allura/setup.py
@@ -90,16 +90,10 @@ setup(
         ('templates/**.html', 'genshi', None),
         ('public/**', 'ignore', None)]},
 
+    # These entry points define what tools and plugins are available for Allura.
+    # Other packages (the Forge* directories) or 3rd-party can add more too.
+    # development.ini is used for many cases to specify which to actually use.
     entry_points="""
-    [paste.app_factory]
-    main = allura.config.middleware:make_app
-    task = allura.config.middleware:make_task_app
-    tool_test = allura.config.middleware:make_tool_test_app
-
-    [paste.app_install]
-    main = pylons.util:PylonsInstaller
-    tool_test = pylons.util:PylonsInstaller
-
     [allura]
     profile = allura.ext.user_profile:UserProfileApp
     admin = allura.ext.admin:AdminApp

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/Allura/test.ini
----------------------------------------------------------------------
diff --git a/Allura/test.ini b/Allura/test.ini
index ecf1639..a3bb23e 100644
--- a/Allura/test.ini
+++ b/Allura/test.ini
@@ -1,168 +1,95 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you 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.
-#
-# allura - TurboGears 2 testing environment configuration
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-[DEFAULT]
-debug = false
-# make sure, since this extends development.ini
-set debug = false
-# Uncomment and replace with the address which should receive any error reports
-# email_to = you@yourdomain.com
-smtp_server = localhost
-error_email_from = paste@localhost
-
-[server:main]
-use = egg:Paste#http
-host = 0.0.0.0
-port = 5000
+;       Licensed to the Apache Software Foundation (ASF) under one
+;       or more contributor license agreements.  See the NOTICE file
+;       distributed with this work for additional information
+;       regarding copyright ownership.  The ASF licenses this file
+;       to you 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.
+;
+; Allura - testing configuration
+;
+;
+
+;
+; This inherits all the settings from development.ini
+; and then overrides only settings needed for tests to work.
+;
 
 [app:main]
-use = config:development.ini#tool_test
-db_prefix = test_
+use = config:development.ini#main
+override_root=basetest_project_root ; TurboGears will use controllers/basetest_project_root.py as root controller
 disable_template_overrides = True
 
-site_name = Allura
-base_url = http://localhost
-domain = localhost
-
-mediawikiimporter.db_config_prefix = hostedapps.db.
-mediawikiimporter.attachments_dir_prefix = /nfs/mediawiki-attachments/
-mediawikiimporter.db_name_template = p_%s_mediawiki
-hostedapps.db.host = localhost
-hostedapps.db.port = 3306
-hostedapps.db.user = user
-hostedapps.db.password = password
-
-# Use test MongoDB DB server
-# ming.main.master = mongo://127.0.0.1:27018/allura
+; Use in-memory MongoDB
 ming.main.uri = mim:///allura
 ming.project.uri = mim:///project-data
 ming.task.uri = mim:///task
-
-trovecategories.enableediting = true
-
-# ActivityStream
 activitystream.master = mim://
-activitystream.database = activitystream
-activitystream.activity_collection = activities
-activitystream.node_collection = nodes
-activitystream.timeline_collection = timelines
-activitystream.recording.enabled = true
-activitystream.enabled = true
-
-solr.mock = true
-amqp.mock = true
-smtp.mock = true
 
-# Forgemail server
-forgemail.host = 0.0.0.0
-forgemail.port = 8825
-forgemail.domain = .in.localhost
-forgemail.url = http://localhost:8080
-forgemail.return_path = noreply@localhost
+solr.server =
+smtp.mock = true
 
 load_test_data = true
 cache_test_data = false
 site_admin_project = test
 
-# useful primarily for test suites, where we want to see the error right away
+; useful primarily for test suites, where we want to see the error right away
 monq.raise_errors = true
 
-# Set the locations of some static resources
-#  script_name is the path that is handled by the application
-#  url_base is the prefix that references to the static resources should have
+; Required so that g.production_mode is True, and Google Analytics is included (weird.)
+; may also be useful for other reasons during tests (e.g. not intercepting error handling)
+debug = false
+
+; specify these without any build_key being included
 ew.script_name = /nf/_ew_/
 ew.url_base = /nf/_ew_/
 static.script_name = /nf/_static_/
 static.url_base = /nf/_static_/
 
+; tests check for these values in output
 scm.host.ro.git = git://git.localhost$path
 scm.host.rw.git = ssh://$username@localhost:8022/scm-repo$path
-scm.host.https.git = https://$username@localhost:8022/scm-repo$path
-scm.host.https_anon.git = https://localhost:8022/scm-repo$path
-scm.host.ro.hg = http://hg.localhost$path
-scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
-scm.host.https.hg = https://$username@localhost:8022/scm-repo$path
-scm.host.https_anon.hg = https://localhost:8022/scm-repo$path
 scm.host.ro.svn = http://svn.localhost$path/
 scm.host.rw.svn = svn+ssh://$username@localhost:8022/scm-repo$path/
 scm.host.https.svn = https://$username@localhost:8022/scm-repo$path/
-scm.host.https_anon.svn = https://localhost:8022/scm-repo$path/
-
-scm.clone.git = git clone $source_url $dest_path
-scm.clone.hg = hg clone $source_url $dest_path
-scm.clone.https_anon.svn = svn checkout $source_url $dest_path
-scm.clone.ro.svn = svn checkout $source_url $dest_path
-scm.clone.svn = svn checkout --username=$username $source_url $dest_path
+scm.host.ro.hg = http://hg.localhost$path
+scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
 
 scm.repos.root = /tmp
 scm.repos.tarball.enable = true
 scm.repos.tarball.root = /tmp/tarball
 scm.repos.tarball.url_prefix = file://
 
-bulk_export_path = /tmp/bulk_export/{nbhd}/{project}
+; TODO: make this and tests match development.ini
 bulk_export_filename = {project}.zip
-bulk_export_download_instructions = Sample instructions for {project}
-
-support_tool_choices = wiki tickets discussion
 
-#stats.sample_rate = 0
+; TODO: update tests and let this be true
+solr.use_new_types = false
 
-short_url.url_pattern = {base_url}/{nbhd}/{project}/{mount_point}/{short_name}
+; TODO: update tests and remove this setting override
+auth.require_email_addr = false
 
-# markdown text longer than max length will not be converted to html
-# tests expect max length of 40000
+; markdown text longer than max length will not be converted to html
+; tests expect max length of 40000
 markdown_render_max_length = 40000
 
-user_message.time_interval = 3600
-user_message.max_messages = 200
-
-auth.min_password_len = 6
-auth.max_password_len = 30
-
-# LDAP auth provider
-auth.ldap.server = ldaps://localhost/
-auth.ldap.suffix = ou=users,dc=sf,dc=net
-auth.ldap.admin_dn = cn=site,ou=admin,dc=sf,dc=net
-auth.ldap.admin_password = admin-password
-auth.ldap.use_schroot = False
-auth.ldap.password.algorithm = 6
-auth.ldap.password.rounds = 6000
-auth.ldap.password.salt_len = 16
-user_prefs_storage.ldap.fields.display_name = cn
-
-auth.allow_user_to_disable_account = true
-auth.allow_edit_prefs = true
-
-[app:main_with_amqp]
-use = main
-# Use test RabbitMQ vhost
-amqp.mock = false
-amqp.hostname = localhost
-amqp.port = 5672
-amqp.userid = testuser
-amqp.password = testpw
-amqp.vhost = vhost_testing
-
-
-# Add additional test specific configuration options as necessary.
+; if enabled during tests, TimerMiddleware will end up wrapping requests way too many times instead of just once
+; not necessary anyway
+stats.sample_rate = 0
+
+
+;
+; Logging goes to a test.log file in current directory
+;
 [loggers]
 keys = root, allura
 

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/ForgeGit/forgegit/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeGit/forgegit/tests/model/test_repository.py b/ForgeGit/forgegit/tests/model/test_repository.py
index 3ffb2a2..dbc12b0 100644
--- a/ForgeGit/forgegit/tests/model/test_repository.py
+++ b/ForgeGit/forgegit/tests/model/test_repository.py
@@ -82,6 +82,7 @@ class TestNewGit(unittest.TestCase):
             '1e146e67985dcd71c74de79613719bef7bddca4a/')
         all_cis = list(self.repo.log(self.rev._id, id_only=True))
         assert len(all_cis) == 4
+        c.lcid_cache = {}
         self.rev.tree.ls()
         # print self.rev.tree.readme()
         assert_equal(self.rev.tree.readme(), (
@@ -204,7 +205,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         with open(os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) as f:
             c = f.read()
         self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n', c)
+            'curl -s http://localhost:8080/auth/refresh_repo/p/test/src-git/\n', c)
         self.assertIn('exec $DIR/post-receive-user\n', c)
         shutil.rmtree(dirname)
 
@@ -238,7 +239,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
             with open(os.path.join(g.tmpdir, 'testgit.git/hooks/post-receive')) as f:
                 c = f.read()
             self.assertIn(
-                'curl -s http://localhost/auth/refresh_repo/p/test/src-git/\n', c)
+                'curl -s http://localhost:8080/auth/refresh_repo/p/test/src-git/\n', c)
             self.assertIn('exec $DIR/post-receive-user\n', c)
             shutil.rmtree(dirname)
 
@@ -403,6 +404,7 @@ class TestGitRepo(unittest.TestCase, RepoImplTestBase):
         self.assertEqual(cids[-1], '9a7df788cf800241e3bb5a849c8870f2f8259d98')
 
     def test_ls(self):
+        c.lcid_cache = {}  # else it'll be a mock
         lcd_map = self.repo.commit('HEAD').tree.ls()
         self.assertEqual(lcd_map, [{
             'href': u'README',

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/ForgeSVN/forgesvn/tests/model/test_repository.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/tests/model/test_repository.py b/ForgeSVN/forgesvn/tests/model/test_repository.py
index 92ccaf5..6276df8 100644
--- a/ForgeSVN/forgesvn/tests/model/test_repository.py
+++ b/ForgeSVN/forgesvn/tests/model/test_repository.py
@@ -169,7 +169,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         with open(os.path.join(g.tmpdir, 'testsvn/hooks/post-commit')) as f:
             hook_data = f.read()
         self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src/\n',
+            'curl -s http://localhost:8080/auth/refresh_repo/p/test/src/\n',
             hook_data)
         self.assertIn('exec $DIR/post-commit-user "$@"\n', hook_data)
 
@@ -221,7 +221,7 @@ class TestSVNRepo(unittest.TestCase, RepoImplTestBase):
         with open(os.path.join(g.tmpdir, 'testsvn/hooks/post-commit')) as f:
             c = f.read()
         self.assertIn(
-            'curl -s http://localhost/auth/refresh_repo/p/test/src/\n', c)
+            'curl -s http://localhost:8080/auth/refresh_repo/p/test/src/\n', c)
         self.assertIn('exec $DIR/post-commit-user "$@"\n', c)
 
         repo.refresh(notify=False)
@@ -696,7 +696,7 @@ class TestSVNRev(unittest.TestCase):
         n = M.Notification.query.find(
             dict(subject='[test:src] [r1] - rick446: Create readme')).first()
         assert n
-        assert_equal(n.text, 'Create readme http://localhost/p/test/src/1/')
+        assert_equal(n.text, 'Create readme http://localhost:8080/p/test/src/1/')
 
 
 class _Test(unittest.TestCase):
@@ -890,7 +890,7 @@ class TestRepo(_TestWithRepo):
         notifications = M.Notification.query.find().all()
         for n in notifications:
             if '100 new commits' in n.subject:
-                assert "master,branch:  by %s http://localhost/ci/foo99" % committer_name in n.text
+                assert "master,branch:  by %s http://localhost:8080/ci/foo99" % committer_name in n.text
                 break
         else:
             assert False, 'Did not find notification'

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 0e92b1f..5b0d094 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -2318,7 +2318,7 @@ class TestFunctionalController(TrackerTestController):
             return_path, rcpts, body = _client.sendmail.call_args[0]
             body = body.split('\n')
             assert 'Subject: [test:bugs] #1 test <h2> ticket' in body
-            assert '<p><strong> <a class="alink" href="http://localhost/p/test/bugs/1">[bugs:#1]</a> test &lt;h2&gt; ticket</strong></p>' in body
+            assert_in('<p><strong> <a class="alink" href="http://localhost:8080/p/test/bugs/1">[bugs:#1]</a> test &lt;h2&gt; ticket</strong></p>', body)
 
     @patch('forgetracker.search.query_filter_choices')
     def test_multiselect(self, query_filter_choices):

http://git-wip-us.apache.org/repos/asf/allura/blob/e70acd57/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
index facc28c..ae2f7a1 100644
--- a/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
+++ b/ForgeTracker/forgetracker/tests/unit/test_root_controller.py
@@ -15,16 +15,19 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+import unittest
+
 from mock import Mock, patch
 from ming.orm.ormsession import session
+from pylons import tmpl_context as c
+from nose.tools import assert_equal
 
 from allura.lib import helpers as h
 from allura.model import User
-from pylons import tmpl_context as c
+
 from forgetracker.tests.unit import TrackerTestWithModel
 from forgetracker.model import Ticket
 from forgetracker import tracker_main
-import unittest
 
 
 class WithUserAndBugsApp(TrackerTestWithModel):
@@ -46,7 +49,7 @@ class TestWhenSearchingWithCustomFields(WithUserAndBugsApp):
         expected = [dict(sortable_name='_iteration_number_s',
                          name='_iteration_number',
                          label='Iteration Number')]
-        assert self.response['sortable_custom_fields'] == expected
+        assert_equal(self.response['sortable_custom_fields'], expected)
 
     def test_that_tickets_are_listed(self):
         assert self.response['tickets'][0].summary == 'colors are wrong'


[3/9] allura git commit: [#7864] handle multiple pages of Google Code comments

Posted by br...@apache.org.
[#7864] handle multiple pages of Google Code comments

The new test .html files are based off of the existing test-issue.html and are very similar.

Some tests were moved around to accomodate different test setup for those using iter_comments and
affected by the changes.


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/225dc73c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/225dc73c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/225dc73c

Branch: refs/heads/db/7870
Commit: 225dc73c51dce1de27de0514cf58f222d3f1a351
Parents: 747cad0
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Apr 7 10:22:46 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Apr 15 11:04:02 2015 +0000

----------------------------------------------------------------------
 .../forgeimporters/google/__init__.py           |  30 +-
 .../data/google/test-issue-first-page.html      | 548 +++++++++++++++++++
 .../tests/data/google/test-issue-prev-page.html | 431 +++++++++++++++
 .../tests/data/google/test-issue.html           |   7 +
 .../tests/google/functional/test_tracker.py     |   7 +-
 .../tests/google/test_extractor.py              | 207 ++++---
 6 files changed, 1148 insertions(+), 82 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/google/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/google/__init__.py b/ForgeImporters/forgeimporters/google/__init__.py
index b848151..302544e 100644
--- a/ForgeImporters/forgeimporters/google/__init__.py
+++ b/ForgeImporters/forgeimporters/google/__init__.py
@@ -304,9 +304,9 @@ class GoogleCodeProjectExtractor(ProjectExtractor):
         return self.page.find(id='hc0').find('span', 'date').get('title')
 
     def get_issue_mod_date(self):
-        comments = self.page.findAll('div', 'issuecomment')
+        comments = list(self.iter_comments())
         if comments:
-            last_update = Comment(comments[-1], self.project_name)
+            last_update = comments[-1]
             return last_update.created_date
         else:
             return self.get_issue_created_date()
@@ -346,8 +346,30 @@ class GoogleCodeProjectExtractor(ProjectExtractor):
         return 0
 
     def iter_comments(self):
-        for comment in self.page.findAll('div', 'issuecomment'):
-            yield Comment(comment, self.project_name)
+        # first, get all pages if there are multiple pages of comments
+        looking_for_comment_pages = True
+        comment_page_urls = [self.url]
+        while looking_for_comment_pages:
+            first_comment = self.page.find('div', 'vt issuecomment')
+            looking_for_comment_pages = False
+            if first_comment and 'cursor_off' not in first_comment['class']:
+                # this is not a real comment, just forward/back links
+                for link in first_comment.findAll('a'):
+                    if link.text.startswith('Older'):
+                        prev_comments_page = urljoin(self.url, link['href'])
+                        comment_page_urls.insert(0, prev_comments_page)
+                        looking_for_comment_pages = True
+                        self.get_page(prev_comments_page)  # prep for next iteration of loop
+
+        # then go through those to get the actual comments
+        for comment_page_url in comment_page_urls:
+            self.get_page(comment_page_url)
+            # regular comments have cursor_off class
+            for comment in self.page.findAll('div', 'cursor_off vt issuecomment'):
+                yield Comment(comment, self.project_name)
+
+
+
 
 
 class UserLink(object):

http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/tests/data/google/test-issue-first-page.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/test-issue-first-page.html b/ForgeImporters/forgeimporters/tests/data/google/test-issue-first-page.html
new file mode 100644
index 0000000..4fc25eb
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/data/google/test-issue-first-page.html
@@ -0,0 +1,548 @@
+<!DOCTYPE html>
+<!--
+
+An issue with a link to another page of comments (google paginates after 500 comments, we simulate with less)
+test-issue-prev-page.html is the test file for that other page of comments
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+<meta name="ROBOTS" content="NOARCHIVE" />
+<link rel="icon" type="image/vnd.microsoft.icon" href="http://www.gstatic.com/codesite/ph/images/phosting.ico" />
+<script type="text/javascript">
+
+
+
+
+ var codesite_token = null;
+
+
+ var CS_env = {"loggedInUserEmail":null,"relativeBaseUrl":"","projectHomeUrl":"/p/allura-google-importer","assetVersionPath":"http://www.gstatic.com/codesite/ph/3783617020303179221","assetHostPath":"http://www.gstatic.com/codesite/ph","domainName":null,"projectName":"allura-google-importer","token":null,"profileUrl":null};
+ var _gaq = _gaq || [];
+ _gaq.push(
+ ['siteTracker._setAccount', 'UA-18071-1'],
+ ['siteTracker._trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
+ })();
+
+ </script>
+<title>Issue 6 -
+ allura-google-importer -
+
+ Test Issue -
+ Import Google Code projects to an Allura forge - Google Project Hosting
+ </title>
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/core.css" />
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/ph_detail.css" />
+<!--[if IE]>
+ <link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/d_ie.css" >
+<![endif]-->
+<style type="text/css">
+ .menuIcon.off { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -42px }
+ .menuIcon.on { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -28px }
+ .menuIcon.down { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 0; }
+
+
+ .attachments { width:33%; border-top:2px solid #999; padding-top: 3px; margin-left: .7em;}
+ .attachments table { margin-bottom: 0.75em; }
+ .attachments table tr td { padding: 0; margin: 0; font-size: 95%; }
+ .preview { border: 2px solid #c3d9ff; padding: 1px; }
+ .preview:hover { border: 2px solid blue; }
+ .label { white-space: nowrap; }
+ .derived { font-style:italic }
+ .cursor_on .author {
+ background: url(http://www.gstatic.com/codesite/ph/images/show-arrow.gif) no-repeat 2px;
+ }
+ .hiddenform {
+ display: none;
+ }
+
+
+ </style>
+</head>
+<body class="t3">
+<script type="text/javascript">
+ window.___gcfg = {lang: 'en'};
+ (function()
+ {var po = document.createElement("script");
+ po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(po, s);
+ })();
+</script>
+<div class="headbg">
+<div id="gaia">
+<span>
+<a href="#" id="projects-dropdown" onclick="return false;"><u>My favorites</u> <small>&#9660;</small></a>
+ | <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6" onclick="_CS_click('/gb/ph/signin');"><u>Sign in</u></a>
+</span>
+</div>
+<div class="gbh" style="left: 0pt;"></div>
+<div class="gbh" style="right: 0pt;"></div>
+<div style="height: 1px"></div>
+<!--[if lte IE 7]>
+<div style="text-align:center;">
+Your version of Internet Explorer is not supported. Try a browser that
+contributes to open source, such as <a href="http://www.firefox.com">Firefox</a>,
+<a href="http://www.google.com/chrome">Google Chrome</a>, or
+<a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame</a>.
+</div>
+<![endif]-->
+<table style="padding:0px; margin: 0px 0px 10px 0px; width:100%" cellpadding="0" cellspacing="0" itemscope="itemscope" itemtype="http://schema.org/CreativeWork">
+<tr style="height: 58px;">
+<td id="plogo">
+<link itemprop="url" href="/p/allura-google-importer" />
+<a href="/p/allura-google-importer/">
+<img src="/p/allura-google-importer/logo?cct=1374769571" alt="Logo" itemprop="image" />
+</a>
+</td>
+<td style="padding-left: 0.5em">
+<div id="pname">
+<a href="/p/allura-google-importer/"><span itemprop="name">allura-google-importer</span></a>
+</div>
+<div id="psum">
+<a id="project_summary_link" href="/p/allura-google-importer/"><span itemprop="description">Import Google Code projects to an Allura forge</span></a>
+</div>
+</td>
+<td style="white-space:nowrap;text-align:right; vertical-align:bottom;">
+<form action="/hosting/search">
+<input size="30" name="q" value="" type="text" />
+<input type="submit" name="projectsearch" value="Search projects" />
+</form>
+</td></tr>
+</table>
+</div>
+<div id="mt" class="gtb">
+<a href="/p/allura-google-importer/" class="tab ">Project&nbsp;Home</a>
+<a href="/p/allura-google-importer/wiki/TestPage?tm=6" class="tab ">Wiki</a>
+<a href="/p/allura-google-importer/issues/list" class="tab active">Issues</a>
+<a href="/p/allura-google-importer/source/checkout" class="tab ">Source</a>
+<div class="gtbc"></div>
+</div>
+<table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st">
+<tr>
+<td class="subt">
+<div class="issueDetail">
+<div class="isf">
+<span class="inIssueEntry">
+<a class="buttonify" href="entry" onclick="return _newIssuePrompt();">New issue</a>
+</span> &nbsp;
+
+ <span class="inIssueList">
+<span>Search</span>
+</span><form action="list" method="GET" style="display:inline">
+<select id="can" name="can">
+<option disabled="disabled">Search within:</option>
+<option value="1">&nbsp;All issues</option>
+<option value="2" selected="selected">&nbsp;Open issues</option>
+<option value="6">&nbsp;New issues</option>
+<option value="7">&nbsp;Issues to verify</option>
+</select>
+<span>for</span>
+<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" onkeydown="_blurOnEsc(event)" /></span>
+<span id="search_colspec"><input type="hidden" name="colspec" value="ID Type Status Priority Milestone Owner Summary" /></span>
+<input type="hidden" name="cells" value="tiles" />
+<input type="submit" value="Search" />
+</form>
+ &nbsp;
+ <span class="inIssueAdvSearch">
+<a href="advsearch">Advanced search</a>
+</span> &nbsp;
+ <span class="inIssueSearchTips">
+<a href="searchtips">Search tips</a>
+</span> &nbsp;
+ <span class="inIssueSubscriptions">
+<a href="/p/allura-google-importer/issues/subscriptions">Subscriptions</a>
+</span>
+</div>
+</div>
+</td>
+<td align="right" valign="top" class="bevel-right"></td>
+</tr>
+</table>
+<script type="text/javascript">
+ var cancelBubble = false;
+ function _go(url) { document.location = url; }
+</script>
+<div id="maincol">
+<div id="color_control" class="">
+<div id="issueheader">
+<table cellpadding="0" cellspacing="0" width="100%"><tbody>
+<tr>
+<td class="vt h3" nowrap="nowrap" style="padding:0 5px">
+
+
+ Issue <a href="detail?id=6">6</a>:
+ </td>
+<td width="90%" class="vt">
+<span class="h3">Test &quot;Issue&quot;</span>
+</td>
+<td>
+<div class="pagination">
+<a href="../../allura-google-importer/issues/detail?id=5" title="Prev">&lsaquo; Prev</a>
+ 6 of 6
+
+ </div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td nowrap="nowrap">
+
+
+ 1 person starred this issue and may be notified of changes.
+
+
+
+ </td>
+<td align="center" nowrap="nowrap">
+<a href="http://code.google.com/p/allura-google-importer/issues/list?cursor=allura-google-importer%3A6">Back to list</a>
+</td>
+</tr>
+</tbody></table>
+</div>
+<table width="100%" cellpadding="0" cellspacing="0" border="0" class="issuepage" id="meta-container">
+<tbody class="collapse">
+<tr>
+<td id="issuemeta">
+<div id="meta-float">
+<table cellspacing="0" cellpadding="0">
+<tr><th align="left">Status:&nbsp;</th>
+<td width="100%">
+<span title="Work on this issue has begun">Started</span>
+</td>
+</tr>
+<tr><th align="left">Owner:&nbsp;</th><td>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>
+</td>
+</tr>
+<tr><td colspan="2">
+<div style="padding-top:2px">
+<a href="list?q=label:Type-Defect" title="Report of a software defect" class="label"><b>Type-</b>Defect</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Priority-Medium" title="Normal priority" class="label"><b>Priority-</b>Medium</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Milestone-Release1.0" title="All essential functionality working" class="label"><b>Milestone-</b>Release1.0</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-All" title="Affects all operating systems" class="label"><b>OpSys-</b>All</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Component-Logic" title="Issue relates to application logic" class="label"><b>Component-</b>Logic</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Performance" title="Performance issue" class="label">Performance</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Security" title="Security risk to users" class="label">Security</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-Windows" title="Affects Windows users" class="label"><b>OpSys-</b>Windows</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-OSX" title="Affects Mac OS X users" class="label"><b>OpSys-</b>OSX</a>
+</div>
+</td></tr>
+</table>
+<div class="rel_issues">
+</div>
+<br /><br />
+<div style="white-space:nowrap"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment</div>
+</div>&nbsp;
+ </td>
+<td class="vt issuedescription" width="100%" id="cursorarea">
+<div class="cursor_off vt issuedescription" id="hc0">
+<div class="author">
+<span class="role_label">Project Member</span>
+ Reported by
+
+
+ <a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>,
+ <span class="date" title="Thu Aug  8 15:33:52 2013">Today (3 minutes ago)</span>
+</div>
+<pre>
+Test *Issue* for testing
+
+  1. Test List
+  2. Item
+
+**Testing**
+
+ * Test list 2
+ * Item
+
+# Test Section
+
+    p = source.test_issue.post()
+    p.count = p.count *5 #* 6
+    if p.count &gt; 5:
+        print "Not &lt; 5 &amp; != 5"
+
+References: <a href="/p/allura-google-importer/issues/detail?id=1">issue 1</a>, <a href="/p/allura-google-importer/source/detail?r=2">r2</a>
+
+That's all
+
+
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at1.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=7&amp;aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b></b>
+<br />
+ 0 bytes
+
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+</div>
+</div>
+
+ <div class="vt issuecomment" width="100%" style="background:#e5ecf9; padding:2px .7em; margin:0; border:0">
+Showing comments 3 - 6
+of 6
+ &nbsp; <a href="detail?id=1769&amp;cnum=500&amp;cstart=2">Older <b>&rsaquo;</b></a>
+ </div>
+
+<div class="cursor_off vt issuecomment" id="hc1">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:35:15 2013">
+ Today (2 minutes ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c1" href="/p/allura-google-importer/issues/detail?id=6#c1">#1</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Test *comment* is a comment
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60001000&amp;name=&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at2.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60001000&amp;name=at2.txt&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60001000&amp;name=at2.txt&amp;token=JOSo4duwaN2FCKZrwYOQ-nx9r7U%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+</div>
+<div class="updates">
+<div class="round4"></div>
+<div class="round2"></div>
+<div class="round1"></div>
+<div class="box-inner">
+<b>Status:</b>
+ Started
+
+ <br />
+<b>Labels:</b>
+ -OpSys-Linux OpSys-Windows
+
+ <br />
+</div>
+<div class="round1"></div>
+<div class="round2"></div>
+<div class="round4"></div>
+</div>
+</div>
+<div class="cursor_off vt issuecomment" id="hc2">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:35:34 2013">
+ Today (1 minute ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c2" href="/p/allura-google-importer/issues/detail?id=6#c2">#2</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Another comment with references: <a href="/p/allura-google-importer/issues/detail?id=2">issue 2</a>, <a href="/p/allura-google-importer/source/detail?r=1">r1</a>
+</pre>
+</div>
+<div class="cursor_off vt issuecomment" id="hc3">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:36:39 2013">
+ Today (moments ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c3" href="/p/allura-google-importer/issues/detail?id=6#c3">#3</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Last comment
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at4.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003000&amp;name=at4.txt&amp;token=6Ny2zYHmV6b82dqxyoiH6HUYoC4%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at1.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=6&amp;aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=60003001&amp;name=at1.txt&amp;token=NS8aMvWsKzTAPuY2kniJG5aLzPg%3A1376001446667">Download</a>
+</td>
+</tr>
+</table>
+</div>
+</div>
+<div class="cursor_off vt issuecomment" id="hc4">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:36:57 2013">
+ Today (moments ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c4" href="/p/allura-google-importer/issues/detail?id=6#c4">#4</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Oh, I forgot one (with an inter-project reference to <a href="/p/other-project/issues/detail?id=1">issue other-project:1</a>)
+</pre>
+<div class="updates">
+<div class="round4"></div>
+<div class="round2"></div>
+<div class="round1"></div>
+<div class="box-inner">
+<b>Labels:</b>
+ OpSys-OSX
+
+ <br />
+</div>
+<div class="round1"></div>
+<div class="round2"></div>
+<div class="round4"></div>
+</div>
+</div>
+
+<div class="vt issuecomment" width="100%" style="background:#e5ecf9; padding:2px .7em; margin:0">
+Showing comments 3 - 6
+of 6
+ &nbsp; <a href="detail?id=1769&amp;cnum=500&amp;cstart=2">Older <b>&rsaquo;</b></a>
+</div>
+
+</td>
+</tr>
+<tr>
+<td></td>
+<td class="vt issuecomment">
+<span class="indicator">&#9658;</span> <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment
+ </td>
+</tr>
+</tbody>
+</table>
+<br />
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/dit_scripts.js"></script>
+</div>
+<form name="delcom" action="delComment.do?q=&amp;can=2&amp;groupby=&amp;sort=&amp;colspec=ID+Type+Status+Priority+Milestone+Owner+Summary" method="POST">
+<input type="hidden" name="sequence_num" value="" />
+<input type="hidden" name="mode" value="" />
+<input type="hidden" name="id" value="6" />
+<input type="hidden" name="token" value="" />
+</form>
+<div id="helparea"></div>
+<script type="text/javascript">
+ _onload();
+ function delComment(sequence_num, delete_mode) {
+ var f = document.forms["delcom"];
+ f.sequence_num.value = sequence_num;
+ f.mode.value = delete_mode;
+
+ f.submit();
+ return false;
+ }
+
+ _floatMetadata();
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/kibbles.js"></script>
+<script type="text/javascript">
+ _setupKibblesOnDetailPage(
+ 'http://code.google.com/p/allura-google-importer/issues/list?cursor\x3dallura-google-importer%3A6',
+ '/p/allura-google-importer/issues/entry',
+ '../../allura-google-importer/issues/detail?id\x3d5',
+ '',
+ '', 'allura-google-importer', 6,
+ false, false, codesite_token);
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/ph_core.js"></script>
+</div>
+<div id="footer" dir="ltr">
+<div class="text">
+<a href="/projecthosting/terms.html">Terms</a> -
+ <a href="http://www.google.com/privacy.html">Privacy</a> -
+ <a href="/p/support/">Project Hosting Help</a>
+</div>
+</div>
+<div class="hostedBy" style="margin-top: -20px;">
+<span style="vertical-align: top;">Powered by <a href="http://code.google.com/projecthosting/">Google Project Hosting</a></span>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/tests/data/google/test-issue-prev-page.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/test-issue-prev-page.html b/ForgeImporters/forgeimporters/tests/data/google/test-issue-prev-page.html
new file mode 100644
index 0000000..62a3b23
--- /dev/null
+++ b/ForgeImporters/forgeimporters/tests/data/google/test-issue-prev-page.html
@@ -0,0 +1,431 @@
+<!DOCTYPE html>
+<!--
+
+This is the second page of previous comments, that goes with test-issue-first-page.html
+
+-->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+<meta name="ROBOTS" content="NOARCHIVE" />
+<link rel="icon" type="image/vnd.microsoft.icon" href="http://www.gstatic.com/codesite/ph/images/phosting.ico" />
+<script type="text/javascript">
+
+
+
+
+ var codesite_token = null;
+
+
+ var CS_env = {"loggedInUserEmail":null,"relativeBaseUrl":"","projectHomeUrl":"/p/allura-google-importer","assetVersionPath":"http://www.gstatic.com/codesite/ph/3783617020303179221","assetHostPath":"http://www.gstatic.com/codesite/ph","domainName":null,"projectName":"allura-google-importer","token":null,"profileUrl":null};
+ var _gaq = _gaq || [];
+ _gaq.push(
+ ['siteTracker._setAccount', 'UA-18071-1'],
+ ['siteTracker._trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
+ })();
+
+ </script>
+<title>Issue 6 -
+ allura-google-importer -
+
+ Test Issue -
+ Import Google Code projects to an Allura forge - Google Project Hosting
+ </title>
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/core.css" />
+<link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/ph_detail.css" />
+<!--[if IE]>
+ <link type="text/css" rel="stylesheet" href="http://www.gstatic.com/codesite/ph/3783617020303179221/css/d_ie.css" >
+<![endif]-->
+<style type="text/css">
+ .menuIcon.off { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -42px }
+ .menuIcon.on { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 -28px }
+ .menuIcon.down { background: no-repeat url(http://www.gstatic.com/codesite/ph/images/dropdown_sprite.gif) 0 0; }
+
+
+ .attachments { width:33%; border-top:2px solid #999; padding-top: 3px; margin-left: .7em;}
+ .attachments table { margin-bottom: 0.75em; }
+ .attachments table tr td { padding: 0; margin: 0; font-size: 95%; }
+ .preview { border: 2px solid #c3d9ff; padding: 1px; }
+ .preview:hover { border: 2px solid blue; }
+ .label { white-space: nowrap; }
+ .derived { font-style:italic }
+ .cursor_on .author {
+ background: url(http://www.gstatic.com/codesite/ph/images/show-arrow.gif) no-repeat 2px;
+ }
+ .hiddenform {
+ display: none;
+ }
+
+
+ </style>
+</head>
+<body class="t3">
+<script type="text/javascript">
+ window.___gcfg = {lang: 'en'};
+ (function()
+ {var po = document.createElement("script");
+ po.type = "text/javascript"; po.async = true;po.src = "https://apis.google.com/js/plusone.js";
+ var s = document.getElementsByTagName("script")[0];
+ s.parentNode.insertBefore(po, s);
+ })();
+</script>
+<div class="headbg">
+<div id="gaia">
+<span>
+<a href="#" id="projects-dropdown" onclick="return false;"><u>My favorites</u> <small>&#9660;</small></a>
+ | <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6" onclick="_CS_click('/gb/ph/signin');"><u>Sign in</u></a>
+</span>
+</div>
+<div class="gbh" style="left: 0pt;"></div>
+<div class="gbh" style="right: 0pt;"></div>
+<div style="height: 1px"></div>
+<!--[if lte IE 7]>
+<div style="text-align:center;">
+Your version of Internet Explorer is not supported. Try a browser that
+contributes to open source, such as <a href="http://www.firefox.com">Firefox</a>,
+<a href="http://www.google.com/chrome">Google Chrome</a>, or
+<a href="http://code.google.com/chrome/chromeframe/">Google Chrome Frame</a>.
+</div>
+<![endif]-->
+<table style="padding:0px; margin: 0px 0px 10px 0px; width:100%" cellpadding="0" cellspacing="0" itemscope="itemscope" itemtype="http://schema.org/CreativeWork">
+<tr style="height: 58px;">
+<td id="plogo">
+<link itemprop="url" href="/p/allura-google-importer" />
+<a href="/p/allura-google-importer/">
+<img src="/p/allura-google-importer/logo?cct=1374769571" alt="Logo" itemprop="image" />
+</a>
+</td>
+<td style="padding-left: 0.5em">
+<div id="pname">
+<a href="/p/allura-google-importer/"><span itemprop="name">allura-google-importer</span></a>
+</div>
+<div id="psum">
+<a id="project_summary_link" href="/p/allura-google-importer/"><span itemprop="description">Import Google Code projects to an Allura forge</span></a>
+</div>
+</td>
+<td style="white-space:nowrap;text-align:right; vertical-align:bottom;">
+<form action="/hosting/search">
+<input size="30" name="q" value="" type="text" />
+<input type="submit" name="projectsearch" value="Search projects" />
+</form>
+</td></tr>
+</table>
+</div>
+<div id="mt" class="gtb">
+<a href="/p/allura-google-importer/" class="tab ">Project&nbsp;Home</a>
+<a href="/p/allura-google-importer/wiki/TestPage?tm=6" class="tab ">Wiki</a>
+<a href="/p/allura-google-importer/issues/list" class="tab active">Issues</a>
+<a href="/p/allura-google-importer/source/checkout" class="tab ">Source</a>
+<div class="gtbc"></div>
+</div>
+<table cellspacing="0" cellpadding="0" width="100%" align="center" border="0" class="st">
+<tr>
+<td class="subt">
+<div class="issueDetail">
+<div class="isf">
+<span class="inIssueEntry">
+<a class="buttonify" href="entry" onclick="return _newIssuePrompt();">New issue</a>
+</span> &nbsp;
+
+ <span class="inIssueList">
+<span>Search</span>
+</span><form action="list" method="GET" style="display:inline">
+<select id="can" name="can">
+<option disabled="disabled">Search within:</option>
+<option value="1">&nbsp;All issues</option>
+<option value="2" selected="selected">&nbsp;Open issues</option>
+<option value="6">&nbsp;New issues</option>
+<option value="7">&nbsp;Issues to verify</option>
+</select>
+<span>for</span>
+<span id="qq"><input type="text" size="38" id="searchq" name="q" value="" autocomplete="off" onkeydown="_blurOnEsc(event)" /></span>
+<span id="search_colspec"><input type="hidden" name="colspec" value="ID Type Status Priority Milestone Owner Summary" /></span>
+<input type="hidden" name="cells" value="tiles" />
+<input type="submit" value="Search" />
+</form>
+ &nbsp;
+ <span class="inIssueAdvSearch">
+<a href="advsearch">Advanced search</a>
+</span> &nbsp;
+ <span class="inIssueSearchTips">
+<a href="searchtips">Search tips</a>
+</span> &nbsp;
+ <span class="inIssueSubscriptions">
+<a href="/p/allura-google-importer/issues/subscriptions">Subscriptions</a>
+</span>
+</div>
+</div>
+</td>
+<td align="right" valign="top" class="bevel-right"></td>
+</tr>
+</table>
+<script type="text/javascript">
+ var cancelBubble = false;
+ function _go(url) { document.location = url; }
+</script>
+<div id="maincol">
+<div id="color_control" class="">
+<div id="issueheader">
+<table cellpadding="0" cellspacing="0" width="100%"><tbody>
+<tr>
+<td class="vt h3" nowrap="nowrap" style="padding:0 5px">
+
+
+ Issue <a href="detail?id=6">6</a>:
+ </td>
+<td width="90%" class="vt">
+<span class="h3">Test &quot;Issue&quot;</span>
+</td>
+<td>
+<div class="pagination">
+<a href="../../allura-google-importer/issues/detail?id=5" title="Prev">&lsaquo; Prev</a>
+ 6 of 6
+
+ </div>
+</td>
+</tr>
+<tr>
+<td></td>
+<td nowrap="nowrap">
+
+
+ 1 person starred this issue and may be notified of changes.
+
+
+
+ </td>
+<td align="center" nowrap="nowrap">
+<a href="http://code.google.com/p/allura-google-importer/issues/list?cursor=allura-google-importer%3A6">Back to list</a>
+</td>
+</tr>
+</tbody></table>
+</div>
+<table width="100%" cellpadding="0" cellspacing="0" border="0" class="issuepage" id="meta-container">
+<tbody class="collapse">
+<tr>
+<td id="issuemeta">
+<div id="meta-float">
+<table cellspacing="0" cellpadding="0">
+<tr><th align="left">Status:&nbsp;</th>
+<td width="100%">
+<span title="Work on this issue has begun">Started</span>
+</td>
+</tr>
+<tr><th align="left">Owner:&nbsp;</th><td>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>
+</td>
+</tr>
+<tr><td colspan="2">
+<div style="padding-top:2px">
+<a href="list?q=label:Type-Defect" title="Report of a software defect" class="label"><b>Type-</b>Defect</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Priority-Medium" title="Normal priority" class="label"><b>Priority-</b>Medium</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Milestone-Release1.0" title="All essential functionality working" class="label"><b>Milestone-</b>Release1.0</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-All" title="Affects all operating systems" class="label"><b>OpSys-</b>All</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Component-Logic" title="Issue relates to application logic" class="label"><b>Component-</b>Logic</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Performance" title="Performance issue" class="label">Performance</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:Security" title="Security risk to users" class="label">Security</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-Windows" title="Affects Windows users" class="label"><b>OpSys-</b>Windows</a>
+</div>
+<div style="padding-top:2px">
+<a href="list?q=label:OpSys-OSX" title="Affects Mac OS X users" class="label"><b>OpSys-</b>OSX</a>
+</div>
+</td></tr>
+</table>
+<div class="rel_issues">
+</div>
+<br /><br />
+<div style="white-space:nowrap"><a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment</div>
+</div>&nbsp;
+ </td>
+<td class="vt issuedescription" width="100%" id="cursorarea">
+<div class="cursor_off vt issuedescription" id="hc0">
+<div class="author">
+<span class="role_label">Project Member</span>
+ Reported by
+
+
+ <a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a>,
+ <span class="date" title="Thu Aug  8 15:33:52 2013">Today (3 minutes ago)</span>
+</div>
+<pre>
+Test *Issue* for testing
+
+  1. Test List
+  2. Item
+
+**Testing**
+
+ * Test list 2
+ * Item
+
+# Test Section
+
+    p = source.test_issue.post()
+    p.count = p.count *5 #* 6
+    if p.count &gt; 5:
+        print "Not &lt; 5 &amp; != 5"
+
+References: <a href="/p/allura-google-importer/issues/detail?id=1">issue 1</a>, <a href="/p/allura-google-importer/source/detail?r=2">r2</a>
+
+That's all
+
+
+</pre>
+<div class="attachments">
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b>at1.txt</b>
+<br />
+ 13 bytes
+
+
+ &nbsp; <a href="../../allura-google-importer/issues/attachmentText?id=7&amp;aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255" target="_blank">View</a>
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000000&amp;name=at1.txt&amp;token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+<table cellspacing="3" cellpadding="2" border="0">
+<tr><td width="20">
+<a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">
+<img width="15" height="15" src="http://www.gstatic.com/codesite/ph/images/paperclip.gif" border="0" />
+</a>
+</td>
+<td style="min-width:16em" valign="top">
+<b></b>
+<br />
+ 0 bytes
+
+
+ &nbsp; <a href="//allura-google-importer.googlecode.com/issues/attachment?aid=70000001&amp;name=&amp;token=C9Hn4s1-g38hlSggRGo65VZM1ys%3A1376059941255">Download</a>
+</td>
+</tr>
+</table>
+</div>
+</div>
+
+ <div class="vt issuecomment" width="100%" style="background:#e5ecf9; padding:2px .7em; margin:0; border:0">
+ <a href="detail?id=1769&amp;cnum=500&amp;cstart=502">Newer <b>&rsaquo;</b></a>
+ &nbsp;
+Showing comments 1 - 2
+of 6
+ </div>
+
+<div class="cursor_off vt issuecomment" id="hc1">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:34:01 2013">
+ Today (3 minutes ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c1" href="/p/allura-google-importer/issues/detail?id=6#c1">#1</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Simple comment
+</pre>
+</div>
+<div class="cursor_off vt issuecomment" id="hc2">
+<div style="float:right; margin-right:.3em; text-align:right">
+<span class="date" title="Thu Aug  8 15:34:09 2013">
+ Today (3 minutes ago)
+ </span>
+</div>
+<span class="author">
+<span class="role_label">Project Member</span>
+<a name="c2" href="/p/allura-google-importer/issues/detail?id=6#c2">#2</a>
+<a class="userlink" href="/u/101557263855536553789/">john...@gmail.com</a></span>
+<pre>
+Boring comment
+</pre>
+</div>
+
+<div class="vt issuecomment" width="100%" style="background:#e5ecf9; padding:2px .7em; margin:0">
+ <a href="detail?id=1769&amp;cnum=500&amp;cstart=502">Newer <b>&rsaquo;</b></a>
+ &nbsp;
+Showing comments 1 - 2
+of 6
+</div>
+
+</td>
+</tr>
+<tr>
+<td></td>
+<td class="vt issuecomment">
+<span class="indicator">&#9658;</span> <a href="https://www.google.com/accounts/ServiceLogin?service=code&amp;ltmpl=phosting&amp;continue=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6&amp;followup=http%3A%2F%2Fcode.google.com%2Fp%2Fallura-google-importer%2Fissues%2Fdetail%3Fid%3D6">Sign in</a> to add a comment
+ </td>
+</tr>
+</tbody>
+</table>
+<br />
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/dit_scripts.js"></script>
+</div>
+<form name="delcom" action="delComment.do?q=&amp;can=2&amp;groupby=&amp;sort=&amp;colspec=ID+Type+Status+Priority+Milestone+Owner+Summary" method="POST">
+<input type="hidden" name="sequence_num" value="" />
+<input type="hidden" name="mode" value="" />
+<input type="hidden" name="id" value="6" />
+<input type="hidden" name="token" value="" />
+</form>
+<div id="helparea"></div>
+<script type="text/javascript">
+ _onload();
+ function delComment(sequence_num, delete_mode) {
+ var f = document.forms["delcom"];
+ f.sequence_num.value = sequence_num;
+ f.mode.value = delete_mode;
+
+ f.submit();
+ return false;
+ }
+
+ _floatMetadata();
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/kibbles.js"></script>
+<script type="text/javascript">
+ _setupKibblesOnDetailPage(
+ 'http://code.google.com/p/allura-google-importer/issues/list?cursor\x3dallura-google-importer%3A6',
+ '/p/allura-google-importer/issues/entry',
+ '../../allura-google-importer/issues/detail?id\x3d5',
+ '',
+ '', 'allura-google-importer', 6,
+ false, false, codesite_token);
+</script>
+<script type="text/javascript" src="http://www.gstatic.com/codesite/ph/3783617020303179221/js/ph_core.js"></script>
+</div>
+<div id="footer" dir="ltr">
+<div class="text">
+<a href="/projecthosting/terms.html">Terms</a> -
+ <a href="http://www.google.com/privacy.html">Privacy</a> -
+ <a href="/p/support/">Project Hosting Help</a>
+</div>
+</div>
+<div class="hostedBy" style="margin-top: -20px;">
+<span style="vertical-align: top;">Powered by <a href="http://code.google.com/projecthosting/">Google Project Hosting</a></span>
+</div>
+</body>
+</html>

http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/data/google/test-issue.html b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
index c6bce0a..59507a9 100644
--- a/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
+++ b/ForgeImporters/forgeimporters/tests/data/google/test-issue.html
@@ -1,4 +1,9 @@
 <!DOCTYPE html>
+<!--
+
+Just a regular single-page issue
+
+-->
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@@ -323,6 +328,7 @@ That's all
 </table>
 </div>
 </div>
+
 <div class="cursor_off vt issuecomment" id="hc1">
 <div style="float:right; margin-right:.3em; text-align:right">
 <span class="date" title="Thu Aug  8 15:35:15 2013">
@@ -469,6 +475,7 @@ Oh, I forgot one (with an inter-project reference to <a href="/p/other-project/i
 <div class="round4"></div>
 </div>
 </div>
+
 </td>
 </tr>
 <tr>

http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/tests/google/functional/test_tracker.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/functional/test_tracker.py b/ForgeImporters/forgeimporters/tests/google/functional/test_tracker.py
index 96d789d..938d1c7 100644
--- a/ForgeImporters/forgeimporters/tests/google/functional/test_tracker.py
+++ b/ForgeImporters/forgeimporters/tests/google/functional/test_tracker.py
@@ -31,6 +31,7 @@ from allura import model as M
 from forgetracker import model as TM
 from forgeimporters import base
 from forgeimporters import google
+import forgeimporters.google.tracker
 
 
 class TestGCTrackerImporter(TestCase):
@@ -42,6 +43,10 @@ class TestGCTrackerImporter(TestCase):
                 'allura-google-importer', 'project_info')
         extractor.page = BeautifulSoup(html)
         extractor.url = "http://test/issue/?id=1"
+        # iter_comments will make more get_page() calls but we don't want the real thing to run an mess up the .page
+        # and .url attributes, make it a no-op which works with these tests (since its just the same page being
+        # fetched really)
+        extractor.get_page = lambda *a, **kw: ''
         return extractor
 
     def _make_ticket(self, issue, issue_id=1):
@@ -197,7 +202,7 @@ class TestGCTrackerImporter(TestCase):
                    for a in actual)
         self.assertEqual(atts, set(expected))
 
-    def test_attachements(self):
+    def test_attachments(self):
         ticket = self._make_ticket(self.test_issue)
         self._assert_attachments(ticket.attachments,
                                  ('at1.txt', 'text/plain',

http://git-wip-us.apache.org/repos/asf/allura/blob/225dc73c/ForgeImporters/forgeimporters/tests/google/test_extractor.py
----------------------------------------------------------------------
diff --git a/ForgeImporters/forgeimporters/tests/google/test_extractor.py b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
index 60ca0e2..fe74f9c 100644
--- a/ForgeImporters/forgeimporters/tests/google/test_extractor.py
+++ b/ForgeImporters/forgeimporters/tests/google/test_extractor.py
@@ -33,7 +33,6 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     def setUp(self):
         self._p_urlopen = mock.patch.object(base.ProjectExtractor, 'urlopen')
-        # self._p_soup = mock.patch.object(google, 'BeautifulSoup')
         self._p_soup = mock.patch.object(base, 'BeautifulSoup')
         self.urlopen = self._p_urlopen.start()
         self.soup = self._p_soup.start()
@@ -145,8 +144,7 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     def _make_extractor(self, html):
         with mock.patch.object(base.ProjectExtractor, 'urlopen'):
-            extractor = google.GoogleCodeProjectExtractor(
-                'allura-google-importer')
+            extractor = google.GoogleCodeProjectExtractor('allura-google-importer')
         extractor.page = BeautifulSoup(html)
         extractor.get_page = lambda pagename: extractor.page
         extractor.url = "http://test/source/browse"
@@ -184,9 +182,9 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     @without_module('html2text')
     def test_get_issue_basic_fields(self):
-        test_issue = open(pkg_resources.resource_filename(
-            'forgeimporters', 'tests/data/google/test-issue.html')).read()
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
         gpe = self._make_extractor(test_issue)
+
         self.assertEqual(gpe.get_issue_creator().name, 'john...@gmail.com')
         self.assertEqual(gpe.get_issue_creator().url,
                          'http://code.google.com/u/101557263855536553789/')
@@ -224,8 +222,7 @@ class TestGoogleCodeProjectExtractor(TestCase):
 
     @skipif(module_not_available('html2text'))
     def test_get_issue_basic_fields_html2text(self):
-        test_issue = open(pkg_resources.resource_filename(
-            'forgeimporters', 'tests/data/google/test-issue.html')).read()
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue.html')).read()
         gpe = self._make_extractor(test_issue)
         self.assertEqual(gpe.get_issue_creator().name, 'john...@gmail.com')
         self.assertEqual(gpe.get_issue_creator().url,
@@ -280,12 +277,6 @@ class TestGoogleCodeProjectExtractor(TestCase):
         gpe = self._make_extractor(html % u'My Summary')
         self.assertEqual(gpe.get_issue_summary(), u'My Summary')
 
-    def test_get_issue_mod_date(self):
-        test_issue = open(pkg_resources.resource_filename(
-            'forgeimporters', 'tests/data/google/test-issue.html')).read()
-        gpe = self._make_extractor(test_issue)
-        self.assertEqual(gpe.get_issue_mod_date(), 'Thu Aug  8 15:36:57 2013')
-
     def test_get_issue_labels(self):
         test_issue = open(pkg_resources.resource_filename(
             'forgeimporters', 'tests/data/google/test-issue.html')).read()
@@ -316,18 +307,116 @@ class TestGoogleCodeProjectExtractor(TestCase):
             attachments[0].url, 'http://allura-google-importer.googlecode.com/issues/attachment?aid=70000000&name=at1.txt&token=3REU1M3JUUMt0rJUg7ldcELt6LA%3A1376059941255')
         self.assertEqual(attachments[0].type, 'text/plain')
 
+    def test_get_issue_ids(self):
+        extractor = google.GoogleCodeProjectExtractor(None)
+        extractor.get_page = mock.Mock(side_effect=((1, 2, 3), (2, 3, 4), ()))
+        self.assertItemsEqual(extractor.get_issue_ids(start=10), (1, 2, 3, 4))
+        self.assertEqual(extractor.get_page.call_count, 3)
+        extractor.get_page.assert_has_calls([
+            mock.call('issues_csv', parser=google.csv_parser, start=10),
+            mock.call('issues_csv', parser=google.csv_parser, start=110),
+            mock.call('issues_csv', parser=google.csv_parser, start=210),
+        ])
+
+    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_page')
+    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_issue_ids')
+    def test_iter_issue_ids(self, get_issue_ids, get_page):
+        get_issue_ids.side_effect = [set([1, 2]), set([2, 3, 4])]
+        issue_ids = [i for i,
+                     e in list(google.GoogleCodeProjectExtractor.iter_issues('foo'))]
+        self.assertEqual(issue_ids, [1, 2, 3, 4])
+        get_issue_ids.assert_has_calls([
+            mock.call(start=0),
+            mock.call(start=-8),
+        ])
+
+    @mock.patch.object(google.GoogleCodeProjectExtractor, '__init__')
+    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_issue_ids')
+    def test_iter_issue_ids_raises(self, get_issue_ids, __init__):
+        get_issue_ids.side_effect = [set([1, 2, 3, 4, 5])]
+        __init__.side_effect = [
+            None,
+            None,
+            # should skip but keep going
+            HTTPError('fourohfour', 404, 'fourohfour', {}, mock.Mock()),
+            None,
+            # should be re-raised
+            HTTPError('fubar', 500, 'fubar', {}, mock.Mock()),
+            None,
+        ]
+        issue_ids = []
+        try:
+            for issue_id, extractor in google.GoogleCodeProjectExtractor.iter_issues('foo'):
+                issue_ids.append(issue_id)
+        except HTTPError as e:
+            self.assertEqual(e.code, 500)
+        else:
+            assert False, 'Missing expected raised exception'
+        self.assertEqual(issue_ids, [1, 3])
+
+    @mock.patch.object(google.requests, 'head')
+    def test_check_readable(self, head):
+        head.return_value.status_code = 200
+        assert google.GoogleCodeProjectExtractor('my-project').check_readable()
+        head.return_value.status_code = 404
+        assert not google.GoogleCodeProjectExtractor('my-project').check_readable()
+
+
+class TestWithSetupForComments(TestCase):
+    # The main test suite did too much patching for how we want these tests to work
+    # These tests use iter_comments and 2 HTML pages of comments.
+
+    def _create_extractor(self):
+        test_issue = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue-first-page.html')).read()
+        test_issue_older = open(pkg_resources.resource_filename('forgeimporters', 'tests/data/google/test-issue-prev-page.html')).read()
+
+        class LocalTestExtractor(google.GoogleCodeProjectExtractor):
+            def urlopen(self, url, **kw):
+                return self.urlopen_results.pop(0)
+
+            def setup_urlopen_results(self, results):
+                self.urlopen_results = results
+
+        gpe = LocalTestExtractor('allura-google-importer')
+        gpe.setup_urlopen_results([test_issue, test_issue_older])
+
+        return gpe
+
+    def test_get_issue_mod_date(self):
+        gpe = self._create_extractor()
+        gpe.get_page('detail?id=6')
+        self.assertEqual(gpe.get_issue_mod_date(), 'Thu Aug  8 15:36:57 2013')
+
     @without_module('html2text')
     @mock.patch.object(base, 'StringIO')
     def test_iter_comments(self, StringIO):
-        test_issue = open(pkg_resources.resource_filename(
-            'forgeimporters', 'tests/data/google/test-issue.html')).read()
-        gpe = self._make_extractor(test_issue)
-        comments = list(gpe.iter_comments())
-        self.assertEqual(len(comments), 4)
+        gpe = self._create_extractor()
+        gpe.get_page('detail?id=6')
+
+        with mock.patch.object(base.ProjectExtractor, 'urlopen'):  # for attachments, which end up using a different Extractor urlopen
+            comments = list(gpe.iter_comments())
+
+        self.assertEqual(len(comments), 6)
         expected = [
             {
                 'author.name': 'john...@gmail.com',
                 'author.url': 'http://code.google.com/u/101557263855536553789/',
+                'created_date': 'Thu Aug  8 15:34:01 2013',
+                'body': 'Simple comment',
+                'updates': {},
+                'attachments': [],
+            },
+            {
+                'author.name': 'john...@gmail.com',
+                'author.url': 'http://code.google.com/u/101557263855536553789/',
+                'created_date': 'Thu Aug  8 15:34:09 2013',
+                'body': 'Boring comment',
+                'updates': {},
+                'attachments': [],
+            },
+            {
+                'author.name': 'john...@gmail.com',
+                'author.url': 'http://code.google.com/u/101557263855536553789/',
                 'created_date': 'Thu Aug  8 15:35:15 2013',
                 'body': 'Test \\*comment\\* is a comment',
                 'updates': {'Status:': 'Started', 'Labels:': '-OpSys-Linux OpSys-Windows'},
@@ -370,15 +459,33 @@ class TestGoogleCodeProjectExtractor(TestCase):
     @skipif(module_not_available('html2text'))
     @mock.patch.object(base, 'StringIO')
     def test_iter_comments_html2text(self, StringIO):
-        test_issue = open(pkg_resources.resource_filename(
-            'forgeimporters', 'tests/data/google/test-issue.html')).read()
-        gpe = self._make_extractor(test_issue)
-        comments = list(gpe.iter_comments())
-        self.assertEqual(len(comments), 4)
+        gpe = self._create_extractor()
+        gpe.get_page('detail?id=6')
+
+        with mock.patch.object(base.ProjectExtractor, 'urlopen'):  # for attachments, which end up using a different Extractor urlopen
+            comments = list(gpe.iter_comments())
+
+        self.assertEqual(len(comments), 6)
         expected = [
             {
                 'author.name': 'john...@gmail.com',
                 'author.url': 'http://code.google.com/u/101557263855536553789/',
+                'created_date': 'Thu Aug  8 15:34:01 2013',
+                'body': 'Simple comment',
+                'updates': {},
+                'attachments': [],
+            },
+            {
+                'author.name': 'john...@gmail.com',
+                'author.url': 'http://code.google.com/u/101557263855536553789/',
+                'created_date': 'Thu Aug  8 15:34:09 2013',
+                'body': 'Boring comment',
+                'updates': {},
+                'attachments': [],
+            },
+            {
+                'author.name': 'john...@gmail.com',
+                'author.url': 'http://code.google.com/u/101557263855536553789/',
                 'created_date': 'Thu Aug  8 15:35:15 2013',
                 'body': 'Test \\*comment\\* is a comment',
                 'updates': {'Status:': 'Started', 'Labels:': '-OpSys-Linux OpSys-Windows'},
@@ -418,60 +525,6 @@ class TestGoogleCodeProjectExtractor(TestCase):
             self.assertEqual(
                 [a.filename for a in actual.attachments], expected['attachments'])
 
-    def test_get_issue_ids(self):
-        extractor = google.GoogleCodeProjectExtractor(None)
-        extractor.get_page = mock.Mock(side_effect=((1, 2, 3), (2, 3, 4), ()))
-        self.assertItemsEqual(extractor.get_issue_ids(start=10), (1, 2, 3, 4))
-        self.assertEqual(extractor.get_page.call_count, 3)
-        extractor.get_page.assert_has_calls([
-            mock.call('issues_csv', parser=google.csv_parser, start=10),
-            mock.call('issues_csv', parser=google.csv_parser, start=110),
-            mock.call('issues_csv', parser=google.csv_parser, start=210),
-        ])
-
-    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_page')
-    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_issue_ids')
-    def test_iter_issue_ids(self, get_issue_ids, get_page):
-        get_issue_ids.side_effect = [set([1, 2]), set([2, 3, 4])]
-        issue_ids = [i for i,
-                     e in list(google.GoogleCodeProjectExtractor.iter_issues('foo'))]
-        self.assertEqual(issue_ids, [1, 2, 3, 4])
-        get_issue_ids.assert_has_calls([
-            mock.call(start=0),
-            mock.call(start=-8),
-        ])
-
-    @mock.patch.object(google.GoogleCodeProjectExtractor, '__init__')
-    @mock.patch.object(google.GoogleCodeProjectExtractor, 'get_issue_ids')
-    def test_iter_issue_ids_raises(self, get_issue_ids, __init__):
-        get_issue_ids.side_effect = [set([1, 2, 3, 4, 5])]
-        __init__.side_effect = [
-            None,
-            None,
-            # should skip but keep going
-            HTTPError('fourohfour', 404, 'fourohfour', {}, mock.Mock()),
-            None,
-            # should be re-raised
-            HTTPError('fubar', 500, 'fubar', {}, mock.Mock()),
-            None,
-        ]
-        issue_ids = []
-        try:
-            for issue_id, extractor in google.GoogleCodeProjectExtractor.iter_issues('foo'):
-                issue_ids.append(issue_id)
-        except HTTPError as e:
-            self.assertEqual(e.code, 500)
-        else:
-            assert False, 'Missing expected raised exception'
-        self.assertEqual(issue_ids, [1, 3])
-
-    @mock.patch.object(google.requests, 'head')
-    def test_check_readable(self, head):
-        head.return_value.status_code = 200
-        assert google.GoogleCodeProjectExtractor('my-project').check_readable()
-        head.return_value.status_code = 404
-        assert not google.GoogleCodeProjectExtractor('my-project').check_readable()
-
 
 class TestUserLink(TestCase):
 


[8/9] allura git commit: [#7870] Add missing config examples, move some configs up from app:tool_test, standardize format for example vs default configs

Posted by br...@apache.org.
[#7870] Add missing config examples, move some configs up from app:tool_test, standardize format for example vs default configs


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/1cc9b76c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/1cc9b76c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/1cc9b76c

Branch: refs/heads/db/7870
Commit: 1cc9b76c76fca622b9461aaaec662e4ecf2e61b1
Parents: 767769c
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Apr 9 18:23:55 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Apr 15 14:29:16 2015 -0400

----------------------------------------------------------------------
 Allura/development.ini | 258 ++++++++++++++++++++++++++++++--------------
 1 file changed, 178 insertions(+), 80 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/1cc9b76c/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index b7ccde6..4a4f18c 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -14,28 +14,42 @@
 ;       KIND, either express or implied.  See the License for the
 ;       specific language governing permissions and limitations
 ;       under the License.
+
+
+;
+; Allura configuration
 ;
-; allura - Pylons development environment configuration
+; Default config values are shown in this file.
+; Commented-out configurations are examples that you can use if you want.
 ;
-; The %(here)s variable will be replaced with the parent directory of this file
+; Logging configuration is at the end of the file (starting at [loggers])
 ;
-; This file is for deployment specific config options -- other configuration
-; that is always required for the app is done in the config directory,
-; and generally should not be modified by end users.
+; There are many settings you should change for your site (name, domain, secret keys, etc)
+; More settings should be changed for good performance in a production site (no autoreload, no debugging, etc)
+;
+; You may copy this file to make a new configuration file (e.g. production.ini)
+; Just use the new file name instead of development.ini for any paster commands you run.
+
+
+; TODO:
+; remove test config
+; clarify debug settings
 
 [DEFAULT]
 debug = true
 ; Uncomment and replace with the address which should receive any error reports
 ;email_to = you@yourdomain.com
 
-; Smtp settings
-;smtp_tls = False
-;smtp_ssl = True
+; SMTP settings for outgoing mail
+smtp_tls = false
+smtp_ssl = false
 ;smtp_user = some_user
 ;smtp_password = some_password
-;smtp_timeout = 10
+smtp_timeout = 10
 smtp_server = localhost
 smtp_port = 8826
+; Reply-To and From address often used in email notifications:
+forgemail.return_path = noreply@sf.net
 
 error_email_from = paste@localhost
 ; Used to uniquify references to static resources, can be a timestamp or any unique value
@@ -54,17 +68,25 @@ next=main
 [app:main]
 use = egg:Allura
 full_stack = true
-site_name = Allura
 
+; Change this to your website's name
+site_name = Allura
+; Change these to your website's domain
 domain = localhost
 base_url = http://localhost:8080
 
-;lang = ru
 cache_dir = %(here)s/data
 
 ; Cache Neighborhood objects for N seconds (speeds up requests).
 ; Set to 0 to disable (the default).
-; neighborhood.cache.duration = 0
+;neighborhood.cache.duration = 0
+
+; Template cache settings
+; See http://jinja.pocoo.org/docs/api/#jinja2.Environment
+jinja_cache_size = -1
+;jinja_bytecode_cache_type = filesystem
+;jinja_bytecode_cache_type = memcached
+;memcached_host =
 
 ; Docs at http://beaker.readthedocs.org/en/latest/configuration.html#session-options
 ; and http://beaker.readthedocs.org/en/latest/modules/session.html#beaker.session.CookieSession
@@ -77,26 +99,29 @@ beaker.session.secure = false
 beaker.session.validate_key = 714bfe3612c42390726f
 
 ; Google Analytics account for tracking
-; ga.account = UA-XXXXX-X
+;ga.account = UA-XXXXX-X
 
+; Project registration system.  Only local is available, unless you write a custom one for custom integratino.
 registration.method = local
-; theme = sftheme
 theme = allura
-show_export_control = false
 
-; auth.method = ldap
+; For LDAP see https://forge-allura.apache.org/docs/getting_started/installation.html#using-ldap
+;auth.method = ldap
 auth.method = local
 auth.remember_for = 365  ; in days, for the "remember me" checkbox on login
-; auth.login_url = /auth/
-; auth.logout_url = /auth/logout
-; auth.login_fragment_url = /auth/login_fragment
+
+; Customize login/logout URLs only if you have some custom authentication set up.
+auth.login_url = /auth/
+auth.logout_url = /auth/logout
+auth.login_fragment_url = /auth/login_fragment/
+auth.post_logout_url = /
 
 auth.min_password_len = 6
 auth.max_password_len = 30
 
 ; password expiration options (disabled if neither is set)
-; auth.pwdexpire.days = 1
-; auth.pwdexpire.before = 1401949912  ; unix timestamp
+;auth.pwdexpire.days = 1
+;auth.pwdexpire.before = 1401949912  ; unix timestamp
 
 ; if using LDAP, also run `pip install python-ldap` in your Allura environment
 
@@ -124,6 +149,8 @@ auth.allow_user_messages_config = true
 auth.allow_birth_date = true
 auth.allow_non_primary_email_password_reset = true
 auth.require_email_addr = true
+; List of social network options to use on user account settings
+socialnetworks = Facebook, Linkedin, Twitter, Google+
 
 ; In seconds
 auth.recovery_hash_expiry_period = 600
@@ -137,6 +164,13 @@ user_prefs_storage.ldap.fields.display_name = cn
 ; Limit the number of emails a user can claim.
 user_prefs.maximum_claimed_emails = 20
 
+; Control the order of sections on the user profile page
+;user_profile_sections.order = activity, personal-data, skills
+
+; Site admins will be the same as the admins of this project:
+site_admin_project = allura
+site_admin_project_nbhd = Projects
+
 ; Spam filtering service: mollom or akismet
 ;spam.method = akismet
 ; for akismet:
@@ -145,41 +179,39 @@ user_prefs.maximum_claimed_emails = 20
 ;spam.public_key =
 ;spam.private_key =
 
-; webhook.timeout = 30  # seconds, default = 30
-
+; Webhook timeout in seconds
+webhook.timeout = 30
 ; List of pauses between retries, if hook fails (in seconds)
-; webhook.retry = 60 120 240
-
+webhook.retry = 60 120 240
 ; Limit rate of webhook firing (in seconds, default = 30)
 ; Option format: webhook.<hook type>.limit,
 ; all '-' in hook type must be changed to '_'
 ; e.g. for repo-push webhook:
-; webhook.repo_push.limit = 10
-
+webhook.repo_push.limit = 10
 ; Limit max number of hooks that can be created for given project/app
 ; Option name format: same as above.
 ; Value format: json dict, where keys are app names (as appears in
 ; `WebhookSender.triggered_by`) and values are actual limits (default=3), e.g.:
-; webhook.repo_push.max_hooks = {"git": 3, "hg": 3, "svn": 3}
+webhook.repo_push.max_hooks = {"git": 3, "hg": 3, "svn": 3}
 
 ; Additional fields for admin project/user search
 ; Note: whitespace after comma is important!
-; search.project.additional_search_fields = private, url, title
-; search.user.additional_search_fields = email_addresses
+;search.project.additional_search_fields = private, url, title
+;search.user.additional_search_fields = email_addresses
 
 ; Additional fields to show in the result of admin project/user search
 ; Note: whitespace after comma is important!
-; search.project.additional_display_fields = private, url, title
-; search.user.additional_display_fields = email_addresses
+;search.project.additional_display_fields = private, url, title
+;search.user.additional_display_fields = email_addresses
 
 ; To make all pages use ssl:   (also set beaker.session.secure above)
-; force_ssl.pattern = .
+;force_ssl.pattern = .
 ; To use ssl if and only if a user is logged in:
-; force_ssl.logged_in = true
+;force_ssl.logged_in = true
 ; If you set force_ssl.logged_in, you probably want some URLs to be ssl when logged out:
-; force_ssl.pattern = ^/auth|^/[a-z0-9-]+/import_project/  ; import_project uses a login overlay
+;force_ssl.pattern = ^/auth|^/[a-z0-9-]+/import_project/  ; import_project uses a login overlay
 ; And to permit some URLs to be accessed over http anyway:
-; no_redirect.pattern = ^/nf/\d+/_(ew|static)_/|^/rest/|^/nf/tool_icon_css|^/auth/refresh_repo
+;no_redirect.pattern = ^/nf/\d+/_(ew|static)_/|^/rest/|^/nf/tool_icon_css|^/auth/refresh_repo
 
 
 ; Set the locations of some static resources.  ("ew" stands for EasyWidgets library)
@@ -210,12 +242,12 @@ scm.host.ro.svn = file:///srv/svn$path/
 scm.host.rw.svn = file:///srv/svn$path/
 
 ; SCM settings for chroot + ldap configuration.  See Allura/docs/getting_started/scm_host.rst
-; scm.host.ro.git = git://git.localhost$path
-; scm.host.rw.git = ssh://$username@localhost:8022/scm-repo$path
-; scm.host.ro.hg = http://hg.localhost$path
-; scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
-; scm.host.ro.svn = http://svn.localhost$path/
-; scm.host.rw.svn = svn+ssh://localhost:8022/scm-repo$path/
+;scm.host.ro.git = git://git.localhost$path
+;scm.host.rw.git = ssh://$username@localhost:8022/scm-repo$path
+;scm.host.ro.hg = http://hg.localhost$path
+;scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
+;scm.host.ro.svn = http://svn.localhost$path/
+;scm.host.rw.svn = svn+ssh://localhost:8022/scm-repo$path/
 
 ; SCM settings for https (sorry no docs for setting these up)
 ; these settings are currently required by the template, no matter what
@@ -240,24 +272,46 @@ scm.repos.tarball.zip_binary = /usr/bin/zip
 
 ; SCM imports (currently just SVN) will retry if it fails
 ; You can control the number of tries and delay between tries here:
-;scm.import.retry_count = 50
-;scm.import.retry_sleep_secs = 5
+scm.import.retry_count = 50
+scm.import.retry_sleep_secs = 5
 
 ; One-click merge is enabled by default, but can be turned off on for each type of repo
-;scm.merge.git.disabled = true
-;scm.merge.hg.disabled = true
+scm.merge.git.disabled = false
+scm.merge.hg.disabled = false
 
+
+; bulk_export_enabled = true
+; If you keep bulk_export_enabled, you should set up your server to securely share bulk_export_path with users somehow
 bulk_export_path = /tmp/bulk_export/{nbhd}/{project}
 bulk_export_filename = {project}-backup-{date:%Y-%m-%d-%H%M%S}.zip
+; You will need to specify site-specific instructions here for accessing the exported files.
 bulk_export_download_instructions = Sample instructions for {project}
 
 importer_upload_path = /tmp/importer_upload/{nbhd}/{project}
 
+; To disable any plugin, tool, importer, etc from being available, you can use the disable_entry_points config option.
+; Specify the keys and values as they are declared in the tool's "setup.py" file.
+; Examples:
+;disable_entry_points.importers = google-code-tracker, google-code-repo
+;disable_entry_points.allura.project_importers = google-code
+
+; Importers specifically, can be left enabled but not linked to.  You have to know the URL to use it.  Example:
+;hidden_importers = trac-tickets
+
 ; GitHub importer keys.  For github ticket import, it is best to set
 ; up an app at https://github.com/settings/applications  Use the root URL
 ; of your Allura instance for both URLs, and enter client values here:
-; github_importer.client_id =
-; github_importer.client_secret =
+;github_importer.client_id =
+;github_importer.client_secret =
+
+; If your site has docs about specific importers, you can add them here and
+; they'll appear on the import forms
+;doc.url.importers.Google Code = http://...
+
+; List of oauth API keys permitted to use special forum import API
+; (should be converted to newer importer system)
+;oauth.can_import_forum = api-key-1234, fa832r0fdsafd, f23f80sdf32fd
+
 
 ; space-separated list of tool names that are valid options
 ; for project admins to set for their 'support_page' field
@@ -265,7 +319,13 @@ importer_upload_path = /tmp/importer_upload/{nbhd}/{project}
 ; is disabled by default
 ;support_tool_choices = wiki tickets discussion
 
+; Control how /categories URL can be accessed to edit trove categories (used in project categories and user skills)
+; Default: everyone
 trovecategories.enableediting = true
+; Nobody:
+;trovecategories.enableediting = false
+; Site admins only:
+;trovecategories.enableediting = admin
 
 ; ActivityStream
 activitystream.master = mongodb://127.0.0.1:27017
@@ -285,12 +345,14 @@ ming.project.uri = mongodb://127.0.0.1:27017/project-data
 ming.project.auto_ensure_indexes = False
 ming.task.uri = mongodb://127.0.0.1:27017/task
 ming.task.auto_ensure_indexes = False
-ming.zarkov.uri = mongodb://127.0.0.1:27017/zarkov
-ming.zarkov.auto_ensure_indexes = False
+;ming.zarkov.uri = mongodb://127.0.0.1:27017/zarkov
+;ming.zarkov.auto_ensure_indexes = False
 
 ; Zarkov host setting, requires the zarkov and gevent libraries.
 ;zarkov.host = tcp://127.0.0.1:9000
 
+; A float from 0-1 representing a % of requests to measure timing on.
+; Sampled requests will have timing logged to stats.log (can change file in [handler_timermiddleware] logging section)
 stats.sample_rate = 1
 
 ; Taskd setup
@@ -298,6 +360,10 @@ monq.poll_interval=2
 
 ; SOLR setup
 solr.server = http://localhost:8983/solr
+; Alternate server to use just for querying
+;solr.query_server =
+; Shorter timeout for search queries (longer timeout for saving to solr)
+solr.short_timeout = 10
 ; commit on every add/delete?
 solr.commit = false
 ; commit add operations within N ms
@@ -308,12 +374,15 @@ solr.commitWithin = 10000
 ; convert existing label and custom field data to more appropriate solr types.
 solr.use_new_types = true
 
-; Forgemail server
+; Incoming email settings.  Used when you run: paster smtp_server development.ini
+; address to listen to
 forgemail.host = 0.0.0.0
 forgemail.port = 8825
+; domain suffix for your mail, change this.  You also need to route *.*.*.forgemail.domain to the above host/port via
+; your mail and DNS configuration
 forgemail.domain = .in.sf.net
+; probably unused?
 forgemail.url = http://localhost:8080
-forgemail.return_path = noreply@sf.net
 
 ; Specify the number of projects allowed to be created by a user
 ; depending on the age of their user account.
@@ -321,11 +390,7 @@ forgemail.return_path = noreply@sf.net
 ; (including the default user-project, so you probably want to add 1)
 ; This example allows for 1 project if the account is less than an hour old
 ; and 5 projects if the account is less than a day old.  No limits after that
-; project.rate_limits = {"3600": 2, "86400": 6}
-
-; Special Command settings
-; no need to sleep in devel
-ensure_index.sleep = 0
+;project.rate_limits = {"3600": 2, "86400": 6}
 
 ; set this to "false" if you are deploying to production and want performance improvements
 auto_reload_templates = true
@@ -335,17 +400,64 @@ auto_reload_templates = true
 ; execute malicious code after an exception is raised.
 ;set debug = false
 
+; How frequently users can send messages
+user_message.time_interval = 3600
+user_message.max_messages = 20
+; Default number of times to show a sitewide notification
+site_notification.impressions = 0
+
+; When rendering discussion post Markdown to html, if the render takes longer
+; than `markdown_cache_threshold` (in seconds), the resulting html will be
+; cached and served from cache on subsequent requests. Set to 0 to cache all
+; posts. Remove entirely to cache nothing.
+markdown_cache_threshold = .1
+; markdown text longer than max length will not be converted to html
+markdown_render_max_length = 999999999
+; Don't add rel=nofollow to these domains when generating links from Markdown content
+;nofollow_exempt_domains =
+
+; Export control choices on the project admin overview page.
+show_export_control = false
+
+; By default project admins can soft-delete their projects.
+allow_project_delete = true
+allow_project_undelete = true
+
+; Advanced settings for controlling "Last Commit Doc" algorithm used when visiting any repo browse page
+lcd_thread_chunk_size = 10
+lcd_timeout = 60
+
+
+;
+; Settings for the Blog tool
+;
 ; Enable or disable external RSS feed importing in ForgeBlog tool.
-; Default is "false". This feature requires GPL library "html2text". Install it
-; with following command:
-; pip install -e git://github.com/brondsem/html2text.git#egg=html2text
+; Default is "false". This feature requires GPL library "html2text". Install it with following command:
+;   pip install -e git://github.com/brondsem/html2text.git#egg=html2text
+; You will also need to run `paster pull-rss-feeds development.ini` in a cron job to fetch them.
 forgeblog.exfeed = false
 
+;
+; Settings for the Chat tool
+;
+forgechat.host = irc.freenode.net
+forgechat.port = 6667
+ircbot.nick = allurabot
+
+;
+; Settings for ShortUrl tool
+;
+; Override this if you set up an additional shortening mechanism (e.g. custom short domain)
 short_url.url_pattern = {base_url}/{nbhd}/{project}/{mount_point}/{short_name}
 
-user_message.time_interval = 3600
-user_message.max_messages = 20
 
+;
+; Settings for UserStats tool
+;
+userstats.count_lines_of_code = true
+
+
+; Setup for tool testing
 [app:tool_test]
 use = egg:Allura
 override_root=basetest_project_root ; TurboGears will use controllers/basetest_project_root.py as root controller
@@ -359,12 +471,6 @@ beaker.session.validate_key = 714bfe3612c42390726f
 ; Ming setup
 ming.main.uri = mongo://127.0.0.1:27017/allura:test
 
-sqlalchemy.url = sqlite:///%(here)s/devdata.db
-;echo shouldn't be used together with the logging module.
-sqlalchemy.echo = false
-sqlalchemy.echo_pool = false
-sqlalchemy.pool_recycle = 3600
-
 ; Forgemail server
 forgemail.host = 0.0.0.0
 forgemail.port = 8825
@@ -375,22 +481,14 @@ forgemail.url = http://localhost:8080
 auth.method = local
 registration.method = local
 
-; When rendering discussion post Markdown to html, if the render takes longer
-; than `markdown_cache_threshold` (in seconds), the resulting html will be
-; cached and served from cache on subsequent requests. Set to 0 to cache all
-; posts. Remove entirely to cache nothing.
-markdown_cache_threshold = .1
-; markdown text longer than max length will not be converted to html
-markdown_render_max_length = 999999999
-
-; If your site has docs about specific importers, you can add them here and
-; they'll appear on the import forms
-;doc.url.importers.Google Code = http://...
-
+; setup for the taskd background daemon request controller
 [app:task]
 use = main
 override_root = task ; TurboGears will use controllers/task.py as root controller
 
+
+
+
 ; Logging configuration
 ; Add additional loggers, handlers, formatters here
 ; Uses python's logging config file format


[6/9] allura git commit: [#7864] add new test data files to rat-excludes.txt

Posted by br...@apache.org.
[#7864] add new test data files to rat-excludes.txt


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/89981f0a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/89981f0a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/89981f0a

Branch: refs/heads/db/7870
Commit: 89981f0ae4fef4f1d3821359a195068bd9a5cd41
Parents: 567b1d4
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Wed Apr 15 14:22:18 2015 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Wed Apr 15 14:22:18 2015 +0000

----------------------------------------------------------------------
 rat-excludes.txt | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/89981f0a/rat-excludes.txt
----------------------------------------------------------------------
diff --git a/rat-excludes.txt b/rat-excludes.txt
index 2d62d50..6be4d29 100644
--- a/rat-excludes.txt
+++ b/rat-excludes.txt
@@ -39,6 +39,8 @@ ForgeGit/forgegit/data/post-receive_tmpl
 ForgeSVN/forgesvn/tests/data/
 ForgeImporters/forgeimporters/tests/data/google/empty-issue.html
 ForgeImporters/forgeimporters/tests/data/google/test-issue.html
+ForgeImporters/forgeimporters/tests/data/google/test-issue-first-page.html
+ForgeImporters/forgeimporters/tests/data/google/test-issue-prev-page.html
 ForgeImporters/forgeimporters/trac/tests/data/test-list.csv
 ForgeImporters/forgeimporters/trac/tests/data/test-list.html
 ForgeTracker/forgetracker/widgets/resources/js/jquery.multiselect.min.js


[7/9] allura git commit: [#7870] Standardize .ini comments with ;

Posted by br...@apache.org.
[#7870] Standardize .ini comments with ;

'#' sort of works, but you actually end up with config keys like '# my comment'


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/767769ce
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/767769ce
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/767769ce

Branch: refs/heads/db/7870
Commit: 767769ce6d6910bddae724af034c5f353445dd9e
Parents: 89981f0
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Apr 9 17:03:57 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Wed Apr 15 14:29:16 2015 -0400

----------------------------------------------------------------------
 Allura/development.ini | 310 ++++++++++++++++++++++----------------------
 1 file changed, 155 insertions(+), 155 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/767769ce/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index b6c3154..b7ccde6 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -1,34 +1,34 @@
-#       Licensed to the Apache Software Foundation (ASF) under one
-#       or more contributor license agreements.  See the NOTICE file
-#       distributed with this work for additional information
-#       regarding copyright ownership.  The ASF licenses this file
-#       to you 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.
-#
-# allura - Pylons development environment configuration
-#
-# The %(here)s variable will be replaced with the parent directory of this file
-#
-# This file is for deployment specific config options -- other configuration
-# that is always required for the app is done in the config directory,
-# and generally should not be modified by end users.
+;       Licensed to the Apache Software Foundation (ASF) under one
+;       or more contributor license agreements.  See the NOTICE file
+;       distributed with this work for additional information
+;       regarding copyright ownership.  The ASF licenses this file
+;       to you 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.
+;
+; allura - Pylons development environment configuration
+;
+; The %(here)s variable will be replaced with the parent directory of this file
+;
+; This file is for deployment specific config options -- other configuration
+; that is always required for the app is done in the config directory,
+; and generally should not be modified by end users.
 
 [DEFAULT]
 debug = true
-# Uncomment and replace with the address which should receive any error reports
-#email_to = you@yourdomain.com
+; Uncomment and replace with the address which should receive any error reports
+;email_to = you@yourdomain.com
 
-# Smtp settings
+; Smtp settings
 ;smtp_tls = False
 ;smtp_ssl = True
 ;smtp_user = some_user
@@ -59,12 +59,12 @@ site_name = Allura
 domain = localhost
 base_url = http://localhost:8080
 
-#lang = ru
+;lang = ru
 cache_dir = %(here)s/data
 
-# Cache Neighborhood objects for N seconds (speeds up requests).
-# Set to 0 to disable (the default).
-# neighborhood.cache.duration = 0
+; Cache Neighborhood objects for N seconds (speeds up requests).
+; Set to 0 to disable (the default).
+; neighborhood.cache.duration = 0
 
 ; Docs at http://beaker.readthedocs.org/en/latest/configuration.html#session-options
 ; and http://beaker.readthedocs.org/en/latest/modules/session.html#beaker.session.CookieSession
@@ -76,29 +76,29 @@ beaker.session.secure = false
 ; CHANGE THIS VALUE FOR YOUR SITE
 beaker.session.validate_key = 714bfe3612c42390726f
 
-# Google Analytics account for tracking
-# ga.account = UA-XXXXX-X
+; Google Analytics account for tracking
+; ga.account = UA-XXXXX-X
 
 registration.method = local
-# theme = sftheme
+; theme = sftheme
 theme = allura
 show_export_control = false
 
-# auth.method = ldap
+; auth.method = ldap
 auth.method = local
 auth.remember_for = 365  ; in days, for the "remember me" checkbox on login
-# auth.login_url = /auth/
-# auth.logout_url = /auth/logout
-# auth.login_fragment_url = /auth/login_fragment
+; auth.login_url = /auth/
+; auth.logout_url = /auth/logout
+; auth.login_fragment_url = /auth/login_fragment
 
 auth.min_password_len = 6
 auth.max_password_len = 30
 
-# password expiration options (disabled if neither is set)
-# auth.pwdexpire.days = 1
-# auth.pwdexpire.before = 1401949912  ; unix timestamp
+; password expiration options (disabled if neither is set)
+; auth.pwdexpire.days = 1
+; auth.pwdexpire.before = 1401949912  ; unix timestamp
 
-# if using LDAP, also run `pip install python-ldap` in your Allura environment
+; if using LDAP, also run `pip install python-ldap` in your Allura environment
 
 auth.ldap.server = ldap://localhost
 auth.ldap.suffix = ou=people,dc=localdomain
@@ -108,11 +108,11 @@ auth.ldap.schroot_name = scm
 auth.ldap.password.algorithm = 6
 auth.ldap.password.rounds = 6000
 auth.ldap.password.salt_len = 16
-# "autoregister" allows users to log in to Allura with an existing LDAP account
-# If using ldap, with autoregister, you should also set "allow_user_registration"
-# to false below.
-# Set "autoregister" to false to require user to register in Allura to create
-# the LDAP record and Allura record for the user.
+; "autoregister" allows users to log in to Allura with an existing LDAP account
+; If using ldap, with autoregister, you should also set "allow_user_registration"
+; to false below.
+; Set "autoregister" to false to require user to register in Allura to create
+; the LDAP record and Allura record for the user.
 auth.ldap.autoregister = true
 
 auth.allow_user_registration = true
@@ -125,16 +125,16 @@ auth.allow_birth_date = true
 auth.allow_non_primary_email_password_reset = true
 auth.require_email_addr = true
 
-# In seconds
+; In seconds
 auth.recovery_hash_expiry_period = 600
 
 user_prefs_storage.method = local
-# user_prefs_storage.method = ldap
-# If using ldap, you can specify which fields to use for a preference.
-# Any fields not specified here will be stored locally in mongo
+; user_prefs_storage.method = ldap
+; If using ldap, you can specify which fields to use for a preference.
+; Any fields not specified here will be stored locally in mongo
 user_prefs_storage.ldap.fields.display_name = cn
 
-# Limit the number of emails a user can claim.
+; Limit the number of emails a user can claim.
 user_prefs.maximum_claimed_emails = 20
 
 ; Spam filtering service: mollom or akismet
@@ -145,32 +145,32 @@ user_prefs.maximum_claimed_emails = 20
 ;spam.public_key =
 ;spam.private_key =
 
-# webhook.timeout = 30  # seconds, default = 30
+; webhook.timeout = 30  # seconds, default = 30
 
-# List of pauses between retries, if hook fails (in seconds)
-# webhook.retry = 60 120 240
+; List of pauses between retries, if hook fails (in seconds)
+; webhook.retry = 60 120 240
 
-# Limit rate of webhook firing (in seconds, default = 30)
-# Option format: webhook.<hook type>.limit,
-# all '-' in hook type must be changed to '_'
-# e.g. for repo-push webhook:
-# webhook.repo_push.limit = 10
+; Limit rate of webhook firing (in seconds, default = 30)
+; Option format: webhook.<hook type>.limit,
+; all '-' in hook type must be changed to '_'
+; e.g. for repo-push webhook:
+; webhook.repo_push.limit = 10
 
-# Limit max number of hooks that can be created for given project/app
-# Option name format: same as above.
-# Value format: json dict, where keys are app names (as appears in
-# `WebhookSender.triggered_by`) and values are actual limits (default=3), e.g.:
-# webhook.repo_push.max_hooks = {"git": 3, "hg": 3, "svn": 3}
+; Limit max number of hooks that can be created for given project/app
+; Option name format: same as above.
+; Value format: json dict, where keys are app names (as appears in
+; `WebhookSender.triggered_by`) and values are actual limits (default=3), e.g.:
+; webhook.repo_push.max_hooks = {"git": 3, "hg": 3, "svn": 3}
 
-# Additional fields for admin project/user search
-# Note: whitespace after comma is important!
-# search.project.additional_search_fields = private, url, title
-# search.user.additional_search_fields = email_addresses
+; Additional fields for admin project/user search
+; Note: whitespace after comma is important!
+; search.project.additional_search_fields = private, url, title
+; search.user.additional_search_fields = email_addresses
 
-# Additional fields to show in the result of admin project/user search
-# Note: whitespace after comma is important!
-# search.project.additional_display_fields = private, url, title
-# search.user.additional_display_fields = email_addresses
+; Additional fields to show in the result of admin project/user search
+; Note: whitespace after comma is important!
+; search.project.additional_display_fields = private, url, title
+; search.user.additional_display_fields = email_addresses
 
 ; To make all pages use ssl:   (also set beaker.session.secure above)
 ; force_ssl.pattern = .
@@ -182,10 +182,10 @@ user_prefs.maximum_claimed_emails = 20
 ; no_redirect.pattern = ^/nf/\d+/_(ew|static)_/|^/rest/|^/nf/tool_icon_css|^/auth/refresh_repo
 
 
-# Set the locations of some static resources.  ("ew" stands for EasyWidgets library)
-#  script_name is the path that is handled by the application
-#  url_base is the prefix that references to the static resources should have
-# If you use a CDN, put your CDN prefix in the url_base values
+; Set the locations of some static resources.  ("ew" stands for EasyWidgets library)
+;  script_name is the path that is handled by the application
+;  url_base is the prefix that references to the static resources should have
+; If you use a CDN, put your CDN prefix in the url_base values
 ew.script_name = /nf/%(build_key)s/_ew_/
 ew.url_base = /nf/%(build_key)s/_ew_/
 static.script_name = /nf/%(build_key)s/_static_/
@@ -199,26 +199,26 @@ ew.extra_headers = [ ('Access-Control-Allow-Origin', '*') ]
 ; If your environment (e.g. behind a server-side proxy) needs to look at an http header to get the actual remote addr
 ;ip_address_header = X-Forwarded-For
 
-# SCM settings for local development
+; SCM settings for local development
 scm.host.ro.git = /srv/git$path
 scm.host.rw.git = /srv/git$path
-# remote access varies by configuration.  If you are using a vagrant VM, this should work:
-#scm.host.rw.git = ssh://vagrant@localhost:2222/srv/git$path
+; remote access varies by configuration.  If you are using a vagrant VM, this should work:
+;scm.host.rw.git = ssh://vagrant@localhost:2222/srv/git$path
 scm.host.ro.hg = /srv/hg$path
 scm.host.rw.hg = /srv/hg$path
 scm.host.ro.svn = file:///srv/svn$path/
 scm.host.rw.svn = file:///srv/svn$path/
 
-# SCM settings for chroot + ldap configuration.  See Allura/docs/getting_started/scm_host.rst
-# scm.host.ro.git = git://git.localhost$path
-# scm.host.rw.git = ssh://$username@localhost:8022/scm-repo$path
-# scm.host.ro.hg = http://hg.localhost$path
-# scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
-# scm.host.ro.svn = http://svn.localhost$path/
-# scm.host.rw.svn = svn+ssh://localhost:8022/scm-repo$path/
+; SCM settings for chroot + ldap configuration.  See Allura/docs/getting_started/scm_host.rst
+; scm.host.ro.git = git://git.localhost$path
+; scm.host.rw.git = ssh://$username@localhost:8022/scm-repo$path
+; scm.host.ro.hg = http://hg.localhost$path
+; scm.host.rw.hg = ssh://$username@localhost:8022/scm-repo$path
+; scm.host.ro.svn = http://svn.localhost$path/
+; scm.host.rw.svn = svn+ssh://localhost:8022/scm-repo$path/
 
-# SCM settings for https (sorry no docs for setting these up)
-# these settings are currently required by the template, no matter what
+; SCM settings for https (sorry no docs for setting these up)
+; these settings are currently required by the template, no matter what
 scm.host.https.git = https://$username@localhost:8022/scm-repo$path
 scm.host.https_anon.git = https://localhost:8022/scm-repo$path
 scm.host.https.hg = https://$username@localhost:8022/scm-repo$path
@@ -253,21 +253,21 @@ bulk_export_download_instructions = Sample instructions for {project}
 
 importer_upload_path = /tmp/importer_upload/{nbhd}/{project}
 
-# GitHub importer keys.  For github ticket import, it is best to set
-# up an app at https://github.com/settings/applications  Use the root URL
-# of your Allura instance for both URLs, and enter client values here:
-# github_importer.client_id =
-# github_importer.client_secret =
+; GitHub importer keys.  For github ticket import, it is best to set
+; up an app at https://github.com/settings/applications  Use the root URL
+; of your Allura instance for both URLs, and enter client values here:
+; github_importer.client_id =
+; github_importer.client_secret =
 
-# space-separated list of tool names that are valid options
-# for project admins to set for their 'support_page' field
-# this field is not used by default in Allura, so this option
-# is disabled by default
-#support_tool_choices = wiki tickets discussion
+; space-separated list of tool names that are valid options
+; for project admins to set for their 'support_page' field
+; this field is not used by default in Allura, so this option
+; is disabled by default
+;support_tool_choices = wiki tickets discussion
 
 trovecategories.enableediting = true
 
-# ActivityStream
+; ActivityStream
 activitystream.master = mongodb://127.0.0.1:27017
 activitystream.database = activitystream
 activitystream.activity_collection = activities
@@ -276,9 +276,9 @@ activitystream.timeline_collection = timelines
 activitystream.enabled = true
 activitystream.recording.enabled = true
 
-# Ming setup
-# These don't necessarily have to be separate databases, they could
-# be all in the same database if desired
+; Ming setup
+; These don't necessarily have to be separate databases, they could
+; be all in the same database if desired
 ming.main.uri = mongodb://127.0.0.1:27017/allura
 ming.main.auto_ensure_indexes = False
 ming.project.uri = mongodb://127.0.0.1:27017/project-data
@@ -288,57 +288,57 @@ ming.task.auto_ensure_indexes = False
 ming.zarkov.uri = mongodb://127.0.0.1:27017/zarkov
 ming.zarkov.auto_ensure_indexes = False
 
-# Zarkov host setting, requires the zarkov and gevent libraries.
-#zarkov.host = tcp://127.0.0.1:9000
+; Zarkov host setting, requires the zarkov and gevent libraries.
+;zarkov.host = tcp://127.0.0.1:9000
 
 stats.sample_rate = 1
 
 ; Taskd setup
 monq.poll_interval=2
 
-# SOLR setup
+; SOLR setup
 solr.server = http://localhost:8983/solr
-# commit on every add/delete?
+; commit on every add/delete?
 solr.commit = false
-# commit add operations within N ms
+; commit add operations within N ms
 solr.commitWithin = 10000
-# Use improved data types for labels and custom fields?
-# New Allura deployments should leave this set to true. Existing deployments
-# should set to false until existing data has been reindexed. Reindexing will
-# convert existing label and custom field data to more appropriate solr types.
+; Use improved data types for labels and custom fields?
+; New Allura deployments should leave this set to true. Existing deployments
+; should set to false until existing data has been reindexed. Reindexing will
+; convert existing label and custom field data to more appropriate solr types.
 solr.use_new_types = true
 
-# Forgemail server
+; Forgemail server
 forgemail.host = 0.0.0.0
 forgemail.port = 8825
 forgemail.domain = .in.sf.net
 forgemail.url = http://localhost:8080
 forgemail.return_path = noreply@sf.net
 
-# Specify the number of projects allowed to be created by a user
-# depending on the age of their user account.
-# Keys are number of seconds, values are max number of projects allowed
-# (including the default user-project, so you probably want to add 1)
-# This example allows for 1 project if the account is less than an hour old
-# and 5 projects if the account is less than a day old.  No limits after that
-# project.rate_limits = {"3600": 2, "86400": 6}
+; Specify the number of projects allowed to be created by a user
+; depending on the age of their user account.
+; Keys are number of seconds, values are max number of projects allowed
+; (including the default user-project, so you probably want to add 1)
+; This example allows for 1 project if the account is less than an hour old
+; and 5 projects if the account is less than a day old.  No limits after that
+; project.rate_limits = {"3600": 2, "86400": 6}
 
-# Special Command settings
-# no need to sleep in devel
+; Special Command settings
+; no need to sleep in devel
 ensure_index.sleep = 0
 
-# set this to "false" if you are deploying to production and want performance improvements
+; set this to "false" if you are deploying to production and want performance improvements
 auto_reload_templates = true
 
-# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
-# Debug mode will enable the interactive debugging tool, allowing ANYONE to
-# execute malicious code after an exception is raised.
-#set debug = false
+; WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
+; Debug mode will enable the interactive debugging tool, allowing ANYONE to
+; execute malicious code after an exception is raised.
+;set debug = false
 
-# Enable or disable external RSS feed importing in ForgeBlog tool.
-# Default is "false". This feature requires GPL library "html2text". Install it
-# with following command:
-# pip install -e git://github.com/brondsem/html2text.git#egg=html2text
+; Enable or disable external RSS feed importing in ForgeBlog tool.
+; Default is "false". This feature requires GPL library "html2text". Install it
+; with following command:
+; pip install -e git://github.com/brondsem/html2text.git#egg=html2text
 forgeblog.exfeed = false
 
 short_url.url_pattern = {base_url}/{nbhd}/{project}/{mount_point}/{short_name}
@@ -356,16 +356,16 @@ beaker.session.key = allura
 beaker.session.type = cookie
 beaker.session.validate_key = 714bfe3612c42390726f
 
-# Ming setup
+; Ming setup
 ming.main.uri = mongo://127.0.0.1:27017/allura:test
 
 sqlalchemy.url = sqlite:///%(here)s/devdata.db
-#echo shouldn't be used together with the logging module.
+;echo shouldn't be used together with the logging module.
 sqlalchemy.echo = false
 sqlalchemy.echo_pool = false
 sqlalchemy.pool_recycle = 3600
 
-# Forgemail server
+; Forgemail server
 forgemail.host = 0.0.0.0
 forgemail.port = 8825
 forgemail.domain = .in.sf.net
@@ -375,26 +375,26 @@ forgemail.url = http://localhost:8080
 auth.method = local
 registration.method = local
 
-# When rendering discussion post Markdown to html, if the render takes longer
-# than `markdown_cache_threshold` (in seconds), the resulting html will be
-# cached and served from cache on subsequent requests. Set to 0 to cache all
-# posts. Remove entirely to cache nothing.
+; When rendering discussion post Markdown to html, if the render takes longer
+; than `markdown_cache_threshold` (in seconds), the resulting html will be
+; cached and served from cache on subsequent requests. Set to 0 to cache all
+; posts. Remove entirely to cache nothing.
 markdown_cache_threshold = .1
-# markdown text longer than max length will not be converted to html
+; markdown text longer than max length will not be converted to html
 markdown_render_max_length = 999999999
 
-# If your site has docs about specific importers, you can add them here and
-# they'll appear on the import forms
-#doc.url.importers.Google Code = http://...
+; If your site has docs about specific importers, you can add them here and
+; they'll appear on the import forms
+;doc.url.importers.Google Code = http://...
 
 [app:task]
 use = main
 override_root = task ; TurboGears will use controllers/task.py as root controller
 
-# Logging configuration
-# Add additional loggers, handlers, formatters here
-# Uses python's logging config file format
-# http://docs.python.org/lib/logging-config-fileformat.html
+; Logging configuration
+; Add additional loggers, handlers, formatters here
+; Uses python's logging config file format
+; http://docs.python.org/lib/logging-config-fileformat.html
 
 [loggers]
 keys = root, allura, sqlalchemy, paste, pylons, taskdstatus, timermiddleware, tmw_details
@@ -405,7 +405,7 @@ keys = console, stats, taskdstatus, timermiddleware
 [formatters]
 keys = generic, stats, timermiddleware
 
-# If you create additional loggers, add them as a key to [loggers]
+; If you create additional loggers, add them as a key to [loggers]
 [logger_root]
 level = INFO
 handlers = console, stats
@@ -419,9 +419,9 @@ qualname = allura
 level = INFO
 handlers =
 qualname = sqlalchemy.engine
-# "level = INFO" logs SQL queries.
-# "level = DEBUG" logs SQL queries and results.
-# "level = WARN" logs neither.  (Recommended for production systems.)
+; "level = INFO" logs SQL queries.
+; "level = DEBUG" logs SQL queries and results.
+; "level = WARN" logs neither.  (Recommended for production systems.)
 
 [logger_paste]
 level = INFO
@@ -434,7 +434,7 @@ qualname = pylons
 handlers =
 
 [logger_tmw_details]
-# DEBUG will include every instrumented call in our logging
+; DEBUG will include every instrumented call in our logging
 level = INFO
 qualname = timermiddleware
 handlers =
@@ -450,7 +450,7 @@ handlers = timermiddleware
 qualname = stats
 propagate = 0
 
-# If you create additional handlers, add them as a key to [handlers]
+; If you create additional handlers, add them as a key to [handlers]
 [handler_console]
 class = StreamHandler
 args = (sys.stderr,)
@@ -471,13 +471,13 @@ formatter = generic
 
 [handler_timermiddleware]
 class = handlers.WatchedFileHandler
-# if you run 'paster serve' in allura/Allura/ then that's where this file will be
-# you may want to hard-code a specific directory here.
+; if you run 'paster serve' in allura/Allura/ then that's where this file will be
+; you may want to hard-code a specific directory here.
 args = ('stats.log', 'a')
 level = NOTSET
 formatter = timermiddleware
 
-# If you create additional formatters, add them as a key to [formatters]
+; If you create additional formatters, add them as a key to [formatters]
 [formatter_generic]
 format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
 datefmt = %H:%M:%S


[4/9] allura git commit: [#7864] update pyflakes to avoid invalid warnings from @property.setter dupe fn name; fix new pyflakes warnings

Posted by br...@apache.org.
[#7864] update pyflakes to avoid invalid warnings from @property.setter dupe fn name; fix new pyflakes warnings


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/567b1d41
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/567b1d41
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/567b1d41

Branch: refs/heads/db/7870
Commit: 567b1d41befe2571e0f7cdd02f061282b1427ffd
Parents: c72837d
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Apr 8 16:04:12 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Apr 15 11:04:03 2015 +0000

----------------------------------------------------------------------
 Allura/allura/command/show_models.py        | 4 ++--
 Allura/allura/controllers/repository.py     | 8 ++++----
 Allura/allura/controllers/site_admin.py     | 6 +++---
 Allura/allura/lib/helpers.py                | 4 ++--
 Allura/allura/model/project.py              | 2 +-
 Allura/allura/tests/test_commands.py        | 7 +++----
 Allura/allura/tests/unit/test_repo.py       | 6 +++---
 ForgeSVN/forgesvn/model/svn.py              | 3 +--
 ForgeTracker/forgetracker/import_support.py | 4 ++--
 ForgeTracker/forgetracker/tracker_main.py   | 6 +++---
 requirements.txt                            | 2 +-
 11 files changed, 25 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/command/show_models.py
----------------------------------------------------------------------
diff --git a/Allura/allura/command/show_models.py b/Allura/allura/command/show_models.py
index 36aa29e..d941e9e 100644
--- a/Allura/allura/command/show_models.py
+++ b/Allura/allura/command/show_models.py
@@ -359,8 +359,8 @@ def dump_cls(depth, cls):
 
 def dfs(root, graph, depth=0):
     yield depth, root
-    for c in graph[root][1]:
-        for r in dfs(c, graph, depth + 1):
+    for node in graph[root][1]:
+        for r in dfs(node, graph, depth + 1):
             yield r
 
 

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/controllers/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py
index 34210ce..b36449c 100644
--- a/Allura/allura/controllers/repository.py
+++ b/Allura/allura/controllers/repository.py
@@ -254,8 +254,8 @@ class RepoRootController(BaseController, FeedController):
         columns = []
 
         def find_column(columns):
-            for i, c in enumerate(columns):
-                if c is None:
+            for i, col in enumerate(columns):
+                if col is None:
                     return i
             columns.append(None)
             return len(columns) - 1
@@ -757,8 +757,8 @@ def topo_sort(children, parents, dates, head_ids):
         visited.add(next)
         yield next
         for p in parents[next]:
-            for c in children[p]:
-                if c not in visited:
+            for child in children[p]:
+                if child not in visited:
                     break
             else:
                 to_visit.append(p)

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index a85680b..ee47274 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -275,18 +275,18 @@ class SiteAdminController(object):
                     _id = obj['id'].split('#')[1]
                     obj['object'] = mongo_objects.get(_id)
                 # Some objects can be deleted, but still have index in solr, should skip those
-                objects = [obj for obj in objects if obj.get('object')]
+                objects = [o for o in objects if o.get('object')]
 
         def convert_fields(obj):
             # throw the type away (e.g. '_s' from 'url_s')
             result = {}
-            for k,v in obj.iteritems():
+            for k,val in obj.iteritems():
                 name = k.rsplit('_', 1)
                 if len(name) == 2:
                     name = name[0]
                 else:
                     name = k
-                result[name] = v
+                result[name] = val
             return result
 
         return {

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 3cd14fb..36932a3 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -583,8 +583,8 @@ def twophase_transaction(*engines):
     txns = []
     to_rollback = []
     try:
-        for c in connections:
-            txn = c.begin_twophase()
+        for conn in connections:
+            txn = conn.begin_twophase()
             txns.append(txn)
             to_rollback.append(txn)
         yield

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index b66ecec..db460a1 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -551,7 +551,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             try:
                 App = ac.load()
             # If so, we don't want it listed
-            except KeyError as e:
+            except KeyError:
                 log.exception('AppConfig %s references invalid tool %s',
                               ac._id, ac.tool_name)
                 continue

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/tests/test_commands.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_commands.py b/Allura/allura/tests/test_commands.py
index 1c298c5..f6800b7 100644
--- a/Allura/allura/tests/test_commands.py
+++ b/Allura/allura/tests/test_commands.py
@@ -193,11 +193,10 @@ class TestEnsureIndexCommand(object):
         cmd._update_indexes(collection, indexes)
 
         collection_call_order = {}
-        for i, call in enumerate(collection.mock_calls):
-            method_name = call[0]
+        for i, call_ in enumerate(collection.mock_calls):
+            method_name = call_[0]
             collection_call_order[method_name] = i
-        assert collection_call_order['ensure_index'] < collection_call_order[
-            'drop_index'], collection.mock_calls
+        assert collection_call_order['ensure_index'] < collection_call_order['drop_index'], collection.mock_calls
 
     def test_update_indexes_unique_changes(self):
         collection = Mock(name='collection')

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/Allura/allura/tests/unit/test_repo.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_repo.py b/Allura/allura/tests/unit/test_repo.py
index 7411db5..9008571 100644
--- a/Allura/allura/tests/unit/test_repo.py
+++ b/Allura/allura/tests/unit/test_repo.py
@@ -42,9 +42,9 @@ class TestCommitRunBuilder(unittest.TestCase):
             M.repository.CommitDoc.make(dict(
                 _id=str(i)))
             for i in range(10)]
-        for p, c in zip(commits, commits[1:]):
-            p.child_ids = [c._id]
-            c.parent_ids = [p._id]
+        for p, com in zip(commits, commits[1:]):
+            p.child_ids = [com._id]
+            com.parent_ids = [p._id]
         for ci in commits:
             ci.m.save()
         self.commits = commits

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/ForgeSVN/forgesvn/model/svn.py
----------------------------------------------------------------------
diff --git a/ForgeSVN/forgesvn/model/svn.py b/ForgeSVN/forgesvn/model/svn.py
index 4594a2f..cd410e3 100644
--- a/ForgeSVN/forgesvn/model/svn.py
+++ b/ForgeSVN/forgesvn/model/svn.py
@@ -360,8 +360,7 @@ class SVNImplementation(M.RepositoryImplementation):
             if not oid.startswith(prefix):
                 break
             seen_oids.add(oid)
-        return [
-            oid for oid in oids if oid not in seen_oids]
+        return [o for o in oids if o not in seen_oids]
 
     def refresh_commit_info(self, oid, seen_object_ids, lazy=True):
         from allura.model.repository import CommitDoc

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/ForgeTracker/forgetracker/import_support.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/import_support.py b/ForgeTracker/forgetracker/import_support.py
index c1865e9..affe94b 100644
--- a/ForgeTracker/forgetracker/import_support.py
+++ b/ForgeTracker/forgetracker/import_support.py
@@ -282,8 +282,8 @@ class ImportSupport(object):
         for a in artifacts:
             users.add(a['submitter'])
             users.add(a['assigned_to'])
-            for c in a['comments']:
-                users.add(c['submitter'])
+            for com in a['comments']:
+                users.add(com['submitter'])
         return users
 
     def find_unknown_users(self, users):

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index b846f42..4f20d88 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -57,7 +57,7 @@ from allura.lib.widgets import form_fields as ffw
 from allura.lib.widgets.subscriptions import SubscribeForm
 from allura.lib.plugin import ImportIdConverter
 from allura.controllers import AppDiscussionController, AppDiscussionRestController
-from allura.controllers import attachments as ac
+from allura.controllers import attachments as att
 from allura.controllers import BaseController
 from allura.controllers.feed import FeedArgs, FeedController
 
@@ -1531,12 +1531,12 @@ class TicketController(BaseController, FeedController):
         }
 
 
-class AttachmentController(ac.AttachmentController):
+class AttachmentController(att.AttachmentController):
     AttachmentClass = TM.TicketAttachment
     edit_perm = 'update'
 
 
-class AttachmentsController(ac.AttachmentsController):
+class AttachmentsController(att.AttachmentsController):
     AttachmentControllerClass = AttachmentController
 
 NONALNUM_RE = re.compile(r'\W+')

http://git-wip-us.apache.org/repos/asf/allura/blob/567b1d41/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index 6de0f60..5664528 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -74,7 +74,7 @@ datadiff==1.1.5
 ipython==1.2.1
 mock==1.0.1
 nose==1.3.4
-pyflakes==0.5.0
+pyflakes==0.8.1
 WebTest==1.4.0
 testfixtures==3.0.0
 q==2.3


[5/9] allura git commit: [#7864] remove Property with nested get/setters, since sys.settrace causes pydev/PyCharm debugger not to work

Posted by br...@apache.org.
[#7864] remove Property with nested get/setters, since sys.settrace causes pydev/PyCharm debugger not to work


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/c72837df
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c72837df
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c72837df

Branch: refs/heads/db/7870
Commit: c72837df2062465c9f75bcde6bb747df38acf243
Parents: fa548be
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Apr 7 15:37:53 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Apr 15 11:04:03 2015 +0000

----------------------------------------------------------------------
 Allura/allura/lib/decorators.py  | 18 ---------
 ForgeBlog/forgeblog/main.py      | 40 +++++++++---------
 ForgeWiki/forgewiki/wiki_main.py | 76 +++++++++++++++++------------------
 3 files changed, 58 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/c72837df/Allura/allura/lib/decorators.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/decorators.py b/Allura/allura/lib/decorators.py
index d472758..cb5cfc5 100644
--- a/Allura/allura/lib/decorators.py
+++ b/Allura/allura/lib/decorators.py
@@ -188,24 +188,6 @@ class log_action(object):  # pragma no cover
         return extra
 
 
-def Property(function):
-    '''Decorator to easily assign descriptors based on sub-function names
-    See <http://code.activestate.com/recipes/410698-property-decorator-for-python-24/>
-    '''
-    keys = 'fget', 'fset', 'fdel'
-    func_locals = {'doc': function.__doc__}
-
-    def probeFunc(frame, event, arg):
-        if event == 'return':
-            locals = frame.f_locals
-            func_locals.update(dict((k, locals.get(k)) for k in keys))
-            sys.settrace(None)
-        return probeFunc
-    sys.settrace(probeFunc)
-    function()
-    return property(**func_locals)
-
-
 def getattr_(obj, name, default_thunk):
     "Similar to .setdefault in dictionaries."
     try:

http://git-wip-us.apache.org/repos/asf/allura/blob/c72837df/ForgeBlog/forgeblog/main.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index 93cd01b..160b94e 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -39,7 +39,7 @@ from allura.app import Application, SitemapEntry
 from allura.app import DefaultAdminController
 from allura.lib import helpers as h
 from allura.lib.search import search_app
-from allura.lib.decorators import require_post, Property
+from allura.lib.decorators import require_post
 from allura.lib.security import has_access, require_access
 from allura.lib import widgets as w
 from allura.lib.widgets.subscriptions import SubscribeForm
@@ -106,25 +106,25 @@ class ForgeBlogApp(Application):
         self.admin = BlogAdminController(self)
         self.api_root = RootRestController()
 
-    @Property
-    def external_feeds_list():
-        def fget(self):
-            globals = BM.Globals.query.get(app_config_id=self.config._id)
-            if globals is not None:
-                external_feeds = globals.external_feeds
-            else:
-                external_feeds = self.default_external_feeds
-            return external_feeds
-
-        def fset(self, new_external_feeds):
-            globals = BM.Globals.query.get(app_config_id=self.config._id)
-            if globals is not None:
-                globals.external_feeds = new_external_feeds
-            elif len(new_external_feeds) > 0:
-                globals = BM.Globals(
-                    app_config_id=self.config._id, external_feeds=new_external_feeds)
-            if globals is not None:
-                session(globals).flush()
+    @property
+    def external_feeds_list(self):
+        globals = BM.Globals.query.get(app_config_id=self.config._id)
+        if globals is not None:
+            external_feeds = globals.external_feeds
+        else:
+            external_feeds = self.default_external_feeds
+        return external_feeds
+
+    @external_feeds_list.setter
+    def external_feeds_list(self, new_external_feeds):
+        globals = BM.Globals.query.get(app_config_id=self.config._id)
+        if globals is not None:
+            globals.external_feeds = new_external_feeds
+        elif len(new_external_feeds) > 0:
+            globals = BM.Globals(
+                app_config_id=self.config._id, external_feeds=new_external_feeds)
+        if globals is not None:
+            session(globals).flush()
 
     def main_menu(self):
         return [SitemapEntry(self.config.options.mount_label, '.')]

http://git-wip-us.apache.org/repos/asf/allura/blob/c72837df/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index ecbddef..a5b3d3e 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -35,7 +35,7 @@ from allura import model as M
 from allura.lib import helpers as h
 from allura.app import Application, SitemapEntry, DefaultAdminController
 from allura.lib.search import search_app
-from allura.lib.decorators import require_post, Property
+from allura.lib.decorators import require_post
 from allura.lib.security import require_access, has_access
 from allura.controllers import AppDiscussionController, BaseController, AppDiscussionRestController
 from allura.controllers import DispatchIndex
@@ -129,25 +129,25 @@ class ForgeWikiApp(Application):
             log.exception('Error getting artifact %s', topic)
         self.handle_artifact_message(page, message)
 
-    @Property
-    def root_page_name():
-        def fget(self):
-            globals = WM.Globals.query.get(app_config_id=self.config._id)
-            if globals is not None:
-                page_name = globals.root
-            else:
-                page_name = self.default_root_page_name
-            return page_name
-
-        def fset(self, new_root_page_name):
-            globals = WM.Globals.query.get(app_config_id=self.config._id)
-            if globals is not None:
-                globals.root = new_root_page_name
-            elif new_root_page_name != self.default_root_page_name:
-                globals = WM.Globals(
-                    app_config_id=self.config._id, root=new_root_page_name)
-            if globals is not None:
-                session(globals).flush(globals)
+    @property
+    def root_page_name(self):
+        globals = WM.Globals.query.get(app_config_id=self.config._id)
+        if globals is not None:
+            page_name = globals.root
+        else:
+            page_name = self.default_root_page_name
+        return page_name
+
+    @root_page_name.setter
+    def root_page_name(self, new_root_page_name):
+        globals = WM.Globals.query.get(app_config_id=self.config._id)
+        if globals is not None:
+            globals.root = new_root_page_name
+        elif new_root_page_name != self.default_root_page_name:
+            globals = WM.Globals(
+                app_config_id=self.config._id, root=new_root_page_name)
+        if globals is not None:
+            session(globals).flush(globals)
 
     def default_root_page_text(self):
         return """Welcome to your wiki!
@@ -159,29 +159,29 @@ The wiki uses [Markdown](%s) syntax.
 [[members limit=20]]
 """ % (self.url + 'markdown_syntax/')
 
-    @Property
-    def show_discussion():
-        def fget(self):
-            return self.config.options.get('show_discussion', True)
+    @property
+    def show_discussion(self):
+        return self.config.options.get('show_discussion', True)
 
-        def fset(self, show):
-            self.config.options['show_discussion'] = bool(show)
+    @show_discussion.setter
+    def show_discussion(self, show):
+        self.config.options['show_discussion'] = bool(show)
 
-    @Property
-    def show_left_bar():
-        def fget(self):
-            return self.config.options.get('show_left_bar', True)
+    @property
+    def show_left_bar(self):
+        return self.config.options.get('show_left_bar', True)
 
-        def fset(self, show):
-            self.config.options['show_left_bar'] = bool(show)
+    @show_left_bar.setter
+    def show_left_bar(self, show):
+        self.config.options['show_left_bar'] = bool(show)
 
-    @Property
-    def show_right_bar():
-        def fget(self):
-            return self.config.options.get('show_right_bar', True)
+    @property
+    def show_right_bar(self):
+        return self.config.options.get('show_right_bar', True)
 
-        def fset(self, show):
-            self.config.options['show_right_bar'] = bool(show)
+    @show_right_bar.setter
+    def show_right_bar(self, show):
+        self.config.options['show_right_bar'] = bool(show)
 
     def main_menu(self):
         '''Apps should provide their entries to be added to the main nav


[2/9] allura git commit: [#7864] remove annoying ew.render logging, by configuring logging before initializing EW

Posted by br...@apache.org.
[#7864] remove annoying ew.render logging, by configuring logging before initializing EW


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/fa548be3
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/fa548be3
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/fa548be3

Branch: refs/heads/db/7870
Commit: fa548be3fae8c90b7d7ef889b11604fac169cd58
Parents: 225dc73
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Apr 7 15:36:38 2015 -0400
Committer: Igor Bondarenko <je...@gmail.com>
Committed: Wed Apr 15 11:04:02 2015 +0000

----------------------------------------------------------------------
 AlluraTest/alluratest/controller.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/fa548be3/AlluraTest/alluratest/controller.py
----------------------------------------------------------------------
diff --git a/AlluraTest/alluratest/controller.py b/AlluraTest/alluratest/controller.py
index 0f13c5d..4a8f983 100644
--- a/AlluraTest/alluratest/controller.py
+++ b/AlluraTest/alluratest/controller.py
@@ -88,10 +88,10 @@ def setup_basic_test(config=None, app_name=DFL_APP_NAME):
         conf_dir = tg.config.here
     except AttributeError:
         conf_dir = os.getcwd()
-    ew.TemplateEngine.initialize({})
     test_file = os.path.join(conf_dir, get_config_file(config))
     cmd = SetupCommand('setup-app')
     cmd.run([test_file])
+    ew.TemplateEngine.initialize({})
 
     # run all tasks, e.g. indexing from bootstrap operations
     while M.MonQTask.run_ready('setup'):