23
23
QgsAbstractFeatureIterator ,
24
24
QgsExpressionContextScope ,
25
25
QgsExpressionContext ,
26
+ QgsVectorDataProvider ,
26
27
NULL
27
28
)
28
29
@@ -44,14 +45,17 @@ class ProviderTestCase(object):
44
45
evaluation are equal.
45
46
'''
46
47
47
- def testGetFeatures (self ):
48
+ def testGetFeatures (self , provider = None , extra_features = [], skip_features = [], changed_attributes = {}, changed_geometries = {} ):
48
49
""" Test that expected results are returned when fetching all features """
49
50
50
51
# IMPORTANT - we do not use `for f in provider.getFeatures()` as we are also
51
52
# testing that existing attributes & geometry in f are overwritten correctly
52
53
# (for f in ... uses a new QgsFeature for every iteration)
53
54
54
- it = self .provider .getFeatures ()
55
+ if not provider :
56
+ provider = self .provider
57
+
58
+ it = provider .getFeatures ()
55
59
f = QgsFeature ()
56
60
attributes = {}
57
61
geometries = {}
@@ -73,16 +77,38 @@ def testGetFeatures(self):
73
77
1 : [1 , 100 , 'Orange' , 'oranGe' , '1' ],
74
78
2 : [2 , 200 , 'Apple' , 'Apple' , '2' ],
75
79
4 : [4 , 400 , 'Honey' , 'Honey' , '4' ]}
76
- self .assertEqual (attributes , expected_attributes , 'Expected {}, got {}' .format (expected_attributes , attributes ))
77
80
78
81
expected_geometries = {1 : 'Point (-70.332 66.33)' ,
79
82
2 : 'Point (-68.2 70.8)' ,
80
83
3 : None ,
81
84
4 : 'Point(-65.32 78.3)' ,
82
85
5 : 'Point(-71.123 78.23)' }
86
+ for f in extra_features :
87
+ expected_attributes [f [0 ]] = f .attributes ()
88
+ if f .hasGeometry ():
89
+ expected_geometries [f [0 ]] = f .geometry ().exportToWkt ()
90
+ else :
91
+ expected_geometries [f [0 ]] = None
92
+
93
+ for i in skip_features :
94
+ del expected_attributes [i ]
95
+ del expected_geometries [i ]
96
+ for i , a in changed_attributes .items ():
97
+ for attr_idx , v in a .items ():
98
+ expected_attributes [i ][attr_idx ] = v
99
+ for i , g , in changed_geometries .items ():
100
+ if g :
101
+ expected_geometries [i ] = g .exportToWkt ()
102
+ else :
103
+ expected_geometries [i ] = None
104
+
105
+ self .assertEqual (attributes , expected_attributes , 'Expected {}, got {}' .format (expected_attributes , attributes ))
106
+
107
+ self .assertEqual (len (expected_geometries ), len (geometries ))
108
+
83
109
for pk , geom in list (expected_geometries .items ()):
84
110
if geom :
85
- assert compareWkt (geom , geometries [pk ]), "Geometry {} mismatch Expected:\n {}\n Got:\n {}\n " .format (pk , geom , geometries [pk ]. exportToWkt () )
111
+ assert compareWkt (geom , geometries [pk ]), "Geometry {} mismatch Expected:\n {}\n Got:\n {}\n " .format (pk , geom , geometries [pk ])
86
112
else :
87
113
self .assertFalse (geometries [pk ], 'Expected null geometry for {}' .format (pk ))
88
114
@@ -652,3 +678,127 @@ def testGetFeaturesWithGeometry(self):
652
678
653
679
assert f .hasGeometry (), 'Expected geometry, got none'
654
680
self .assertTrue (f .isValid ())
681
+
682
+ def testAddFeature (self ):
683
+ if not getattr (self , 'getEditableLayer' , None ):
684
+ return
685
+
686
+ l = self .getEditableLayer ()
687
+ self .assertTrue (l .isValid ())
688
+
689
+ f1 = QgsFeature ()
690
+ f1 .setAttributes ([6 , - 220 , NULL , 'String' , '15' ])
691
+ f1 .setGeometry (QgsGeometry .fromWkt ('Point (-72.345 71.987)' ))
692
+
693
+ f2 = QgsFeature ()
694
+ f2 .setAttributes ([7 , 330 , 'Coconut' , 'CoCoNut' , '13' ])
695
+
696
+ if l .dataProvider ().capabilities () & QgsVectorDataProvider .AddFeatures :
697
+ # expect success
698
+ result , added = l .dataProvider ().addFeatures ([f1 , f2 ])
699
+ self .assertTrue (result , 'Provider reported AddFeatures capability, but returned False to addFeatures' )
700
+ f1 .setId (added [0 ].id ())
701
+ f2 .setId (added [1 ].id ())
702
+
703
+ # check result
704
+ self .testGetFeatures (l .dataProvider (), [f1 , f2 ])
705
+
706
+ # add empty list, should return true for consistency
707
+ self .assertTrue (l .dataProvider ().addFeatures ([]))
708
+
709
+ else :
710
+ # expect fail
711
+ self .assertFalse (l .dataProvider ().addFeatures ([f1 , f2 ]), 'Provider reported no AddFeatures capability, but returned true to addFeatures' )
712
+
713
+ def testDeleteFeatures (self ):
714
+ if not getattr (self , 'getEditableLayer' , None ):
715
+ return
716
+
717
+ l = self .getEditableLayer ()
718
+ self .assertTrue (l .isValid ())
719
+
720
+ #find 2 features to delete
721
+ features = [f for f in l .dataProvider ().getFeatures ()]
722
+ to_delete = [f .id () for f in features if f .attributes ()[0 ] in [1 , 3 ]]
723
+
724
+ if l .dataProvider ().capabilities () & QgsVectorDataProvider .DeleteFeatures :
725
+ # expect success
726
+ result = l .dataProvider ().deleteFeatures (to_delete )
727
+ self .assertTrue (result , 'Provider reported DeleteFeatures capability, but returned False to deleteFeatures' )
728
+
729
+ # check result
730
+ self .testGetFeatures (l .dataProvider (), skip_features = [1 , 3 ])
731
+
732
+ # delete empty list, should return true for consistency
733
+ self .assertTrue (l .dataProvider ().deleteFeatures ([]))
734
+
735
+ else :
736
+ # expect fail
737
+ self .assertFalse (l .dataProvider ().deleteFeatures (to_delete ),
738
+ 'Provider reported no DeleteFeatures capability, but returned true to deleteFeatures' )
739
+
740
+ def testChangeAttributes (self ):
741
+ if not getattr (self , 'getEditableLayer' , None ):
742
+ return
743
+
744
+ l = self .getEditableLayer ()
745
+ self .assertTrue (l .isValid ())
746
+
747
+ #find 2 features to change
748
+ features = [f for f in l .dataProvider ().getFeatures ()]
749
+ # need to keep order here
750
+ to_change = [f for f in features if f .attributes ()[0 ] == 1 ]
751
+ to_change .extend ([f for f in features if f .attributes ()[0 ] == 3 ])
752
+ # changes by feature id, for changeAttributeValues call
753
+ changes = {to_change [0 ].id (): {1 : 501 , 3 : 'new string' }, to_change [1 ].id (): {1 : 502 , 4 : 'NEW' }}
754
+ # changes by pk, for testing after retrieving changed features
755
+ new_attr_map = {1 : {1 : 501 , 3 : 'new string' }, 3 : {1 : 502 , 4 : 'NEW' }}
756
+
757
+ if l .dataProvider ().capabilities () & QgsVectorDataProvider .ChangeAttributeValues :
758
+ # expect success
759
+ result = l .dataProvider ().changeAttributeValues (changes )
760
+ self .assertTrue (result , 'Provider reported ChangeAttributeValues capability, but returned False to changeAttributeValues' )
761
+
762
+ # check result
763
+ self .testGetFeatures (l .dataProvider (), changed_attributes = new_attr_map )
764
+
765
+ # change empty list, should return true for consistency
766
+ self .assertTrue (l .dataProvider ().changeAttributeValues ({}))
767
+
768
+ else :
769
+ # expect fail
770
+ self .assertFalse (l .dataProvider ().changeAttributeValues (changes ),
771
+ 'Provider reported no ChangeAttributeValues capability, but returned true to changeAttributeValues' )
772
+
773
+ def testChangeGeometries (self ):
774
+ if not getattr (self , 'getEditableLayer' , None ):
775
+ return
776
+
777
+ l = self .getEditableLayer ()
778
+ self .assertTrue (l .isValid ())
779
+
780
+ # find 2 features to change
781
+ features = [f for f in l .dataProvider ().getFeatures ()]
782
+ to_change = [f for f in features if f .attributes ()[0 ] == 1 ]
783
+ to_change .extend ([f for f in features if f .attributes ()[0 ] == 3 ])
784
+ # changes by feature id, for changeGeometryValues call
785
+ changes = {to_change [0 ].id (): QgsGeometry .fromWkt ('Point (10 20)' ), to_change [1 ].id (): QgsGeometry ()}
786
+ # changes by pk, for testing after retrieving changed features
787
+ new_geom_map = {1 : QgsGeometry .fromWkt ('Point ( 10 20 )' ), 3 : QgsGeometry ()}
788
+
789
+ if l .dataProvider ().capabilities () & QgsVectorDataProvider .ChangeGeometries :
790
+ # expect success
791
+ result = l .dataProvider ().changeGeometryValues (changes )
792
+ self .assertTrue (result ,
793
+ 'Provider reported ChangeGeometries capability, but returned False to changeGeometryValues' )
794
+
795
+ # check result
796
+ self .testGetFeatures (l .dataProvider (), changed_geometries = new_geom_map )
797
+
798
+ # change empty list, should return true for consistency
799
+ self .assertTrue (l .dataProvider ().changeGeometryValues ({}))
800
+
801
+ else :
802
+ # expect fail
803
+ self .assertFalse (l .dataProvider ().changeGeometryValues (changes ),
804
+ 'Provider reported no ChangeGeometries capability, but returned true to changeGeometryValues' )
0 commit comments