浏览代码

Code clean (annotations, method rename, method move)

Bastien Sevajol 9 年前
父节点
当前提交
416862cbb1

+ 2 - 2
tracim/tracim/lib/content.py 查看文件

91
                     .correlate(Content))
91
                     .correlate(Content))
92
 
92
 
93
     @classmethod
93
     @classmethod
94
-    def get_base_query(cls):
94
+    def get_canonical_query(cls):
95
         """
95
         """
96
         Return the Content/ContentRevision base query who join these table on the last revision.
96
         Return the Content/ContentRevision base query who join these table on the last revision.
97
         :return: Content/ContentRevision Query
97
         :return: Content/ContentRevision Query
156
         return breadcrumb
156
         return breadcrumb
157
 
157
 
158
     def __real_base_query(self, workspace: Workspace=None):
158
     def __real_base_query(self, workspace: Workspace=None):
159
-        result = self.get_base_query()
159
+        result = self.get_canonical_query()
160
 
160
 
161
         if workspace:
161
         if workspace:
162
             result = result.filter(Content.workspace_id==workspace.workspace_id)
162
             result = result.filter(Content.workspace_id==workspace.workspace_id)

+ 14 - 13
tracim/tracim/model/__init__.py 查看文件

3
 from decorator import contextmanager
3
 from decorator import contextmanager
4
 from sqlalchemy import event, inspect, MetaData
4
 from sqlalchemy import event, inspect, MetaData
5
 from sqlalchemy.ext.declarative import declarative_base
5
 from sqlalchemy.ext.declarative import declarative_base
6
-from sqlalchemy.orm import scoped_session, sessionmaker
7
-
6
+from sqlalchemy.orm import scoped_session, sessionmaker, Session
7
+from sqlalchemy.orm.unitofwork import UOWTransaction
8
 from zope.sqlalchemy import ZopeTransactionExtension
8
 from zope.sqlalchemy import ZopeTransactionExtension
9
 
9
 
10
 from tracim.lib.exception import ContentRevisionUpdateError, ContentRevisionDeleteError
10
 from tracim.lib.exception import ContentRevisionUpdateError, ContentRevisionDeleteError
22
     _updatable_revisions = []
22
     _updatable_revisions = []
23
 
23
 
24
     @classmethod
24
     @classmethod
25
-    def add_to_updatable(cls, revision):
25
+    def add_to_updatable(cls, revision: 'ContentRevisionRO') -> None:
26
         if inspect(revision).has_identity:
26
         if inspect(revision).has_identity:
27
             raise ContentRevisionUpdateError("ContentRevision is not updatable. %s already have identity." % revision)
27
             raise ContentRevisionUpdateError("ContentRevision is not updatable. %s already have identity." % revision)
28
 
28
 
30
             cls._updatable_revisions.append(revision)
30
             cls._updatable_revisions.append(revision)
31
 
31
 
32
     @classmethod
32
     @classmethod
33
-    def remove_from_updatable(cls, revision):
33
+    def remove_from_updatable(cls, revision: 'ContentRevisionRO') -> None:
34
         cls._updatable_revisions.remove(revision)
34
         cls._updatable_revisions.remove(revision)
35
 
35
 
36
     @classmethod
36
     @classmethod
37
-    def is_updatable(cls, revision):
37
+    def is_updatable(cls, revision: 'ContentRevisionRO') -> bool:
38
         return revision in cls._updatable_revisions
38
         return revision in cls._updatable_revisions
39
 
39
 
40
 # Global session manager: DBSession() returns the Thread-local
40
 # Global session manager: DBSession() returns the Thread-local
47
 # defined with SQLAlchemy's declarative extension, but if you need more
47
 # defined with SQLAlchemy's declarative extension, but if you need more
48
 # control, you can switch to the traditional method.
48
 # control, you can switch to the traditional method.
49
 convention = {
49
 convention = {
50
-  "ix": 'ix__%(column_0_label)s',
51
-  "uq": "uk__%(table_name)s__%(column_0_name)s",
52
-  "ck": "ck__%(table_name)s__%(constraint_name)s",
53
-  "fk": "fk__%(table_name)s__%(column_0_name)s__%(referred_table_name)s",
54
-  "pk": "pk__%(table_name)s"
50
+  "ix": 'ix__%(column_0_label)s',  # Indexes
51
+  "uq": "uq__%(table_name)s__%(column_0_name)s",  # Unique constrains
52
+  "ck": "ck__%(table_name)s__%(constraint_name)s",  # Other column constrains
53
+  "fk": "fk__%(table_name)s__%(column_0_name)s__%(referred_table_name)s",  # Foreign keys
54
+  "pk": "pk__%(table_name)s"  # Primary keys
55
 }
55
 }
56
 
56
 
57
 metadata = MetaData(naming_convention=convention)
57
 metadata = MetaData(naming_convention=convention)
105
 
105
 
106
 
106
 
107
 @event.listens_for(DBSession, 'before_flush')
107
 @event.listens_for(DBSession, 'before_flush')
108
-def prevent_content_revision_delete(session, flush_context, instances):
108
+def prevent_content_revision_delete(session: Session, flush_context: UOWTransaction,
109
+                                    instances: [DeclarativeBase]) -> None:
109
     for instance in session.deleted:
110
     for instance in session.deleted:
110
         if isinstance(instance, ContentRevisionRO) and instance.revision_id is not None:
111
         if isinstance(instance, ContentRevisionRO) and instance.revision_id is not None:
111
             raise ContentRevisionDeleteError("ContentRevision is not deletable. You must make a new revision with" +
112
             raise ContentRevisionDeleteError("ContentRevision is not deletable. You must make a new revision with" +
114
 
115
 
115
 
116
 
116
 @contextmanager
117
 @contextmanager
117
-def new_revision(content):
118
+def new_revision(content: Content) -> Content:
118
     """
119
     """
119
     Prepare context to update a Content. It will add a new updatable revision to the content.
120
     Prepare context to update a Content. It will add a new updatable revision to the content.
120
     :param content: Content instance to update
121
     :param content: Content instance to update
125
             if inspect(content.revision).has_identity:
126
             if inspect(content.revision).has_identity:
126
                 content.new_revision()
127
                 content.new_revision()
127
             RevisionsIntegrity.add_to_updatable(content.revision)
128
             RevisionsIntegrity.add_to_updatable(content.revision)
128
-            yield content.revision
129
+            yield content
129
         finally:
130
         finally:
130
             RevisionsIntegrity.remove_from_updatable(content.revision)
131
             RevisionsIntegrity.remove_from_updatable(content.revision)

+ 94 - 90
tracim/tracim/model/data.py 查看文件

16
 from sqlalchemy.orm import backref
16
 from sqlalchemy.orm import backref
17
 from sqlalchemy.orm import deferred
17
 from sqlalchemy.orm import deferred
18
 from sqlalchemy.orm import relationship
18
 from sqlalchemy.orm import relationship
19
+from sqlalchemy.orm.attributes import InstrumentedAttribute
19
 from sqlalchemy.orm.collections import attribute_mapped_collection
20
 from sqlalchemy.orm.collections import attribute_mapped_collection
20
 from sqlalchemy.types import Boolean
21
 from sqlalchemy.types import Boolean
21
 from sqlalchemy.types import DateTime
22
 from sqlalchemy.types import DateTime
51
     label   = Column(Unicode(1024), unique=False, nullable=False, default='')
52
     label   = Column(Unicode(1024), unique=False, nullable=False, default='')
52
     description = Column(Text(), unique=False, nullable=False, default='')
53
     description = Column(Text(), unique=False, nullable=False, default='')
53
 
54
 
55
+    #  Default value datetime.utcnow, see: http://stackoverflow.com/a/13370382/801924 (or http://pastebin.com/VLyWktUn)
54
     created = Column(DateTime, unique=False, nullable=False, default=datetime.utcnow)
56
     created = Column(DateTime, unique=False, nullable=False, default=datetime.utcnow)
57
+    #  Default value datetime.utcnow, see: http://stackoverflow.com/a/13370382/801924 (or http://pastebin.com/VLyWktUn)
55
     updated = Column(DateTime, unique=False, nullable=False, default=datetime.utcnow)
58
     updated = Column(DateTime, unique=False, nullable=False, default=datetime.utcnow)
56
 
59
 
57
     is_deleted = Column(Boolean, unique=False, nullable=False, default=False)
60
     is_deleted = Column(Boolean, unique=False, nullable=False, default=False)
515
 
518
 
516
     """ List of column copied when make a new revision from another """
519
     """ List of column copied when make a new revision from another """
517
     _cloned_columns = (
520
     _cloned_columns = (
518
-        'content_id', 'owner_id', 'label', 'description', 'file_name', 'file_mimetype', 'properties',
519
-        'file_content', 'type', 'status', 'created', 'updated', 'is_deleted', 'is_archived',
520
-        'revision_type', 'workspace_id', 'workspace', 'parent_id', 'parent', 'node', 'owner'
521
+        'content_id', 'created', 'description', 'file_content', 'file_mimetype', 'file_name', 'is_archived',
522
+        'is_deleted', 'label', 'node', 'owner' 'owner_id', 'parent', 'parent_id', 'properties', 'revision_type',
523
+        'status', 'type', 'updated', 'workspace', 'workspace_id',
524
+    )
525
+
526
+    # Read by must be used like this:
527
+    # read_datetime = revision.ready_by[<User instance>]
528
+    # if user did not read the content, then a key error is raised
529
+    read_by = association_proxy(
530
+        'revision_read_statuses',  # name of the attribute
531
+        'view_datetime',  # attribute the value is taken from
532
+        creator=lambda k, v: \
533
+            RevisionReadStatus(user=k, view_datetime=v)
521
     )
534
     )
522
 
535
 
523
     @classmethod
536
     @classmethod
524
-    def new_from(cls, revision):
537
+    def new_from(cls, revision: 'ContentRevisionRO') -> 'ContentRevisionRO':
525
         """
538
         """
526
 
539
 
527
         Return new instance of ContentRevisionRO where properties are copied from revision parameter.
540
         Return new instance of ContentRevisionRO where properties are copied from revision parameter.
542
 
555
 
543
         return new_rev
556
         return new_rev
544
 
557
 
545
-    def __setattr__(self, key, value):
558
+    def __setattr__(self, key: str, value: 'mixed'):
546
         """
559
         """
547
         ContentRevisionUpdateError is raised if tried to update column and revision own identity
560
         ContentRevisionUpdateError is raised if tried to update column and revision own identity
548
         :param key: attribute name
561
         :param key: attribute name
561
 
574
 
562
         super().__setattr__(key, value)
575
         super().__setattr__(key, value)
563
 
576
 
564
-    def get_status(self):
577
+    def get_status(self) -> ContentStatus:
565
         return ContentStatus(self.status)
578
         return ContentStatus(self.status)
566
 
579
 
567
-    def get_label(self):
580
+    def get_label(self) -> str:
568
         return self.label if self.label else self.file_name if self.file_name else ''
581
         return self.label if self.label else self.file_name if self.file_name else ''
569
 
582
 
570
     def get_last_action(self) -> ActionDescription:
583
     def get_last_action(self) -> ActionDescription:
571
         return ActionDescription(self.revision_type)
584
         return ActionDescription(self.revision_type)
572
 
585
 
573
-    # Read by must be used like this:
574
-    # read_datetime = revision.ready_by[<User instance>]
575
-    # if user did not read the content, then a key error is raised
576
-    read_by = association_proxy(
577
-        'revision_read_statuses',  # name of the attribute
578
-        'view_datetime',  # attribute the value is taken from
579
-        creator=lambda k, v: \
580
-            RevisionReadStatus(user=k, view_datetime=v)
581
-    )
582
-
583
     def has_new_information_for(self, user: User) -> bool:
586
     def has_new_information_for(self, user: User) -> bool:
584
         """
587
         """
585
         :param user: the session current user
588
         :param user: the session current user
621
                   .filter(Content.label == 'foo')
624
                   .filter(Content.label == 'foo')
622
                   .one()
625
                   .one()
623
 
626
 
624
-    ContentApi provide also prepared Content at tracim.lib.content.ContentApi#get_base_query:
627
+    ContentApi provide also prepared Content at tracim.lib.content.ContentApi#get_canonical_query:
625
 
628
 
626
-    content = ContentApi.get_base_query()
629
+    content = ContentApi.get_canonical_query()
627
               .filter(Content.label == 'foo')
630
               .filter(Content.label == 'foo')
628
               .one()
631
               .one()
629
     """
632
     """
641
                                       back_populates="parent")
644
                                       back_populates="parent")
642
 
645
 
643
     @hybrid_property
646
     @hybrid_property
644
-    def content_id(self):
647
+    def content_id(self) -> int:
645
         return self.revision.content_id
648
         return self.revision.content_id
646
 
649
 
647
     @content_id.setter
650
     @content_id.setter
648
-    def content_id(self, value):
651
+    def content_id(self, value: int) -> None:
649
         self.revision.content_id = value
652
         self.revision.content_id = value
650
 
653
 
651
     @content_id.expression
654
     @content_id.expression
652
-    def content_id(cls):
655
+    def content_id(cls) -> InstrumentedAttribute:
653
         return ContentRevisionRO.content_id
656
         return ContentRevisionRO.content_id
654
 
657
 
655
     @hybrid_property
658
     @hybrid_property
656
-    def revision_id(self):
659
+    def revision_id(self) -> int:
657
         return self.revision.revision_id
660
         return self.revision.revision_id
658
 
661
 
659
     @revision_id.setter
662
     @revision_id.setter
660
-    def revision_id(self, value):
663
+    def revision_id(self, value: int):
661
         self.revision.revision_id = value
664
         self.revision.revision_id = value
662
 
665
 
663
     @revision_id.expression
666
     @revision_id.expression
664
-    def revision_id(cls):
667
+    def revision_id(cls) -> InstrumentedAttribute:
665
         return ContentRevisionRO.revision_id
668
         return ContentRevisionRO.revision_id
666
 
669
 
667
     @hybrid_property
670
     @hybrid_property
668
-    def owner_id(self):
671
+    def owner_id(self) -> int:
669
         return self.revision.owner_id
672
         return self.revision.owner_id
670
 
673
 
671
     @owner_id.setter
674
     @owner_id.setter
672
-    def owner_id(self, value):
675
+    def owner_id(self, value: int) -> None:
673
         self.revision.owner_id = value
676
         self.revision.owner_id = value
674
 
677
 
675
     @owner_id.expression
678
     @owner_id.expression
676
-    def owner_id(cls):
679
+    def owner_id(cls) -> InstrumentedAttribute:
677
         return ContentRevisionRO.owner_id
680
         return ContentRevisionRO.owner_id
678
 
681
 
679
     @hybrid_property
682
     @hybrid_property
680
-    def label(self):
683
+    def label(self) -> str:
681
         return self.revision.label
684
         return self.revision.label
682
 
685
 
683
     @label.setter
686
     @label.setter
684
-    def label(self, value):
687
+    def label(self, value: str) -> None:
685
         self.revision.label = value
688
         self.revision.label = value
686
 
689
 
687
     @label.expression
690
     @label.expression
688
-    def label(cls):
691
+    def label(cls) -> InstrumentedAttribute:
689
         return ContentRevisionRO.label
692
         return ContentRevisionRO.label
690
 
693
 
691
     @hybrid_property
694
     @hybrid_property
692
-    def description(self):
695
+    def description(self) -> str:
693
         return self.revision.description
696
         return self.revision.description
694
 
697
 
695
     @description.setter
698
     @description.setter
696
-    def description(self, value):
699
+    def description(self, value: str) -> None:
697
         self.revision.description = value
700
         self.revision.description = value
698
 
701
 
699
     @description.expression
702
     @description.expression
700
-    def description(cls):
703
+    def description(cls) -> InstrumentedAttribute:
701
         return ContentRevisionRO.description
704
         return ContentRevisionRO.description
702
 
705
 
703
     @hybrid_property
706
     @hybrid_property
704
-    def file_name(self):
707
+    def file_name(self) -> str:
705
         return self.revision.file_name
708
         return self.revision.file_name
706
 
709
 
707
     @file_name.setter
710
     @file_name.setter
708
-    def file_name(self, value):
711
+    def file_name(self, value: str) -> None:
709
         self.revision.file_name = value
712
         self.revision.file_name = value
710
 
713
 
711
     @file_name.expression
714
     @file_name.expression
712
-    def file_name(cls):
715
+    def file_name(cls) -> InstrumentedAttribute:
713
         return ContentRevisionRO.file_name
716
         return ContentRevisionRO.file_name
714
 
717
 
715
     @hybrid_property
718
     @hybrid_property
716
-    def file_mimetype(self):
719
+    def file_mimetype(self) -> str:
717
         return self.revision.file_mimetype
720
         return self.revision.file_mimetype
718
 
721
 
719
     @file_mimetype.setter
722
     @file_mimetype.setter
720
-    def file_mimetype(self, value):
723
+    def file_mimetype(self, value: str) -> None:
721
         self.revision.file_mimetype = value
724
         self.revision.file_mimetype = value
722
 
725
 
723
     @file_mimetype.expression
726
     @file_mimetype.expression
724
-    def file_mimetype(cls):
727
+    def file_mimetype(cls) -> InstrumentedAttribute:
725
         return ContentRevisionRO.file_mimetype
728
         return ContentRevisionRO.file_mimetype
726
 
729
 
727
     @hybrid_property
730
     @hybrid_property
733
         self.revision.file_content = value
736
         self.revision.file_content = value
734
 
737
 
735
     @file_content.expression
738
     @file_content.expression
736
-    def file_content(cls):
739
+    def file_content(cls) -> InstrumentedAttribute:
737
         return ContentRevisionRO.file_content
740
         return ContentRevisionRO.file_content
738
 
741
 
739
     @hybrid_property
742
     @hybrid_property
740
-    def _properties(self):
743
+    def _properties(self) -> str:
741
         return self.revision.properties
744
         return self.revision.properties
742
 
745
 
743
     @_properties.setter
746
     @_properties.setter
744
-    def _properties(self, value):
747
+    def _properties(self, value: str) -> None:
745
         self.revision.properties = value
748
         self.revision.properties = value
746
 
749
 
747
     @_properties.expression
750
     @_properties.expression
748
-    def _properties(cls):
751
+    def _properties(cls) -> InstrumentedAttribute:
749
         return ContentRevisionRO.properties
752
         return ContentRevisionRO.properties
750
 
753
 
751
     @hybrid_property
754
     @hybrid_property
752
-    def type(self):
755
+    def type(self) -> str:
753
         return self.revision.type
756
         return self.revision.type
754
 
757
 
755
     @type.setter
758
     @type.setter
756
-    def type(self, value):
759
+    def type(self, value: str) -> None:
757
         self.revision.type = value
760
         self.revision.type = value
758
 
761
 
759
     @type.expression
762
     @type.expression
760
-    def type(cls):
763
+    def type(cls) -> InstrumentedAttribute:
761
         return ContentRevisionRO.type
764
         return ContentRevisionRO.type
762
 
765
 
763
     @hybrid_property
766
     @hybrid_property
764
-    def status(self):
767
+    def status(self) -> str:
765
         return self.revision.status
768
         return self.revision.status
766
 
769
 
767
     @status.setter
770
     @status.setter
768
-    def status(self, value):
771
+    def status(self, value: str) -> None:
769
         self.revision.status = value
772
         self.revision.status = value
770
 
773
 
771
     @status.expression
774
     @status.expression
772
-    def status(cls):
775
+    def status(cls) -> InstrumentedAttribute:
773
         return ContentRevisionRO.status
776
         return ContentRevisionRO.status
774
 
777
 
775
     @hybrid_property
778
     @hybrid_property
776
-    def created(self):
779
+    def created(self) -> datetime:
777
         return self.revision.created
780
         return self.revision.created
778
 
781
 
779
     @created.setter
782
     @created.setter
780
-    def created(self, value):
783
+    def created(self, value: datetime) -> None:
781
         self.revision.created = value
784
         self.revision.created = value
782
 
785
 
783
     @created.expression
786
     @created.expression
784
-    def created(cls):
787
+    def created(cls) -> InstrumentedAttribute:
785
         return ContentRevisionRO.created
788
         return ContentRevisionRO.created
786
 
789
 
787
     @hybrid_property
790
     @hybrid_property
788
-    def updated(self):
791
+    def updated(self) -> datetime:
789
         return self.revision.updated
792
         return self.revision.updated
790
 
793
 
791
     @updated.setter
794
     @updated.setter
792
-    def updated(self, value):
795
+    def updated(self, value: datetime) -> None:
793
         self.revision.updated = value
796
         self.revision.updated = value
794
 
797
 
795
     @updated.expression
798
     @updated.expression
796
-    def updated(cls):
799
+    def updated(cls) -> InstrumentedAttribute:
797
         return ContentRevisionRO.updated
800
         return ContentRevisionRO.updated
798
 
801
 
799
     @hybrid_property
802
     @hybrid_property
800
-    def is_deleted(self):
803
+    def is_deleted(self) -> bool:
801
         return self.revision.is_deleted
804
         return self.revision.is_deleted
802
 
805
 
803
     @is_deleted.setter
806
     @is_deleted.setter
804
-    def is_deleted(self, value):
807
+    def is_deleted(self, value: bool) -> None:
805
         self.revision.is_deleted = value
808
         self.revision.is_deleted = value
806
 
809
 
807
     @is_deleted.expression
810
     @is_deleted.expression
808
-    def is_deleted(cls):
811
+    def is_deleted(cls) -> InstrumentedAttribute:
809
         return ContentRevisionRO.is_deleted
812
         return ContentRevisionRO.is_deleted
810
 
813
 
811
     @hybrid_property
814
     @hybrid_property
812
-    def is_archived(self):
815
+    def is_archived(self) -> bool:
813
         return self.revision.is_archived
816
         return self.revision.is_archived
814
 
817
 
815
     @is_archived.setter
818
     @is_archived.setter
816
-    def is_archived(self, value):
819
+    def is_archived(self, value: bool) -> None:
817
         self.revision.is_archived = value
820
         self.revision.is_archived = value
818
 
821
 
819
     @is_archived.expression
822
     @is_archived.expression
820
-    def is_archived(cls):
823
+    def is_archived(cls) -> InstrumentedAttribute:
821
         return ContentRevisionRO.is_archived
824
         return ContentRevisionRO.is_archived
822
 
825
 
823
     @hybrid_property
826
     @hybrid_property
824
-    def revision_type(self):
827
+    def revision_type(self) -> str:
825
         return self.revision.revision_type
828
         return self.revision.revision_type
826
 
829
 
827
     @revision_type.setter
830
     @revision_type.setter
828
-    def revision_type(self, value):
831
+    def revision_type(self, value: str) -> None:
829
         self.revision.revision_type = value
832
         self.revision.revision_type = value
830
 
833
 
831
     @revision_type.expression
834
     @revision_type.expression
832
-    def revision_type(cls):
835
+    def revision_type(cls) -> InstrumentedAttribute:
833
         return ContentRevisionRO.revision_type
836
         return ContentRevisionRO.revision_type
834
 
837
 
835
     @hybrid_property
838
     @hybrid_property
836
-    def workspace_id(self):
839
+    def workspace_id(self) -> int:
837
         return self.revision.workspace_id
840
         return self.revision.workspace_id
838
 
841
 
839
     @workspace_id.setter
842
     @workspace_id.setter
840
-    def workspace_id(self, value):
843
+    def workspace_id(self, value: int) -> None:
841
         self.revision.workspace_id = value
844
         self.revision.workspace_id = value
842
 
845
 
843
     @workspace_id.expression
846
     @workspace_id.expression
844
-    def workspace_id(cls):
847
+    def workspace_id(cls) -> InstrumentedAttribute:
845
         return ContentRevisionRO.workspace_id
848
         return ContentRevisionRO.workspace_id
846
 
849
 
847
     @hybrid_property
850
     @hybrid_property
848
-    def workspace(self):
851
+    def workspace(self) -> Workspace:
849
         return self.revision.workspace
852
         return self.revision.workspace
850
 
853
 
851
     @workspace.setter
854
     @workspace.setter
852
-    def workspace(self, value):
855
+    def workspace(self, value: Workspace) -> None:
853
         self.revision.workspace = value
856
         self.revision.workspace = value
854
 
857
 
855
     @workspace.expression
858
     @workspace.expression
856
-    def workspace(cls):
859
+    def workspace(cls) -> InstrumentedAttribute:
857
         return ContentRevisionRO.workspace
860
         return ContentRevisionRO.workspace
858
 
861
 
859
     @hybrid_property
862
     @hybrid_property
860
-    def parent_id(self):
863
+    def parent_id(self) -> int:
861
         return self.revision.parent_id
864
         return self.revision.parent_id
862
 
865
 
863
     @parent_id.setter
866
     @parent_id.setter
864
-    def parent_id(self, value):
867
+    def parent_id(self, value: int) -> None:
865
         self.revision.parent_id = value
868
         self.revision.parent_id = value
866
 
869
 
867
     @parent_id.expression
870
     @parent_id.expression
868
-    def parent_id(cls):
871
+    def parent_id(cls) -> InstrumentedAttribute:
869
         return ContentRevisionRO.parent_id
872
         return ContentRevisionRO.parent_id
870
 
873
 
871
     @hybrid_property
874
     @hybrid_property
872
-    def parent(self):
875
+    def parent(self) -> 'Content':
873
         return self.revision.parent
876
         return self.revision.parent
874
 
877
 
875
     @parent.setter
878
     @parent.setter
876
-    def parent(self, value):
879
+    def parent(self, value: 'Content') -> None:
877
         self.revision.parent = value
880
         self.revision.parent = value
878
 
881
 
879
     @parent.expression
882
     @parent.expression
880
-    def parent(cls):
883
+    def parent(cls) -> InstrumentedAttribute:
881
         return ContentRevisionRO.parent
884
         return ContentRevisionRO.parent
882
 
885
 
883
     @hybrid_property
886
     @hybrid_property
884
-    def node(self):
887
+    def node(self) -> 'Content':
885
         return self.revision.node
888
         return self.revision.node
886
 
889
 
887
     @node.setter
890
     @node.setter
888
-    def node(self, value):
891
+    def node(self, value: 'Content') -> None:
889
         self.revision.node = value
892
         self.revision.node = value
890
 
893
 
891
     @node.expression
894
     @node.expression
892
-    def node(cls):
895
+    def node(cls) -> InstrumentedAttribute:
893
         return ContentRevisionRO.node
896
         return ContentRevisionRO.node
894
 
897
 
895
     @hybrid_property
898
     @hybrid_property
896
-    def owner(self):
899
+    def owner(self) -> User:
897
         return self.revision.owner
900
         return self.revision.owner
898
 
901
 
899
     @owner.setter
902
     @owner.setter
900
-    def owner(self, value):
903
+    def owner(self, value: User) -> None:
901
         self.revision.owner = value
904
         self.revision.owner = value
902
 
905
 
903
     @owner.expression
906
     @owner.expression
904
-    def owner(cls):
907
+    def owner(cls) -> InstrumentedAttribute:
905
         return ContentRevisionRO.owner
908
         return ContentRevisionRO.owner
906
 
909
 
907
     @hybrid_property
910
     @hybrid_property
908
-    def children(self):
911
+    def children(self) -> ['Content']:
909
         """
912
         """
910
         :return: list of children Content
913
         :return: list of children Content
911
         :rtype Content
914
         :rtype Content
914
         return list(set([revision.node for revision in self.children_revisions]))
917
         return list(set([revision.node for revision in self.children_revisions]))
915
 
918
 
916
     @property
919
     @property
917
-    def revision(self):
920
+    def revision(self) -> ContentRevisionRO:
918
         return self.get_current_revision()
921
         return self.get_current_revision()
919
 
922
 
920
-    def get_current_revision(self):
923
+    def get_current_revision(self) -> ContentRevisionRO:
921
         if not self.revisions:
924
         if not self.revisions:
922
             return self.new_revision()
925
             return self.new_revision()
923
 
926
 
929
         revisions = sorted(self.revisions, key=lambda revision: revision.revision_id)
932
         revisions = sorted(self.revisions, key=lambda revision: revision.revision_id)
930
         return revisions[-1]
933
         return revisions[-1]
931
 
934
 
932
-    def new_revision(self):
935
+    def new_revision(self) -> None:
933
         """
936
         """
934
         Return and assign to this content a new revision.
937
         Return and assign to this content a new revision.
935
         If it's a new content, revision is totally new.
938
         If it's a new content, revision is totally new.
951
                     yield child.node
954
                     yield child.node
952
 
955
 
953
     @hybrid_property
956
     @hybrid_property
954
-    def properties(self):
957
+    def properties(self) -> dict:
955
         """ return a structure decoded from json content of _properties """
958
         """ return a structure decoded from json content of _properties """
956
         if not self._properties:
959
         if not self._properties:
957
             ContentChecker.reset_properties(self)
960
             ContentChecker.reset_properties(self)
958
         return json.loads(self._properties)
961
         return json.loads(self._properties)
959
 
962
 
960
     @properties.setter
963
     @properties.setter
961
-    def properties(self, properties_struct):
964
+    def properties(self, properties_struct: dict) -> None:
962
         """ encode a given structure into json and store it in _properties attribute"""
965
         """ encode a given structure into json and store it in _properties attribute"""
963
         self._properties = json.dumps(properties_struct)
966
         self._properties = json.dumps(properties_struct)
964
         ContentChecker.check_properties(self)
967
         ContentChecker.check_properties(self)
1130
 
1133
 
1131
     revision_id = Column(Integer, ForeignKey('content_revisions.revision_id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
1134
     revision_id = Column(Integer, ForeignKey('content_revisions.revision_id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
1132
     user_id = Column(Integer, ForeignKey('users.user_id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
1135
     user_id = Column(Integer, ForeignKey('users.user_id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
1133
-    view_datetime = Column(DateTime, unique=False, nullable=False, server_default=func.now())
1136
+    #  Default value datetime.utcnow, see: http://stackoverflow.com/a/13370382/801924 (or http://pastebin.com/VLyWktUn)
1137
+    view_datetime = Column(DateTime, unique=False, nullable=False, default=datetime.utcnow)
1134
 
1138
 
1135
     content_revision = relationship(
1139
     content_revision = relationship(
1136
         'ContentRevisionRO',
1140
         'ContentRevisionRO',

+ 5 - 8
tracim/tracim/tests/__init__.py 查看文件

300
 
300
 
301
 class BaseTest(object):
301
 class BaseTest(object):
302
 
302
 
303
-    def _create_workspace(self, name, *args, **kwargs):
303
+    def _create_workspace(self, name, *args, **kwargs) -> Workspace:
304
         """
304
         """
305
         All extra parameters (*args, **kwargs) are for Workspace init
305
         All extra parameters (*args, **kwargs) are for Workspace init
306
         :return: Created workspace instance
306
         :return: Created workspace instance
307
-        :rtype: Workspace
308
         """
307
         """
309
         workspace = Workspace(label=name, *args, **kwargs)
308
         workspace = Workspace(label=name, *args, **kwargs)
310
         DBSession.add(workspace)
309
         DBSession.add(workspace)
313
         eq_(1, DBSession.query(Workspace).filter(Workspace.label == name).count())
312
         eq_(1, DBSession.query(Workspace).filter(Workspace.label == name).count())
314
         return DBSession.query(Workspace).filter(Workspace.label == name).one()
313
         return DBSession.query(Workspace).filter(Workspace.label == name).one()
315
 
314
 
316
-    def _create_content(self, name, workspace, *args, **kwargs):
315
+    def _create_content(self, name, workspace, *args, **kwargs) -> Content:
317
         """
316
         """
318
         All extra parameters (*args, **kwargs) are for Content init
317
         All extra parameters (*args, **kwargs) are for Content init
319
         :return: Created Content instance
318
         :return: Created Content instance
320
-        :rtype: Content
321
         """
319
         """
322
         content = Content(*args, **kwargs)
320
         content = Content(*args, **kwargs)
323
         content.label = name
321
         content.label = name
325
         DBSession.add(content)
323
         DBSession.add(content)
326
         DBSession.flush()
324
         DBSession.flush()
327
 
325
 
328
-        eq_(1, ContentApi.get_base_query().filter(Content.label == name).count())
329
-        return ContentApi.get_base_query().filter(Content.label == name).one()
326
+        eq_(1, ContentApi.get_canonical_query().filter(Content.label == name).count())
327
+        return ContentApi.get_canonical_query().filter(Content.label == name).one()
330
 
328
 
331
 
329
 
332
 class BaseTestThread(BaseTest):
330
 class BaseTestThread(BaseTest):
333
 
331
 
334
-    def _create_thread(self, workspace_name='workspace_1', folder_name='folder_1', thread_name='thread_1'):
332
+    def _create_thread(self, workspace_name='workspace_1', folder_name='folder_1', thread_name='thread_1') -> Content:
335
         """
333
         """
336
         :return: Thread
334
         :return: Thread
337
-        :rtype: Content
338
         """
335
         """
339
         workspace = self._create_workspace(workspace_name)
336
         workspace = self._create_workspace(workspace_name)
340
         folder = self._create_content(folder_name, workspace, type=ContentType.Folder)
337
         folder = self._create_content(folder_name, workspace, type=ContentType.Folder)

+ 1 - 1
tracim/tracim/tests/library/test_workspace.py 查看文件

17
             thread_name='thread_1',
17
             thread_name='thread_1',
18
         )
18
         )
19
         workspace = DBSession.query(Workspace).filter(Workspace.label == 'workspace_1').one()
19
         workspace = DBSession.query(Workspace).filter(Workspace.label == 'workspace_1').one()
20
-        folder = ContentApi.get_base_query().filter(Content.label == 'folder_1').one()
20
+        folder = ContentApi.get_canonical_query().filter(Content.label == 'folder_1').one()
21
         eq_([folder, ], list(workspace.get_valid_children()))
21
         eq_([folder, ], list(workspace.get_valid_children()))

+ 18 - 18
tracim/tracim/tests/models/test_content_revision.py 查看文件

12
 
12
 
13
 class TestContentRevision(BaseTest, TestStandard):
13
 class TestContentRevision(BaseTest, TestStandard):
14
 
14
 
15
+    def _new_from(self, revision):
16
+        excluded_columns = ('revision_id', '_sa_instance_state')
17
+        revision_columns = [attr.key for attr in inspect(revision).attrs if not attr.key in excluded_columns]
18
+        new_revision = ContentRevisionRO()
19
+
20
+        for revision_column in revision_columns:
21
+            old_revision_column_value = getattr(revision, revision_column)
22
+            setattr(new_revision, revision_column, old_revision_column_value)
23
+
24
+        return new_revision
25
+
26
+    def _get_dict_representation(self, revision):
27
+        keys_to_remove = ('updated', '_sa_instance_state')
28
+        dict_repr = OrderedDict(sorted(revision.__dict__.items()))
29
+        for key_to_remove in keys_to_remove:
30
+            dict_repr.pop(key_to_remove, None)
31
+        return dict_repr
32
+
15
     def test_new_revision(self):
33
     def test_new_revision(self):
16
         admin = DBSession.query(User).filter(User.email == 'admin@admin.admin').one()
34
         admin = DBSession.query(User).filter(User.email == 'admin@admin.admin').one()
17
         workspace = self._create_workspace(name='workspace_1')
35
         workspace = self._create_workspace(name='workspace_1')
37
 
55
 
38
         # They must be identical
56
         # They must be identical
39
         eq_(new_revision_by_model_dict, new_revision_by_test_dict)
57
         eq_(new_revision_by_model_dict, new_revision_by_test_dict)
40
-
41
-    def _new_from(self, revision):
42
-        excluded_columns = ('revision_id', '_sa_instance_state')
43
-        revision_columns = [attr.key for attr in inspect(revision).attrs if not attr.key in excluded_columns]
44
-        new_revision = ContentRevisionRO()
45
-
46
-        for revision_column in revision_columns:
47
-            old_revision_column_value = getattr(revision, revision_column)
48
-            setattr(new_revision, revision_column, old_revision_column_value)
49
-
50
-        return new_revision
51
-
52
-    def _get_dict_representation(self, revision):
53
-        keys_to_remove = ('updated', '_sa_instance_state')
54
-        dict_repr = OrderedDict(sorted(revision.__dict__.items()))
55
-        for key_to_remove in keys_to_remove:
56
-            dict_repr.pop(key_to_remove, None)
57
-        return dict_repr