Browse Source

Migration to python 3.4 and TurboGear 2.3.4

Bastien Sevajol 9 years ago
parent
commit
bf519cf633

+ 2 - 8
README.md View File

@@ -68,7 +68,7 @@ Tracim is licensed under the terms of the
68 68
 
69 69
 Tracim is a web application:
70 70
 
71
-* developed with python 3.
71
+* developed with python >=3.4.
72 72
 * based on the [TurboGears](http://www.turbogears.org/) web framework.
73 73
 * relying on [PostgreSQL](http://www.postgresql.org/) as the storage engine.
74 74
 
@@ -136,14 +136,11 @@ Get the sources from Bitbucket:
136 136
 
137 137
 ### Setting-up python virtualenv ###
138 138
 
139
-_Reminder : Tracim is developped and tested using python3._
139
+_Reminder : Tracim is developped and tested using python3.4._
140 140
 
141 141
 Tracim uses virtualenv as deployment environment. This ensure that there will be no 
142 142
 conflict between system-wide python installation and Tracim required ones.
143 143
 
144
-**Note**: If you're using python3.4 or more, modify ``install/requirements.txt`` file to remove
145
-``wsgiref`` package and change ``tgext.pluggable`` to ``0.5.4`` version.
146
-
147 144
     SITE_PACKAGES_PATH=`python -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"`
148 145
     virtualenv -p /usr/bin/python3 tg2env
149 146
     source tg2env/bin/activate
@@ -155,9 +152,6 @@ conflict between system-wide python installation and Tracim required ones.
155 152
     
156 153
 Notes:
157 154
 
158
-* Patchs are applied in a two-step process because some dependencies require to be patched before other packages installation
159
-* Debian: you may get errors with stevedore/pbr which is not supported by python 3.2
160
-(debian version of python 3). This is not a real problem
161 155
 * Ubuntu (at least 14.04): please update the site-package path with your version of python
162 156
 
163 157
 ## Database Setup ##

+ 13 - 14
install/requirements.txt View File

@@ -3,24 +3,24 @@ Beaker==1.6.4
3 3
 CherryPy==3.6.0
4 4
 FormEncode==1.3.0a1
5 5
 Genshi==0.7
6
-Mako==1.0.0
7
-MarkupSafe==0.15
6
+Mako==1.0.3
7
+MarkupSafe==0.23
8 8
 PasteDeploy==1.5.2
9
-SQLAlchemy==0.9.8
9
+SQLAlchemy==1.0.11
10 10
 Tempita==0.5.3dev
11
-TurboGears2==2.3.4
12
-WebOb==1.4
11
+TurboGears2==2.3.7
12
+WebOb==1.6.0a0
13 13
 WebTest==1.4.2
14
-alembic==0.6.7
14
+alembic==0.8.4
15 15
 argparse==1.2.1
16 16
 backlash==0.0.6
17 17
 beautifulsoup4==4.3.2
18 18
 cliff==1.8.0
19 19
 cmd2==0.6.7
20 20
 coverage==4.0a1
21
-crank==0.7.1
21
+crank==0.7.3
22 22
 decorator==3.4.0
23
-gearbox==0.0.6
23
+gearbox==0.0.7
24 24
 itsdangerous==0.24
25 25
 nose==1.3.4
26 26
 pbr==0.10.0
@@ -34,17 +34,16 @@ six==1.8.0
34 34
 speaklater==1.3
35 35
 sprox==0.9.4
36 36
 stevedore==1.1.0
37
-tg.devtools==2.3.4
37
+tg.devtools==2.3.7
38 38
 tgext.admin==0.6.4
39 39
 tgext.asyncjob==0.3.1
40 40
 tgext.crud==0.7.3
41
-tgext.pluggable==0.5.2
42
-transaction==1.4.3
41
+tgext.pluggable==0.5.4
42
+transaction==1.4.4
43 43
 tw2.core==2.2.2
44 44
 tw2.forms==2.2.2.1
45 45
 waitress==0.8.9
46
-wsgiref==0.1.2
47
-zope.interface==4.1.1
48
-zope.sqlalchemy==0.7.5
46
+zope.interface==4.1.3
47
+zope.sqlalchemy==0.7.6
49 48
 tgapp-resetpassword==0.1.3
50 49
 lxml

+ 1 - 1
tracim/setup.py View File

@@ -32,7 +32,7 @@ testpkgs=['WebTest >= 1.2.3',
32 32
                ]
33 33
 
34 34
 install_requires=[
35
-    "TurboGears2 >= 2.3.1",
35
+    "TurboGears2 >= 2.3.7",
36 36
     "Genshi",
37 37
     "Mako",
38 38
     "zope.sqlalchemy >= 0.4",

+ 7 - 0
tracim/tracim/config/app_cfg.py View File

@@ -24,6 +24,7 @@ from tg.i18n import lazy_ugettext as l_
24 24
 
25 25
 import tracim
26 26
 from tracim import model
27
+from tracim.lib import app_globals, helpers
27 28
 from tracim.lib.base import logger
28 29
 from tracim.model.data import ActionDescription
29 30
 from tracim.model.data import ContentType
@@ -288,4 +289,10 @@ class CFG(object):
288 289
 #
289 290
 # OR
290 291
 #
292
+
293
+# Add some variable to each templates
294
+base_config.variable_provider = lambda: {
295
+    'CFG': CFG.get_instance()
296
+}
297
+
291 298
 plug(base_config, 'tgext.asyncjob')

+ 1 - 14
tracim/tracim/lib/helpers.py View File

@@ -11,7 +11,6 @@ from markupsafe import Markup
11 11
 
12 12
 import tg
13 13
 from tg.i18n import ugettext as _
14
-from tracim.config.app_cfg import CFG
15 14
 
16 15
 from tracim.lib import app_globals as plag
17 16
 
@@ -83,15 +82,6 @@ class ICON(object):
83 82
   Shared = '<i class="fa fa-group"></i>'
84 83
   Private = '<i class="fa fa-key"></i>'
85 84
 
86
-def show_email_stuff():
87
-    """
88
-    this function is used in order to show/hide link for sending password reset through email
89
-    """
90
-    return CFG.get_instance().EMAIL_NOTIFICATION_ACTIVATED
91
-
92
-def tracker_js():
93
-    return CFG.get_instance().TRACKER_JS_CONTENT
94
-
95 85
 def IconPath(icon_size, icon_path):
96 86
     return tg.url('/assets/icons/{0}x{0}/{1}.png'.format(icon_size, icon_path))
97 87
 
@@ -176,7 +166,7 @@ def delete_label_for_item(item) -> str:
176 166
     """
177 167
     return ContentType._DELETE_LABEL[item.type]
178 168
 
179
-def is_item_still_editable(item):
169
+def is_item_still_editable(CFG, item):
180 170
     if item.type.id != 'comment':
181 171
         return False
182 172
 
@@ -208,6 +198,3 @@ def shorten(text: str, maxlength: int, add_three_points=True) -> str:
208 198
             result += '…'
209 199
 
210 200
     return result
211
-
212
-from tracim.config.app_cfg import CFG as CFG_ORI
213
-CFG = CFG_ORI.get_instance() # local CFG var is an instance of CFG class found in app_cfg

+ 7 - 3
tracim/tracim/lib/notifications.py View File

@@ -11,8 +11,6 @@ from mako.template import Template
11 11
 from tg.i18n import lazy_ugettext as l_
12 12
 from tg.i18n import ugettext as _
13 13
 
14
-from tracim.config.app_cfg import CFG
15
-
16 14
 from tracim.lib.base import logger
17 15
 from tracim.lib.email import SmtpConfiguration
18 16
 from tracim.lib.email import EmailSender
@@ -46,6 +44,8 @@ class NotifierFactory(object):
46 44
 
47 45
     @classmethod
48 46
     def create(cls, current_user: User=None) -> INotifier:
47
+        # TODO: Find a way to import properly without cyclic import
48
+        from tracim.config.app_cfg import CFG
49 49
         cfg = CFG.get_instance()
50 50
         if not cfg.EMAIL_NOTIFICATION_ACTIVATED:
51 51
             return DummyNotifier(current_user)
@@ -69,6 +69,8 @@ class RealNotifier(object):
69 69
         :return:
70 70
         """
71 71
         logger.info(self, 'Instantiating Real Notifier')
72
+        # TODO: Find a way to import properly without cyclic import
73
+        from tracim.config.app_cfg import CFG
72 74
         cfg = CFG.get_instance()
73 75
 
74 76
         self._user = current_user
@@ -78,6 +80,8 @@ class RealNotifier(object):
78 80
                                        cfg.EMAIL_NOTIFICATION_SMTP_PASSWORD)
79 81
 
80 82
     def notify_content_update(self, content: Content):
83
+        # TODO: Find a way to import properly without cyclic import
84
+        from tracim.config.app_cfg import CFG
81 85
         global_config = CFG.get_instance()
82 86
 
83 87
         if content.get_last_action().id not \
@@ -174,7 +178,7 @@ class EmailNotifier(object):
174 178
     and other stuff related to the turbogears environment)
175 179
     """
176 180
 
177
-    def __init__(self, smtp_config: SmtpConfiguration, global_config: CFG):
181
+    def __init__(self, smtp_config: SmtpConfiguration, global_config):
178 182
         self._smtp_config = smtp_config
179 183
         self._global_config = global_config
180 184
 

+ 7 - 7
tracim/tracim/templates/index.mak View File

@@ -2,7 +2,7 @@
2 2
 <%namespace name="TIM" file="tracim.templates.pod"/>
3 3
 
4 4
 <%def name="title()">
5
-  ${h.CFG.WEBSITE_TITLE|n}
5
+  ${CFG.WEBSITE_TITLE|n}
6 6
 </%def>
7 7
 
8 8
 
@@ -11,17 +11,17 @@
11 11
         <div>
12 12
             <div class="row">
13 13
                 <div class="col-sm-offset-3 col-sm-6">
14
-                    <h1 class="text-center" style="color: ${h.CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${h.CFG.WEBSITE_TITLE|n}</b></h1>
15
-                    <p class="text-center" style="color: ${h.CFG.WEBSITE_HOME_TITLE_COLOR};">${h.CFG.WEBSITE_SUBTITLE|n}</p>
14
+                    <h1 class="text-center" style="color: ${CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${CFG.WEBSITE_TITLE|n}</b></h1>
15
+                    <p class="text-center" style="color: ${CFG.WEBSITE_HOME_TITLE_COLOR};">${CFG.WEBSITE_SUBTITLE|n}</p>
16 16
                 </div>
17 17
             </div>
18 18
 
19 19
             <div class="row">
20 20
                 <div class="col-sm-offset-3 col-sm-2">
21 21
                     <a class="thumbnail">
22
-                        <img src="${h.CFG.WEBSITE_HOME_IMAGE_URL}" alt="">
22
+                        <img src="${CFG.WEBSITE_HOME_IMAGE_URL}" alt="">
23 23
                     </a>
24
-                    <p>${h.CFG.WEBSITE_HOME_TAG_LINE|n}</p>
24
+                    <p>${CFG.WEBSITE_HOME_TAG_LINE|n}</p>
25 25
                     
26 26
 
27 27
                 </div>
@@ -50,7 +50,7 @@
50 50
                                 <button type="submit" class="btn btn-small btn-success text-right">
51 51
                                     <i class="fa fa-check"></i> ${_('Login')}
52 52
                                 </button>
53
-                                % if h.show_email_stuff():
53
+                                % if CFG.EMAIL_NOTIFICATION_ACTIVATED:
54 54
                                     <div class="pull-left">
55 55
                                         <a class="btn btn-link" href="${tg.url('/reset_password')}"><i class="fa fa-magic"></i> ${_('Forgot password?')}</a>
56 56
                                     </div>
@@ -61,7 +61,7 @@
61 61
                 </div>
62 62
             </div>
63 63
             <div class="row">
64
-                <div class="col-sm-offset-3 col-sm-6 text-center">${h.CFG.WEBSITE_HOME_BELOW_LOGIN_FORM|n}</div>
64
+                <div class="col-sm-offset-3 col-sm-6 text-center">${CFG.WEBSITE_HOME_BELOW_LOGIN_FORM|n}</div>
65 65
             </div>
66 66
 
67 67
 

+ 1 - 1
tracim/tracim/templates/mail/content_update_body_html.mak View File

@@ -63,7 +63,7 @@
63 63
     
64 64
     <div id="footer">
65 65
         <p>
66
-            ${_('{user_display_name}, you receive this email because you are registered on <i>{website_title}</i> and you are <i>{user_role_label}</i> in the workspace <a href="{workspace_url}">{workspace_label}</a>.').format(user_display_name=user_display_name, user_role_label=user_role_label, workspace_url=result.item.workspace.url, workspace_label=workspace_label, website_title=h.CFG.WEBSITE_TITLE)|n}
66
+            ${_('{user_display_name}, you receive this email because you are registered on <i>{website_title}</i> and you are <i>{user_role_label}</i> in the workspace <a href="{workspace_url}">{workspace_label}</a>.').format(user_display_name=user_display_name, user_role_label=user_role_label, workspace_url=result.item.workspace.url, workspace_label=workspace_label, website_title=CFG.WEBSITE_TITLE)|n}
67 67
         </p>
68 68
         <hr/>
69 69
         <p>

+ 1 - 1
tracim/tracim/templates/mail/content_update_body_text.mak View File

@@ -15,7 +15,7 @@ Hope you'll switch your mail client configuration and enjoy Tracim :)
15 15
 --------------------------------------------------------------------------------
16 16
 
17 17
 
18
-You receive this email because you are registered on /${h.CFG.WEBSITE_TITLE}/
18
+You receive this email because you are registered on /${CFG.WEBSITE_TITLE}/
19 19
 and you are /${user_role_label}/ in the workspace /${workspace_label}/
20 20
 ${result.item.workspace.url}
21 21
 

+ 2 - 2
tracim/tracim/templates/master_anonymous.mak View File

@@ -17,7 +17,7 @@
17 17
 
18 18
     <body class="${self.body_class()}" style="
19 19
     height: 100%;
20
-    background: url(${h.CFG.WEBSITE_HOME_BACKGROUND_IMAGE_URL}) no-repeat center bottom scroll;
20
+    background: url(${CFG.WEBSITE_HOME_BACKGROUND_IMAGE_URL}) no-repeat center bottom scroll;
21 21
     -webkit-background-size: cover;
22 22
     -moz-background-size: cover;
23 23
     background-size: cover;
@@ -44,7 +44,7 @@
44 44
             });
45 45
         </script>
46 46
 
47
-        ${h.tracker_js()|n}
47
+        ${CFG.TRACKER_JS_CONTENT|n}
48 48
     </body>
49 49
 
50 50
 <%def name="content_wrapper()">

+ 1 - 1
tracim/tracim/templates/master_authenticated.mak View File

@@ -32,7 +32,7 @@
32 32
         ${self.footer()}
33 33
 
34 34
         <script src="${tg.url('/assets/js/bootstrap.min.js')}"></script>
35
-        ${h.tracker_js()|n}
35
+        ${CFG.TRACKER_JS_CONTENT|n}
36 36
     </body>
37 37
 
38 38
 <%def name="content_wrapper()">

+ 1 - 1
tracim/tracim/templates/master_no_toolbar_no_login.mak View File

@@ -46,7 +46,7 @@
46 46
         <script src="${tg.url('/javascript/external/google-code-prettify/prettify.js')}"></script>
47 47
         <script src="${tg.url('/javascript/external/bootstrap-wysiwyg.js')}"></script>
48 48
         <script src="/javascript/external/bootstrap-datetimepicker.min.js"></script>
49
-        ${h.tracker_js()|n}
49
+        ${CFG.TRACKER_JS_CONTENT|n}
50 50
     </body>
51 51
 
52 52
 <%def name="content_wrapper()">

+ 2 - 2
tracim/tracim/templates/reset_password_change_password.mak View File

@@ -1,13 +1,13 @@
1 1
 <%inherit file="local:templates.master_anonymous"/>
2 2
 
3
-<%def name="title()">${h.CFG.WEBSITE_TITLE|n} - ${_('Change Password Request')}</%def>
3
+<%def name="title()">${CFG.WEBSITE_TITLE|n} - ${_('Change Password Request')}</%def>
4 4
 
5 5
 <div class="container-fluid">
6 6
     <div class="row-fluid">
7 7
         <div>
8 8
             <div class="row">
9 9
                 <div class="col-sm-offset-3 col-sm-5">
10
-                    <h1 class="text-center" style="color: ${h.CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${h.CFG.WEBSITE_TITLE}</b></h1>
10
+                    <h1 class="text-center" style="color: ${CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${CFG.WEBSITE_TITLE}</b></h1>
11 11
                 </div>
12 12
             </div>
13 13
             <div class="row">

+ 2 - 2
tracim/tracim/templates/reset_password_index.mak View File

@@ -1,13 +1,13 @@
1 1
 <%inherit file="local:templates.master_anonymous"/>
2 2
 
3
-<%def name="title()">${h.CFG.WEBSITE_TITLE|n} - ${_('Password Reset Request')}</%def>
3
+<%def name="title()">${CFG.WEBSITE_TITLE|n} - ${_('Password Reset Request')}</%def>
4 4
 
5 5
 <div class="container-fluid">
6 6
     <div class="row-fluid">
7 7
         <div>
8 8
             <div class="row">
9 9
                 <div class="col-sm-offset-3 col-sm-5">
10
-                    <h1 class="text-center" style="color: ${h.CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${h.CFG.WEBSITE_TITLE}</b></h1>
10
+                    <h1 class="text-center" style="color: ${CFG.WEBSITE_HOME_TITLE_COLOR};"><b>${CFG.WEBSITE_TITLE}</b></h1>
11 11
                 </div>
12 12
             </div>
13 13
             <div class="row">

+ 1 - 1
tracim/tracim/templates/user_workspace_widgets.mak View File

@@ -356,7 +356,7 @@
356 356
                     <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(event.created)|n}">
357 357
                         ${_('{delta} ago').format(delta=event.created_as_delta)}
358 358
 
359
-                        % if h.is_item_still_editable(event) and event.owner.id==user.id:
359
+                        % if h.is_item_still_editable(CFG, event) and event.owner.id==user.id:
360 360
                             <br/>
361 361
                                 <a class="t-timeline-comment-delete-button" href="${event.urls.delete}">
362 362
                                     ${_('delete')} ${ICON.FA('fa fa-trash-o')}

+ 6 - 4
tracim/tracim/tests/library/test_helpers.py View File

@@ -6,6 +6,7 @@ from nose.tools import eq_
6 6
 from nose.tools import ok_
7 7
 
8 8
 import tracim.lib.helpers as h
9
+from tracim.config.app_cfg import CFG
9 10
 from tracim.model.data import Content
10 11
 from tracim.model.data import ContentType
11 12
 from tracim.model.data import Workspace
@@ -16,6 +17,7 @@ from tracim.model.serializers import DictLikeClass
16 17
 
17 18
 from tracim.tests import TestStandard
18 19
 
20
+config = CFG.get_instance()
19 21
 
20 22
 
21 23
 class TestHelpers(TestStandard):
@@ -23,7 +25,7 @@ class TestHelpers(TestStandard):
23 25
     def test_is_item_still_editable(self):
24 26
         item = DictLikeClass()
25 27
 
26
-        h.CFG.DATA_UPDATE_ALLOWED_DURATION = 0
28
+        config.DATA_UPDATE_ALLOWED_DURATION = 0
27 29
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
28 30
 
29 31
         item.type = DictLikeClass({'id': 5})
@@ -32,15 +34,15 @@ class TestHelpers(TestStandard):
32 34
         item.type.id = 'comment'
33 35
         eq_(False, h.is_item_still_editable(item))
34 36
 
35
-        h.CFG.DATA_UPDATE_ALLOWED_DURATION = -1
37
+        config.DATA_UPDATE_ALLOWED_DURATION = -1
36 38
         item.type.id = 'comment'
37 39
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
38 40
         eq_(True, h.is_item_still_editable(item))
39 41
 
40
-        h.CFG.DATA_UPDATE_ALLOWED_DURATION = 12
42
+        config.DATA_UPDATE_ALLOWED_DURATION = 12
41 43
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
42 44
         eq_(True, h.is_item_still_editable(item), 'created: {}, now: {}'.format(item.created, datetime.datetime.now())) # This test will pass only if the test duration is less than 120s !!!
43 45
 
44
-        h.CFG.DATA_UPDATE_ALLOWED_DURATION = 8
46
+        config.DATA_UPDATE_ALLOWED_DURATION = 8
45 47
         item.created = datetime.datetime.now() - datetime.timedelta(0, 10)
46 48
         eq_(False, h.is_item_still_editable(item))