Browse Source

some typing and pep8

Bastien Sevajol 7 years ago
parent
commit
4eb285365a
5 changed files with 103 additions and 46 deletions
  1. 1 1
      .gitignore
  2. 8 0
      README.txt
  3. 2 0
      setup.py
  4. 81 42
      tracim/lib/core/content.py
  5. 11 3
      tracim/models/data.py

+ 1 - 1
.gitignore View File

63
 
63
 
64
 # binary translation files
64
 # binary translation files
65
 *.mo
65
 *.mo
66
-
66
+.mypy_cache/

+ 8 - 0
README.txt View File

35
 - Run your project.
35
 - Run your project.
36
 
36
 
37
     env/bin/pserve development.ini
37
     env/bin/pserve development.ini
38
+
39
+- Run mypy checks
40
+
41
+    mypy --ignore-missing-imports --disallow-untyped-defs tracim
42
+
43
+- Run pep8 checks
44
+
45
+    pep8 tracim

+ 2 - 0
setup.py View File

29
     'pytest',
29
     'pytest',
30
     'pytest-cov',
30
     'pytest-cov',
31
     'nose',
31
     'nose',
32
+    'pep8',
33
+    'mypy',
32
 ]
34
 ]
33
 
35
 
34
 setup(
36
 setup(

+ 81 - 42
tracim/lib/core/content.py View File

49
 def compare_content_for_sorting_by_type_and_name(
49
 def compare_content_for_sorting_by_type_and_name(
50
         content1: Content,
50
         content1: Content,
51
         content2: Content
51
         content2: Content
52
-):
52
+) -> int:
53
     """
53
     """
54
     :param content1:
54
     :param content1:
55
     :param content2:
55
     :param content2:
58
                 0 if content1 = content2
58
                 0 if content1 = content2
59
     """
59
     """
60
 
60
 
61
-    if content1.type==content2.type:
61
+    if content1.type == content2.type:
62
         if content1.get_label().lower()>content2.get_label().lower():
62
         if content1.get_label().lower()>content2.get_label().lower():
63
             return 1
63
             return 1
64
         elif content1.get_label().lower()<content2.get_label().lower():
64
         elif content1.get_label().lower()<content2.get_label().lower():
66
         return 0
66
         return 0
67
     else:
67
     else:
68
         # TODO - D.A. - 2014-12-02 - Manage Content Types Dynamically
68
         # TODO - D.A. - 2014-12-02 - Manage Content Types Dynamically
69
-        content_type_order = [ContentType.Folder, ContentType.Page, ContentType.Thread, ContentType.File]
70
-        result = content_type_order.index(content1.type)-content_type_order.index(content2.type)
71
-        if result<0:
69
+        content_type_order = [
70
+            ContentType.Folder,
71
+            ContentType.Page,
72
+            ContentType.Thread,
73
+            ContentType.File,
74
+        ]
75
+
76
+        content_1_type_index = content_type_order.index(content1.type)
77
+        content_2_type_index = content_type_order.index(content2.type)
78
+        result = content_1_type_index - content_2_type_index
79
+
80
+        if result < 0:
72
             return -1
81
             return -1
73
-        elif result>0:
82
+        elif result > 0:
74
             return 1
83
             return 1
75
         else:
84
         else:
76
             return 0
85
             return 0
79
 def compare_tree_items_for_sorting_by_type_and_name(
88
 def compare_tree_items_for_sorting_by_type_and_name(
80
         item1: NodeTreeItem,
89
         item1: NodeTreeItem,
81
         item2: NodeTreeItem
90
         item2: NodeTreeItem
82
-):
91
+) -> int:
83
     return compare_content_for_sorting_by_type_and_name(item1.node, item2.node)
92
     return compare_content_for_sorting_by_type_and_name(item1.node, item2.node)
84
 
93
 
85
 
94
 
100
             self,
109
             self,
101
             session: Session,
110
             session: Session,
102
             current_user: typing.Optional[User],
111
             current_user: typing.Optional[User],
103
-            show_archived=False,
104
-            show_deleted=False,
105
-            show_temporary=False,
106
-            all_content_in_treeview=True,
107
-            force_show_all_types=False,
108
-            disable_user_workspaces_filter=False,
109
-    ):
112
+            show_archived: bool = False,
113
+            show_deleted: bool = False,
114
+            show_temporary: bool = False,
115
+            all_content_in_treeview: bool = True,
116
+            force_show_all_types: bool = False,
117
+            disable_user_workspaces_filter: bool = False,
118
+    ) -> None:
110
         self._session = session
119
         self._session = session
111
         self._user = current_user
120
         self._user = current_user
112
         self._user_id = current_user.user_id if current_user else None
121
         self._user_id = current_user.user_id if current_user else None
123
             show_archived: bool=False,
132
             show_archived: bool=False,
124
             show_deleted: bool=False,
133
             show_deleted: bool=False,
125
             show_temporary: bool=False,
134
             show_temporary: bool=False,
126
-    ):
135
+    ) -> typing.Generator['ContentApi', None, None]:
127
         """
136
         """
128
         Use this method as context manager to update show_archived,
137
         Use this method as context manager to update show_archived,
129
         show_deleted and show_temporary properties during context.
138
         show_deleted and show_temporary properties during context.
145
             self._show_deleted = previous_show_deleted
154
             self._show_deleted = previous_show_deleted
146
             self._show_temporary = previous_show_temporary
155
             self._show_temporary = previous_show_temporary
147
 
156
 
148
-    def get_revision_join(self):
157
+    def get_revision_join(self) -> sqlalchemy.sql.elements.BooleanClauseList:
149
         """
158
         """
150
         Return the Content/ContentRevision query join condition
159
         Return the Content/ContentRevision query join condition
151
         :return: Content/ContentRevision query join condition
160
         :return: Content/ContentRevision query join condition
152
-        :rtype sqlalchemy.sql.elements.BooleanClauseList
153
         """
161
         """
154
         return and_(Content.id == ContentRevisionRO.content_id,
162
         return and_(Content.id == ContentRevisionRO.content_id,
155
                     ContentRevisionRO.revision_id == self._session.query(
163
                     ContentRevisionRO.revision_id == self._session.query(
159
                     .limit(1)
167
                     .limit(1)
160
                     .correlate(Content))
168
                     .correlate(Content))
161
 
169
 
162
-
163
-    def get_canonical_query(self):
170
+    def get_canonical_query(self) -> Query:
164
         """
171
         """
165
         Return the Content/ContentRevision base query who join these table on the last revision.
172
         Return the Content/ContentRevision base query who join these table on the last revision.
166
         :return: Content/ContentRevision Query
173
         :return: Content/ContentRevision Query
167
-        :rtype sqlalchemy.orm.query.Query
168
         """
174
         """
169
-        return self._session.query(Content).join(ContentRevisionRO, self.get_revision_join())
175
+        return self._session.query(Content)\
176
+            .join(ContentRevisionRO, self.get_revision_join())
170
 
177
 
171
     @classmethod
178
     @classmethod
172
-    def sort_tree_items(cls, content_list: [NodeTreeItem])-> [Content]:
179
+    def sort_tree_items(
180
+        cls,
181
+        content_list: typing.List[NodeTreeItem],
182
+    )-> typing.List[NodeTreeItem]:
173
         news = []
183
         news = []
174
         for item in content_list:
184
         for item in content_list:
175
             news.append(item)
185
             news.append(item)
176
 
186
 
177
-        content_list.sort(key=cmp_to_key(compare_tree_items_for_sorting_by_type_and_name))
187
+        content_list.sort(key=cmp_to_key(
188
+            compare_tree_items_for_sorting_by_type_and_name,
189
+        ))
178
 
190
 
179
         return content_list
191
         return content_list
180
 
192
 
181
-
182
     @classmethod
193
     @classmethod
183
-    def sort_content(cls, content_list: [Content])-> [Content]:
194
+    def sort_content(
195
+        cls,
196
+        content_list: typing.List[Content],
197
+    ) -> typing.List[Content]:
184
         content_list.sort(key=cmp_to_key(compare_content_for_sorting_by_type_and_name))
198
         content_list.sort(key=cmp_to_key(compare_content_for_sorting_by_type_and_name))
185
         return content_list
199
         return content_list
186
 
200
 
187
-    def __real_base_query(self, workspace: Workspace=None):
201
+    def __real_base_query(
202
+        self,
203
+        workspace: Workspace = None,
204
+    ) -> Query:
188
         result = self.get_canonical_query()
205
         result = self.get_canonical_query()
189
 
206
 
190
         # Exclude non displayable types
207
         # Exclude non displayable types
212
 
229
 
213
         return result
230
         return result
214
 
231
 
215
-    def _base_query(self, workspace: Workspace=None):
232
+    def _base_query(self, workspace: Workspace=None) -> Query:
216
         result = self.__real_base_query(workspace)
233
         result = self.__real_base_query(workspace)
217
 
234
 
218
         if not self._show_deleted:
235
         if not self._show_deleted:
226
 
243
 
227
         return result
244
         return result
228
 
245
 
229
-    def __revisions_real_base_query(self, workspace: Workspace=None):
246
+    def __revisions_real_base_query(
247
+        self,
248
+        workspace: Workspace=None,
249
+    ) -> Query:
230
         result = self._session.query(ContentRevisionRO)
250
         result = self._session.query(ContentRevisionRO)
231
 
251
 
232
         # Exclude non displayable types
252
         # Exclude non displayable types
245
 
265
 
246
         return result
266
         return result
247
 
267
 
248
-    def _revisions_base_query(self, workspace: Workspace=None):
268
+    def _revisions_base_query(
269
+        self,
270
+        workspace: Workspace=None,
271
+    ) -> Query:
249
         result = self.__revisions_real_base_query(workspace)
272
         result = self.__revisions_real_base_query(workspace)
250
 
273
 
251
         if not self._show_deleted:
274
         if not self._show_deleted:
259
 
282
 
260
         return result
283
         return result
261
 
284
 
262
-    def _hard_filtered_base_query(self, workspace: Workspace=None):
285
+    def _hard_filtered_base_query(
286
+        self,
287
+        workspace: Workspace=None,
288
+    ) -> Query:
263
         """
289
         """
264
         If set to True, then filterign on is_deleted and is_archived will also
290
         If set to True, then filterign on is_deleted and is_archived will also
265
         filter parent properties. This is required for search() function which
291
         filter parent properties. This is required for search() function which
291
 
317
 
292
         return result
318
         return result
293
 
319
 
294
-    def get_base_query(self, workspace: Workspace) -> Query:
320
+    def get_base_query(
321
+        self,
322
+        workspace: Workspace,
323
+    ) -> Query:
295
         return self._base_query(workspace)
324
         return self._base_query(workspace)
296
 
325
 
297
-    def get_child_folders(self, parent: Content=None, workspace: Workspace=None, filter_by_allowed_content_types: list=[], removed_item_ids: list=[], allowed_node_types=None) -> [Content]:
326
+    def get_child_folders(self, parent: Content=None, workspace: Workspace=None, filter_by_allowed_content_types: list=[], removed_item_ids: list=[], allowed_node_types=None) -> typing.List[Content]:
298
         """
327
         """
299
         This method returns child items (folders or items) for left bar treeview.
328
         This method returns child items (folders or items) for left bar treeview.
300
 
329
 
306
                For example, if you want to move a Page from a folder to another, you should show only folders that accept pages
335
                For example, if you want to move a Page from a folder to another, you should show only folders that accept pages
307
         :return:
336
         :return:
308
         """
337
         """
338
+        filter_by_allowed_content_types = filter_by_allowed_content_types or []  # FDV
339
+        removed_item_ids = removed_item_ids or []  # FDV
340
+
309
         if not allowed_node_types:
341
         if not allowed_node_types:
310
             allowed_node_types = [ContentType.Folder]
342
             allowed_node_types = [ContentType.Folder]
311
         elif allowed_node_types==ContentType.Any:
343
         elif allowed_node_types==ContentType.Any:
332
         result = []
364
         result = []
333
         for folder in folders:
365
         for folder in folders:
334
             for allowed_content_type in filter_by_allowed_content_types:
366
             for allowed_content_type in filter_by_allowed_content_types:
335
-                if folder.type==ContentType.Folder and folder.properties['allowed_content'][allowed_content_type]==True:
367
+
368
+                is_folder = folder.type == ContentType.Folder
369
+                content_type__allowed = folder.properties['allowed_content'][allowed_content_type] == True
370
+
371
+                if is_folder and content_type__allowed:
336
                     result.append(folder)
372
                     result.append(folder)
337
                     break
373
                     break
338
 
374
 
636
             ),
672
             ),
637
         ))
673
         ))
638
 
674
 
639
-    def get_all(self, parent_id: int=None, content_type: str=ContentType.Any, workspace: Workspace=None) -> [Content]:
675
+    def get_all(self, parent_id: int=None, content_type: str=ContentType.Any, workspace: Workspace=None) -> typing.List[Content]:
640
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
676
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
641
         assert content_type is not None# DYN_REMOVE
677
         assert content_type is not None# DYN_REMOVE
642
         assert isinstance(content_type, str) # DYN_REMOVE
678
         assert isinstance(content_type, str) # DYN_REMOVE
653
 
689
 
654
         return resultset.all()
690
         return resultset.all()
655
 
691
 
656
-    def get_children(self, parent_id: int, content_types: list, workspace: Workspace=None) -> [Content]:
692
+    def get_children(self, parent_id: int, content_types: list, workspace: Workspace=None) -> typing.List[Content]:
657
         """
693
         """
658
         Return parent_id childs of given content_types
694
         Return parent_id childs of given content_types
659
         :param parent_id: parent id
695
         :param parent_id: parent id
672
         return resultset.all()
708
         return resultset.all()
673
 
709
 
674
     # TODO find an other name to filter on is_deleted / is_archived
710
     # TODO find an other name to filter on is_deleted / is_archived
675
-    def get_all_with_filter(self, parent_id: int=None, content_type: str=ContentType.Any, workspace: Workspace=None) -> [Content]:
711
+    def get_all_with_filter(self, parent_id: int=None, content_type: str=ContentType.Any, workspace: Workspace=None) -> typing.List[Content]:
676
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
712
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
677
         assert content_type is not None# DYN_REMOVE
713
         assert content_type is not None# DYN_REMOVE
678
         assert isinstance(content_type, str) # DYN_REMOVE
714
         assert isinstance(content_type, str) # DYN_REMOVE
690
 
726
 
691
         return resultset.all()
727
         return resultset.all()
692
 
728
 
693
-    def get_all_without_exception(self, content_type: str, workspace: Workspace=None) -> [Content]:
729
+    def get_all_without_exception(self, content_type: str, workspace: Workspace=None) -> typing.List[Content]:
694
         assert content_type is not None# DYN_REMOVE
730
         assert content_type is not None# DYN_REMOVE
695
 
731
 
696
         resultset = self._base_query(workspace)
732
         resultset = self._base_query(workspace)
700
 
736
 
701
         return resultset.all()
737
         return resultset.all()
702
 
738
 
703
-    def get_last_active(self, parent_id: int, content_type: str, workspace: Workspace=None, limit=10) -> [Content]:
739
+    def get_last_active(self, parent_id: int, content_type: str, workspace: Workspace=None, limit=10) -> typing.List[Content]:
704
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
740
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
705
         assert content_type is not None# DYN_REMOVE
741
         assert content_type is not None# DYN_REMOVE
706
         assert isinstance(content_type, str) # DYN_REMOVE
742
         assert isinstance(content_type, str) # DYN_REMOVE
736
         return result
772
         return result
737
 
773
 
738
     def get_last_unread(self, parent_id: int, content_type: str,
774
     def get_last_unread(self, parent_id: int, content_type: str,
739
-                        workspace: Workspace=None, limit=10) -> [Content]:
775
+                        workspace: Workspace=None, limit=10) -> typing.List[Content]:
740
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
776
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
741
         assert content_type is not None# DYN_REMOVE
777
         assert content_type is not None# DYN_REMOVE
742
         assert isinstance(content_type, str) # DYN_REMOVE
778
         assert isinstance(content_type, str) # DYN_REMOVE
1106
 
1142
 
1107
         return keywords
1143
         return keywords
1108
 
1144
 
1109
-    def search(self, keywords: [str]) -> sqlalchemy.orm.query.Query:
1145
+    def search(self, keywords: [str]) -> Query:
1110
         """
1146
         """
1111
         :return: a sorted list of Content items
1147
         :return: a sorted list of Content items
1112
         """
1148
         """
1123
 
1159
 
1124
         return title_keyworded_items
1160
         return title_keyworded_items
1125
 
1161
 
1126
-    def get_all_types(self) -> [ContentType]:
1162
+    def get_all_types(self) -> typing.List[ContentType]:
1127
         labels = ContentType.all()
1163
         labels = ContentType.all()
1128
         content_types = []
1164
         content_types = []
1129
         for label in labels:
1165
         for label in labels:
1131
 
1167
 
1132
         return ContentType.sorted(content_types)
1168
         return ContentType.sorted(content_types)
1133
 
1169
 
1134
-    def exclude_unavailable(self, contents: [Content]) -> [Content]:
1170
+    def exclude_unavailable(
1171
+        self,
1172
+        contents: typing.List[Content],
1173
+    ) -> typing.List[Content]:
1135
         """
1174
         """
1136
         Update and return list with content under archived/deleted removed.
1175
         Update and return list with content under archived/deleted removed.
1137
         :param contents: List of contents to parse
1176
         :param contents: List of contents to parse

+ 11 - 3
tracim/models/data.py View File

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
+import typing
2
 import datetime as datetime_root
3
 import datetime as datetime_root
3
 import json
4
 import json
4
 import os
5
 import os
1327
 
1328
 
1328
 class NodeTreeItem(object):
1329
 class NodeTreeItem(object):
1329
     """
1330
     """
1330
-        This class implements a model that allow to simply represents the left-panel menu items
1331
-         This model is used by dbapi but is not directly related to sqlalchemy and database
1331
+        This class implements a model that allow to simply represents
1332
+        the left-panel menu items. This model is used by dbapi but
1333
+        is not directly related to sqlalchemy and database
1332
     """
1334
     """
1333
-    def __init__(self, node: Content, children: list('NodeTreeItem'), is_selected = False):
1335
+    def __init__(
1336
+        self,
1337
+        node: Content,
1338
+        children: typing.List['NodeTreeItem'],
1339
+        is_selected: bool = False,
1340
+    ):
1334
         self.node = node
1341
         self.node = node
1335
         self.children = children
1342
         self.children = children
1336
         self.is_selected = is_selected
1343
         self.is_selected = is_selected
1337
 
1344
 
1345
+
1338
 class VirtualEvent(object):
1346
 class VirtualEvent(object):
1339
     @classmethod
1347
     @classmethod
1340
     def create_from(cls, object):
1348
     def create_from(cls, object):