1
# ***************************************************************************
2
# * Copyright (c) 2003 Juergen Riegel <juergen.riegel@web.de> *
4
# * This file is part of the FreeCAD CAx development system. *
6
# * This program is free software; you can redistribute it and/or modify *
7
# * it under the terms of the GNU Lesser General Public License (LGPL) *
8
# * as published by the Free Software Foundation; either version 2 of *
9
# * the License, or (at your option) any later version. *
10
# * for detail see the LICENCE text file. *
12
# * FreeCAD is distributed in the hope that it will be useful, *
13
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
# * GNU Library General Public License for more details. *
17
# * You should have received a copy of the GNU Library General Public *
18
# * License along with FreeCAD; if not, write to the Free Software *
19
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
22
# ***************************************************************************/
24
import FreeCAD, os, unittest, tempfile
25
from FreeCAD import Base
27
import xml.etree.ElementTree as ET
29
# ---------------------------------------------------------------------------
30
# define the functions to test the FreeCAD Document code
31
# ---------------------------------------------------------------------------
35
def __init__(self, obj):
41
return self.Dictionary
43
def loads(self, data):
44
self.Dictionary = data
47
class DocumentBasicCases(unittest.TestCase):
49
self.Doc = FreeCAD.newDocument("CreateTest")
51
def saveAndRestore(self):
52
# saving and restoring
53
SaveName = tempfile.gettempdir() + os.sep + "CreateTest.FCStd"
54
self.Doc.saveAs(SaveName)
55
FreeCAD.closeDocument("CreateTest")
56
self.Doc = FreeCAD.open(SaveName)
59
def testAccessByNameOrID(self):
60
obj = self.Doc.addObject("App::DocumentObject", "MyName")
62
with self.assertRaises(TypeError):
63
self.Doc.getObject([1])
65
self.assertEqual(self.Doc.getObject(obj.Name), obj)
66
self.assertEqual(self.Doc.getObject("Unknown"), None)
67
self.assertEqual(self.Doc.getObject(obj.ID), obj)
68
self.assertEqual(self.Doc.getObject(obj.ID + 1), None)
70
def testCreateDestroy(self):
71
# FIXME: Causes somehow a ref count error but it's _not_ FreeCAD.getDocument()!!!
72
# If we remove the whole method no error appears.
73
self.assertTrue(FreeCAD.getDocument("CreateTest") is not None, "Creating Document failed")
75
def testAddition(self):
76
# Cannot write a real test case for that but when debugging the
77
# C-code there shouldn't be a memory leak (see rev. 1814)
78
self.Doc.openTransaction("Add")
79
L1 = self.Doc.addObject("App::FeatureTest", "Label")
80
self.Doc.commitTransaction()
83
def testAddRemoveUndo(self):
85
self.Doc.openTransaction("Add")
86
obj = self.Doc.addObject("App::FeatureTest", "Label")
87
self.Doc.commitTransaction()
88
self.Doc.removeObject(obj.Name)
92
def testNoRecompute(self):
93
L1 = self.Doc.addObject("App::FeatureTest", "Label")
95
L1.TypeNoRecompute = 2
96
execcount = L1.ExecCount
97
objectcount = self.Doc.recompute()
98
self.assertEqual(objectcount, 0)
99
self.assertEqual(L1.ExecCount, execcount)
101
def testNoRecomputeParent(self):
102
L1 = self.Doc.addObject("App::FeatureTest", "Child")
103
L2 = self.Doc.addObject("App::FeatureTest", "Parent")
106
L1.TypeNoRecompute = 2
107
countChild = L1.ExecCount
108
countParent = L2.ExecCount
109
objectcount = self.Doc.recompute()
110
self.assertEqual(objectcount, 1)
111
self.assertEqual(L1.ExecCount, countChild)
112
self.assertEqual(L2.ExecCount, countParent + 1)
115
countChild = L1.ExecCount
116
countParent = L2.ExecCount
117
objectcount = self.Doc.recompute()
118
self.assertEqual(objectcount, 1)
119
self.assertEqual(L1.ExecCount, countChild)
120
self.assertEqual(L2.ExecCount, countParent + 1)
122
L1.enforceRecompute()
123
countChild = L1.ExecCount
124
countParent = L2.ExecCount
125
objectcount = self.Doc.recompute()
126
self.assertEqual(objectcount, 2)
127
self.assertEqual(L1.ExecCount, countChild + 1)
128
self.assertEqual(L2.ExecCount, countParent + 1)
130
def testAbortTransaction(self):
131
self.Doc.openTransaction("Add")
132
obj = self.Doc.addObject("App::FeatureTest", "Label")
133
self.Doc.abortTransaction()
134
TempPath = tempfile.gettempdir()
135
SaveName = TempPath + os.sep + "SaveRestoreTests.FCStd"
136
self.Doc.saveAs(SaveName)
138
def testRemoval(self):
139
# Cannot write a real test case for that but when debugging the
140
# C-code there shouldn't be a memory leak (see rev. 1814)
141
self.Doc.openTransaction("Add")
142
L1 = self.Doc.addObject("App::FeatureTest", "Label")
143
self.Doc.commitTransaction()
144
self.Doc.openTransaction("Rem")
145
L1 = self.Doc.removeObject("Label")
146
self.Doc.commitTransaction()
148
def testObjects(self):
149
L1 = self.Doc.addObject("App::FeatureTest", "Label_1")
150
# call members to check for errors in ref counting
151
self.Doc.ActiveObject
154
self.Doc.UndoRedoMemSize
156
# test read only mechanismus
158
self.Doc.UndoCount = 3
160
FreeCAD.Console.PrintLog(" exception thrown, OK\n")
162
self.fail("no exception thrown")
167
self.assertTrue(L1.Integer == 4711)
168
self.assertTrue(L1.Float - 47.11 < 0.001)
169
self.assertTrue(L1.Bool == True)
170
self.assertTrue(L1.String == "4711")
171
# temporarily not checked because of strange behavior of boost::filesystem JR
172
# self.assertTrue(L1.Path == "c:/temp")
173
self.assertTrue(float(L1.Angle) - 3.0 < 0.001)
174
self.assertTrue(float(L1.Distance) - 47.11 < 0.001)
176
# test basic property stuff
177
self.assertTrue(not L1.getDocumentationOfProperty("Source1") == "")
178
self.assertTrue(L1.getGroupOfProperty("Source1") == "Feature Test")
179
self.assertTrue(L1.getTypeOfProperty("Source1") == [])
180
self.assertTrue(L1.getEnumerationsOfProperty("Source1") is None)
182
# test the constraint types ( both are constraint to percent range)
183
self.assertTrue(L1.ConstraintInt == 5)
184
self.assertTrue(L1.ConstraintFloat - 5.0 < 0.001)
185
L1.ConstraintInt = 500
186
L1.ConstraintFloat = 500.0
187
self.assertTrue(L1.ConstraintInt == 100)
188
self.assertTrue(L1.ConstraintFloat - 100.0 < 0.001)
189
L1.ConstraintInt = -500
190
L1.ConstraintFloat = -500.0
191
self.assertTrue(L1.ConstraintInt == 0)
192
self.assertTrue(L1.ConstraintFloat - 0.0 < 0.001)
195
# in App::FeatureTest the current value is set to 4
196
self.assertTrue(L1.Enum == "Four")
198
self.assertTrue(L1.Enum == "Three", "Different value to 'Three'")
200
self.assertTrue(L1.Enum == "Two", "Different value to 'Two'")
202
L1.Enum = "SurelyNotInThere!"
204
FreeCAD.Console.PrintLog(" exception thrown, OK\n")
206
self.fail("no exception thrown")
208
sorted(L1.getEnumerationsOfProperty("Enum"))
209
== sorted(["Zero", "One", "Two", "Three", "Four"])
212
# self.assertTrue(L1.IntegerList == [4711] )
214
# self.assertTrue(f -47.11<0.001 )
215
# self.assertTrue(L1.Matrix == [1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0] )
216
# self.assertTrue(L1.Vector == [1.0,2.0,3.0])
218
self.assertTrue(L1.Label == "Label_1", "Invalid object name")
221
self.assertTrue(L1.Label == "Label_2", "Invalid object name")
222
self.Doc.removeObject("Label_1")
225
enumeration_choices = ["one", "two"]
226
obj = self.Doc.addObject("App::FeaturePython", "Label_2")
227
obj.addProperty("App::PropertyEnumeration", "myEnumeration", "Enum", "mytest")
228
with self.assertRaises(ValueError):
229
obj.myEnumeration = enumeration_choices[0]
231
obj.myEnumeration = enumeration_choices
232
obj.myEnumeration = 0
233
self.Doc.openTransaction("Modify enum")
234
obj.myEnumeration = 1
235
self.assertTrue(obj.myEnumeration, enumeration_choices[1])
236
self.Doc.commitTransaction()
238
self.assertTrue(obj.myEnumeration, enumeration_choices[0])
240
def testWrongTypes(self):
241
with self.assertRaises(TypeError):
242
self.Doc.addObject("App::DocumentObjectExtension")
247
with self.assertRaises(TypeError):
248
self.Doc.addObject(type="App::DocumentObjectExtension", objProxy=Feature(), attach=True)
250
ext = FreeCAD.Base.TypeId.fromName("App::DocumentObjectExtension")
251
self.assertEqual(ext.createInstance(), None)
253
obj = self.Doc.addObject("App::FeaturePython", "Object")
254
with self.assertRaises(TypeError):
255
obj.addProperty("App::DocumentObjectExtension", "Property")
257
with self.assertRaises(TypeError):
258
self.Doc.findObjects(Type="App::DocumentObjectExtension")
260
e = FreeCAD.Base.TypeId.fromName("App::LinkExtensionPython")
261
self.assertIsNone(e.createInstance())
264
obj = self.Doc.addObject("App::DocumentObject", viewType="App::Extension")
265
self.assertIsNone(obj.ViewObject)
270
def testDuplicateLinks(self):
271
obj = self.Doc.addObject("App::FeatureTest", "obj")
272
grp = self.Doc.addObject("App::DocumentObjectGroup", "group")
273
grp.Group = [obj, obj]
274
self.Doc.removeObject(obj.Name)
275
self.assertListEqual(grp.Group, [])
277
def testPlacementList(self):
278
obj = self.Doc.addObject("App::FeaturePython", "Label")
279
obj.addProperty("App::PropertyPlacementList", "PlmList")
280
plm = FreeCAD.Placement()
282
plm.Rotation = (0, 0, 1, 0)
284
cpy = self.Doc.copyObject(obj)
285
self.assertListEqual(obj.PlmList, cpy.PlmList)
287
def testRawAxis(self):
288
obj = self.Doc.addObject("App::FeaturePython", "Label")
289
obj.addProperty("App::PropertyPlacement", "Plm")
290
obj.addProperty("App::PropertyRotation", "Rot")
291
obj.Plm.Rotation.Axis = (1, 2, 3)
292
obj.Rot.Axis = (3, 2, 1)
294
# saving and restoring
295
SaveName = tempfile.gettempdir() + os.sep + "CreateTest.FCStd"
296
self.Doc.saveAs(SaveName)
297
FreeCAD.closeDocument("CreateTest")
298
self.Doc = FreeCAD.open(SaveName)
299
obj = self.Doc.ActiveObject
301
self.assertEqual(obj.Plm.Rotation.RawAxis.x, 1)
302
self.assertEqual(obj.Plm.Rotation.RawAxis.y, 2)
303
self.assertEqual(obj.Plm.Rotation.RawAxis.z, 3)
305
self.assertEqual(obj.Rot.RawAxis.x, 3)
306
self.assertEqual(obj.Rot.RawAxis.y, 2)
307
self.assertEqual(obj.Rot.RawAxis.z, 1)
309
def testAddRemove(self):
310
L1 = self.Doc.addObject("App::FeatureTest", "Label_1")
312
self.Doc.removeObject(L1.Name)
316
self.assertTrue(True)
318
self.assertTrue(False)
321
# What do we expect here?
322
self.Doc.openTransaction("AddRemove")
323
L2 = self.Doc.addObject("App::FeatureTest", "Label_2")
324
self.Doc.removeObject(L2.Name)
325
self.Doc.commitTransaction()
330
self.assertTrue(True)
332
self.assertTrue(False)
335
def testSubObject(self):
336
obj = self.Doc.addObject("App::Origin", "Origin")
339
res = obj.getSubObject("X_Axis", retType=2)
341
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
344
res = obj.getSubObject("Y_Axis", retType=2)
346
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(0, 1, 0)), 0.0
349
res = obj.getSubObject("Z_Axis", retType=2)
351
res[1].multVec(FreeCAD.Vector(1, 0, 0)).getAngle(FreeCAD.Vector(0, 0, 1)), 0.0
354
res = obj.getSubObject("XY_Plane", retType=2)
356
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(0, 0, 1)), 0.0
359
res = obj.getSubObject("XZ_Plane", retType=2)
361
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(0, -1, 0)), 0.0
364
res = obj.getSubObject("YZ_Plane", retType=2)
366
res[1].multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
369
res = obj.getSubObject("YZ_Plane", retType=3)
371
res.multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
374
res = obj.getSubObject("YZ_Plane", retType=4)
376
res.multVec(FreeCAD.Vector(0, 0, 1)).getAngle(FreeCAD.Vector(1, 0, 0)), 0.0
380
obj.getSubObject(("XY_Plane", "YZ_Plane"), retType=4)[0],
381
obj.getSubObject("XY_Plane", retType=4),
384
obj.getSubObject(("XY_Plane", "YZ_Plane"), retType=4)[1],
385
obj.getSubObject("YZ_Plane", retType=4),
388
# Create a second origin object
389
obj2 = self.Doc.addObject("App::Origin", "Origin2")
392
# Use the names of the origin's out-list
393
for i in obj2.OutList:
394
self.assertEqual(obj2.getSubObject(i.Name, retType=1).Name, i.Name)
395
# Add a '.' to the names
396
for i in obj2.OutList:
397
self.assertEqual(obj2.getSubObject(i.Name + ".", retType=1).Name, i.Name)
399
def testExtensions(self):
400
# we try to create a normal python object and add an extension to it
401
obj = self.Doc.addObject("App::DocumentObject", "Extension_1")
402
grp = self.Doc.addObject("App::DocumentObject", "Extension_2")
403
# we should have all methods we need to handle extensions
405
self.assertTrue(not grp.hasExtension("App::GroupExtensionPython"))
406
grp.addExtension("App::GroupExtensionPython")
407
self.assertTrue(grp.hasExtension("App::GroupExtension"))
408
self.assertTrue(grp.hasExtension("App::GroupExtensionPython"))
410
self.assertTrue(len(grp.Group) == 1)
411
self.assertTrue(grp.Group[0] == obj)
413
self.assertTrue(False)
415
# test if the method override works
417
def allowObject(self, obj):
420
callback = SpecialGroup()
421
grp2 = self.Doc.addObject("App::FeaturePython", "Extension_3")
422
grp2.addExtension("App::GroupExtensionPython")
423
grp2.Proxy = callback
426
self.assertTrue(grp2.hasExtension("App::GroupExtension"))
428
self.assertTrue(len(grp2.Group) == 0)
430
self.assertTrue(True)
432
self.Doc.removeObject(grp.Name)
433
self.Doc.removeObject(grp2.Name)
434
self.Doc.removeObject(obj.Name)
439
def testExtensionBug0002785(self):
441
def __init__(self, obj):
442
obj.addExtension("App::GroupExtensionPython")
444
obj = self.Doc.addObject("App::DocumentObject", "myObj")
446
self.assertTrue(obj.hasExtension("App::GroupExtension"))
447
self.assertTrue(obj.hasExtension("App::GroupExtensionPython"))
448
self.Doc.removeObject(obj.Name)
451
def testExtensionGroup(self):
452
obj = self.Doc.addObject("App::DocumentObject", "Obj")
453
grp = self.Doc.addObject("App::FeaturePython", "Extension_2")
454
grp.addExtension("App::GroupExtensionPython")
456
self.assertTrue(obj in grp.Group)
458
def testExtensionBugViewProvider(self):
460
def __init__(self, obj):
461
obj.addExtension("App::GroupExtensionPython")
463
class LayerViewProvider:
464
def __init__(self, obj):
465
obj.addExtension("Gui::ViewProviderGroupExtensionPython")
468
obj = self.Doc.addObject("App::FeaturePython", "Layer")
470
self.assertTrue(obj.hasExtension("App::GroupExtension"))
473
LayerViewProvider(obj.ViewObject)
474
self.assertTrue(obj.ViewObject.hasExtension("Gui::ViewProviderGroupExtension"))
475
self.assertTrue(obj.ViewObject.hasExtension("Gui::ViewProviderGroupExtensionPython"))
477
self.Doc.removeObject(obj.Name)
480
def testHasSelection(self):
484
self.assertFalse(FreeCADGui.Selection.hasSelection("", 1))
486
def testPropertyLink_Issue2902Part1(self):
487
o1 = self.Doc.addObject("App::FeatureTest", "test1")
488
o2 = self.Doc.addObject("App::FeatureTest", "test2")
489
o3 = self.Doc.addObject("App::FeatureTest", "test3")
492
self.assertEqual(o1.Link, o2)
494
self.assertEqual(o1.Link, o3)
495
o2.Placement = FreeCAD.Placement()
496
self.assertEqual(o1.Link, o3)
498
def testProp_NonePropertyLink(self):
499
obj1 = self.Doc.addObject("App::FeaturePython", "Obj1")
500
obj2 = self.Doc.addObject("App::FeaturePython", "Obj2")
505
"Link to another feature",
506
FreeCAD.PropertyType.Prop_None,
511
self.assertEqual(obj1.MustExecute, True)
513
def testProp_OutputPropertyLink(self):
514
obj1 = self.Doc.addObject("App::FeaturePython", "Obj1")
515
obj2 = self.Doc.addObject("App::FeaturePython", "Obj2")
520
"Link to another feature",
521
FreeCAD.PropertyType.Prop_Output,
526
self.assertEqual(obj1.MustExecute, False)
528
def testAttributeOfDynamicProperty(self):
529
obj = self.Doc.addObject("App::FeaturePython", "Obj")
530
# Prop_NoPersist is the enum with the highest value
531
max_value = FreeCAD.PropertyType.Prop_NoPersist
533
for i in range(0, max_value + 1):
534
obj.addProperty("App::PropertyString", "String" + str(i), "", "", i)
535
list_of_types.append(obj.getTypeOfProperty("String" + str(i)))
537
# saving and restoring
538
SaveName = tempfile.gettempdir() + os.sep + "CreateTest.FCStd"
539
self.Doc.saveAs(SaveName)
540
FreeCAD.closeDocument("CreateTest")
541
self.Doc = FreeCAD.open(SaveName)
543
obj = self.Doc.ActiveObject
544
for i in range(0, max_value):
545
types = obj.getTypeOfProperty("String" + str(i))
546
self.assertEqual(list_of_types[i], types)
548
# A property with flag Prop_NoPersist won't be saved to the file
549
with self.assertRaises(AttributeError):
550
obj.getTypeOfProperty("String" + str(max_value))
552
def testNotification_Issue2902Part2(self):
553
o = self.Doc.addObject("App::FeatureTest", "test")
556
o.Placement = FreeCAD.Placement()
558
self.assertEqual(o.Placement.Base.x, 0)
559
o.Placement.Base.x = 5
560
self.assertEqual(o.Placement.Base.x, 5)
562
def testNotification_Issue2996(self):
563
if not FreeCAD.GuiUp:
566
# works only if Gui is shown
568
def __init__(self, vobj):
571
def attach(self, vobj):
572
self.ViewObject = vobj
573
self.Object = vobj.Object
575
def claimChildren(self):
576
children = [self.Object.Link]
579
obj = self.Doc.addObject("App::FeaturePython", "Sketch")
580
obj.addProperty("App::PropertyLink", "Link")
581
ViewProvider(obj.ViewObject)
583
ext = self.Doc.addObject("App::FeatureTest", "Extrude")
586
sli = self.Doc.addObject("App::FeaturePython", "Slice")
587
sli.addProperty("App::PropertyLink", "Link").Link = ext
588
ViewProvider(sli.ViewObject)
590
com = self.Doc.addObject("App::FeaturePython", "CompoundFilter")
591
com.addProperty("App::PropertyLink", "Link").Link = sli
592
ViewProvider(com.ViewObject)
596
self.assertEqual(ext.Link, obj)
597
self.assertNotEqual(ext.Link, sli)
599
def testIssue4823(self):
600
# https://forum.freecad.org/viewtopic.php?f=3&t=52775
601
# The issue was only visible in GUI mode and it crashed in the tree view
602
obj = self.Doc.addObject("App::Origin")
603
self.Doc.removeObject(obj.Name)
605
def testSamePropertyOfLinkAndLinkedObject(self):
606
# See also https://github.com/FreeCAD/FreeCAD/pull/6787
607
test = self.Doc.addObject("App::FeaturePython", "Python")
608
link = self.Doc.addObject("App::Link", "Link")
609
test.addProperty("App::PropertyFloat", "Test")
610
link.addProperty("App::PropertyFloat", "Test")
611
link.LinkedObject = test
612
# saving and restoring
613
SaveName = tempfile.gettempdir() + os.sep + "CreateTest.FCStd"
614
self.Doc.saveAs(SaveName)
615
FreeCAD.closeDocument("CreateTest")
616
self.Doc = FreeCAD.open(SaveName)
617
self.assertIn("Test", self.Doc.Python.PropertiesList)
618
self.assertIn("Test", self.Doc.Link.PropertiesList)
620
def testNoProxy(self):
621
test = self.Doc.addObject("App::DocumentObject", "Object")
622
test.addProperty("App::PropertyPythonObject", "Dictionary")
623
test.Dictionary = {"Stored data": [3, 5, 7]}
625
doc = self.saveAndRestore()
628
self.assertEqual(obj.Dictionary, {"Stored data": [3, 5, 7]})
630
def testWithProxy(self):
631
test = self.Doc.addObject("App::FeaturePython", "Python")
633
proxy.Dictionary["Stored data"] = [3, 5, 7]
635
doc = self.saveAndRestore()
636
obj = doc.Python.Proxy
638
self.assertEqual(obj.Dictionary, {"Stored data": [3, 5, 7]})
640
def testContent(self):
641
test = self.Doc.addObject("App::FeaturePython", "Python")
642
types = Base.TypeId.getAllDerivedFrom("App::Property")
645
test.addProperty(type.Name, type.Name.replace(":", "_"))
646
print("Add property type: {}".format(type.Name))
647
except Exception as e:
649
root = ET.fromstring(test.Content)
650
self.assertEqual(root.tag, "Properties")
654
FreeCAD.closeDocument("CreateTest")
657
# class must be defined in global scope to allow it to be reloaded on document open
658
class SaveRestoreSpecialGroup:
659
def __init__(self, obj):
660
obj.addExtension("App::GroupExtensionPython")
663
def allowObject(self, obj):
667
# class must be defined in global scope to allow it to be reloaded on document open
668
class SaveRestoreSpecialGroupViewProvider:
669
def __init__(self, obj):
670
obj.addExtension("Gui::ViewProviderGroupExtensionPython")
673
def testFunction(self):
677
class DocumentSaveRestoreCases(unittest.TestCase):
679
self.Doc = FreeCAD.newDocument("SaveRestoreTests")
680
L1 = self.Doc.addObject("App::FeatureTest", "Label_1")
681
L2 = self.Doc.addObject("App::FeatureTest", "Label_2")
682
L3 = self.Doc.addObject("App::FeatureTest", "Label_3")
683
self.TempPath = tempfile.gettempdir()
684
FreeCAD.Console.PrintLog(" Using temp path: " + self.TempPath + "\n")
686
def testSaveAndRestore(self):
687
# saving and restoring
688
SaveName = self.TempPath + os.sep + "SaveRestoreTests.FCStd"
689
self.assertTrue(self.Doc.Label_1.TypeTransient == 4711)
690
self.Doc.Label_1.TypeTransient = 4712
692
self.Doc.Label_1.Link = self.Doc.Label_2
693
self.Doc.Label_2.Link = self.Doc.Label_3
694
self.Doc.Label_1.LinkSub = (self.Doc.Label_2, ["Sub1", "Sub2"])
695
self.Doc.Label_2.LinkSub = (self.Doc.Label_3, ["Sub3", "Sub4"])
697
self.Doc.saveAs(SaveName)
698
FreeCAD.closeDocument("SaveRestoreTests")
699
self.Doc = FreeCAD.open(SaveName)
700
self.assertTrue(self.Doc.Label_1.Integer == 4711)
701
self.assertTrue(self.Doc.Label_2.Integer == 4711)
703
self.assertTrue(self.Doc.Label_1.Link == self.Doc.Label_2)
704
self.assertTrue(self.Doc.Label_2.Link == self.Doc.Label_3)
705
self.assertTrue(self.Doc.Label_1.LinkSub == (self.Doc.Label_2, ["Sub1", "Sub2"]))
706
self.assertTrue(self.Doc.Label_2.LinkSub == (self.Doc.Label_3, ["Sub3", "Sub4"]))
707
# do NOT save transient properties
708
self.assertTrue(self.Doc.Label_1.TypeTransient == 4711)
709
self.assertTrue(self.Doc == FreeCAD.getDocument(self.Doc.Name))
711
def testRestore(self):
712
Doc = FreeCAD.newDocument("RestoreTests")
713
Doc.addObject("App::FeatureTest", "Label_1")
714
# saving and restoring
715
FileName = self.TempPath + os.sep + "Test2.FCStd"
717
# restore must first clear the current content
719
self.assertTrue(len(Doc.Objects) == 1)
720
FreeCAD.closeDocument("RestoreTests")
722
def testActiveDocument(self):
724
Second = FreeCAD.newDocument("Active")
725
FreeCAD.closeDocument("Active")
727
# There might be no active document anymore
728
# This also checks for dangling pointers
729
Active = FreeCAD.activeDocument()
730
# Second is still a valid object
731
self.assertTrue(Second != Active)
733
# Okay, no document open
734
self.assertTrue(True)
736
def testExtensionSaveRestore(self):
737
# saving and restoring
738
SaveName = self.TempPath + os.sep + "SaveRestoreExtensions.FCStd"
739
Doc = FreeCAD.newDocument("SaveRestoreExtensions")
740
# we try to create a normal python object and add an extension to it
741
obj = Doc.addObject("App::DocumentObject", "Obj")
742
grp1 = Doc.addObject("App::DocumentObject", "Extension_1")
743
grp2 = Doc.addObject("App::FeaturePython", "Extension_2")
745
grp1.addExtension("App::GroupExtensionPython")
746
SaveRestoreSpecialGroup(grp2)
748
SaveRestoreSpecialGroupViewProvider(grp2.ViewObject)
752
FreeCAD.closeDocument("SaveRestoreExtensions")
753
Doc = FreeCAD.open(SaveName)
755
self.assertTrue(Doc.Extension_1.hasExtension("App::GroupExtension"))
756
self.assertTrue(Doc.Extension_2.hasExtension("App::GroupExtension"))
757
self.assertTrue(Doc.Extension_2.Group[0] is Doc.Obj)
758
self.assertTrue(hasattr(Doc.Extension_2.Proxy, "allowObject"))
762
Doc.Extension_2.ViewObject.hasExtension("Gui::ViewProviderGroupExtensionPython")
764
self.assertTrue(hasattr(Doc.Extension_2.ViewObject.Proxy, "testFunction"))
766
FreeCAD.closeDocument("SaveRestoreExtensions")
768
def testPersistenceContentDump(self):
769
# test smallest level... property
770
self.Doc.Label_1.Vector = (1, 2, 3)
771
dump = self.Doc.Label_1.dumpPropertyContent("Vector", Compression=9)
772
self.Doc.Label_2.restorePropertyContent("Vector", dump)
773
self.assertEqual(self.Doc.Label_1.Vector, self.Doc.Label_2.Vector)
775
# next higher: object
776
self.Doc.Label_1.Distance = 12
777
self.Doc.Label_1.String = "test"
778
dump = self.Doc.Label_1.dumpContent()
779
self.Doc.Label_3.restoreContent(dump)
780
self.assertEqual(self.Doc.Label_1.Distance, self.Doc.Label_3.Distance)
781
self.assertEqual(self.Doc.Label_1.String, self.Doc.Label_3.String)
783
# highest level: document
784
dump = self.Doc.dumpContent(9)
785
Doc = FreeCAD.newDocument("DumpTest")
786
Doc.restoreContent(dump)
787
self.assertEqual(len(self.Doc.Objects), len(Doc.Objects))
788
self.assertEqual(self.Doc.Label_1.Distance, Doc.Label_1.Distance)
789
self.assertEqual(self.Doc.Label_1.String, Doc.Label_1.String)
790
self.assertEqual(self.Doc.Label_1.Vector, Doc.Label_1.Vector)
791
FreeCAD.closeDocument("DumpTest")
795
FreeCAD.closeDocument("SaveRestoreTests")
798
class DocumentRecomputeCases(unittest.TestCase):
800
self.Doc = FreeCAD.newDocument("RecomputeTests")
801
self.L1 = self.Doc.addObject("App::FeatureTest", "Label_1")
802
self.L2 = self.Doc.addObject("App::FeatureTest", "Label_2")
803
self.L3 = self.Doc.addObject("App::FeatureTest", "Label_3")
805
def testDescent(self):
806
# testing the up and downstream stuff
807
FreeCAD.Console.PrintLog("def testDescent(self):Testcase not implemented\n")
808
self.L1.Link = self.L2
809
self.L2.Link = self.L3
811
def testRecompute(self):
813
# sequence to test recompute behaviour
820
L1 = self.Doc.addObject("App::FeatureTest", "Label_1")
821
L2 = self.Doc.addObject("App::FeatureTest", "Label_2")
822
L3 = self.Doc.addObject("App::FeatureTest", "Label_3")
823
L4 = self.Doc.addObject("App::FeatureTest", "Label_4")
824
L5 = self.Doc.addObject("App::FeatureTest", "Label_5")
825
L6 = self.Doc.addObject("App::FeatureTest", "Label_6")
826
L7 = self.Doc.addObject("App::FeatureTest", "Label_7")
827
L8 = self.Doc.addObject("App::FeatureTest", "Label_8")
828
L1.LinkList = [L2, L3, L6]
831
L3.LinkList = [L5, L6]
832
L7.Link = L8 # make second root
834
self.assertTrue(L7 in self.Doc.RootObjects)
835
self.assertTrue(L1 in self.Doc.RootObjects)
837
self.assertTrue(len(self.Doc.Objects) == len(self.Doc.TopologicalSortedObjects))
841
for obj in self.Doc.TopologicalSortedObjects:
846
self.assertTrue(seqDic[L2] > seqDic[L1])
847
self.assertTrue(seqDic[L3] > seqDic[L1])
848
self.assertTrue(seqDic[L5] > seqDic[L2])
849
self.assertTrue(seqDic[L5] > seqDic[L3])
850
self.assertTrue(seqDic[L5] > seqDic[L1])
854
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
856
self.assertTrue(self.Doc.recompute() == 4)
859
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
861
L5.enforceRecompute()
864
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
866
self.assertTrue(self.Doc.recompute() == 4)
869
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
871
L4.enforceRecompute()
872
self.assertTrue(self.Doc.recompute() == 3)
875
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
877
L5.enforceRecompute()
878
self.assertTrue(self.Doc.recompute() == 4)
881
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
883
L6.enforceRecompute()
884
self.assertTrue(self.Doc.recompute() == 3)
887
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
889
L2.enforceRecompute()
890
self.assertTrue(self.Doc.recompute() == 2)
893
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
895
L1.enforceRecompute()
896
self.assertTrue(self.Doc.recompute() == 1)
899
== (L1.ExecCount, L2.ExecCount, L3.ExecCount, L4.ExecCount, L5.ExecCount, L6.ExecCount)
902
self.Doc.removeObject(L1.Name)
903
self.Doc.removeObject(L2.Name)
904
self.Doc.removeObject(L3.Name)
905
self.Doc.removeObject(L4.Name)
906
self.Doc.removeObject(L5.Name)
907
self.Doc.removeObject(L6.Name)
908
self.Doc.removeObject(L7.Name)
909
self.Doc.removeObject(L8.Name)
913
FreeCAD.closeDocument("RecomputeTests")
916
class UndoRedoCases(unittest.TestCase):
918
self.Doc = FreeCAD.newDocument("UndoTest")
919
self.Doc.UndoMode = 0
920
self.Doc.addObject("App::FeatureTest", "Base")
921
self.Doc.addObject("App::FeatureTest", "Del")
922
self.Doc.getObject("Del").Integer = 2
924
def testUndoProperties(self):
926
self.Doc.UndoMode = 1
929
self.Doc.openTransaction("Transaction1")
930
self.Doc.addObject("App::FeatureTest", "test1")
931
self.Doc.getObject("test1").Integer = 1
932
self.Doc.getObject("test1").String = "test1"
933
self.Doc.getObject("test1").Float = 1.0
934
self.Doc.getObject("test1").Bool = 1
936
# self.Doc.getObject("test1").IntegerList = 1
937
# self.Doc.getObject("test1").FloatList = 1.0
939
# self.Doc.getObject("test1").Matrix = (1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0)
940
# self.Doc.getObject("test1").Vector = (1.0,1.0,1.0)
943
self.Doc.openTransaction("Transaction2")
944
self.Doc.getObject("test1").Integer = 2
945
self.Doc.getObject("test1").String = "test2"
946
self.Doc.getObject("test1").Float = 2.0
947
self.Doc.getObject("test1").Bool = 0
949
# switch on the Undo OFF
950
self.Doc.UndoMode = 0
952
def testUndoClear(self):
954
self.Doc.UndoMode = 1
955
self.assertEqual(self.Doc.UndoNames, [])
956
self.assertEqual(self.Doc.UndoCount, 0)
957
self.assertEqual(self.Doc.RedoNames, [])
958
self.assertEqual(self.Doc.RedoCount, 0)
960
self.Doc.openTransaction("Transaction1")
961
# becomes the active object
962
self.Doc.addObject("App::FeatureTest", "test1")
963
self.Doc.commitTransaction()
964
# removes the active object
966
self.assertEqual(self.Doc.ActiveObject, None)
967
# deletes the active object
968
self.Doc.clearUndos()
969
self.assertEqual(self.Doc.ActiveObject, None)
973
self.Doc.UndoMode = 1
974
self.assertEqual(self.Doc.UndoNames, [])
975
self.assertEqual(self.Doc.UndoCount, 0)
976
self.assertEqual(self.Doc.RedoNames, [])
977
self.assertEqual(self.Doc.RedoCount, 0)
980
self.Doc.openTransaction("Transaction1")
981
self.Doc.addObject("App::FeatureTest", "test1")
982
self.Doc.getObject("test1").Integer = 1
983
self.Doc.getObject("Del").Integer = 1
984
self.Doc.removeObject("Del")
985
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
986
self.assertEqual(self.Doc.UndoCount, 1)
987
self.assertEqual(self.Doc.RedoNames, [])
988
self.assertEqual(self.Doc.RedoCount, 0)
991
self.Doc.openTransaction("Transaction2")
992
# new behavior: no change, no transaction
993
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
994
self.assertEqual(self.Doc.UndoCount, 1)
995
self.assertEqual(self.Doc.RedoNames, [])
996
self.assertEqual(self.Doc.RedoCount, 0)
998
self.Doc.getObject("test1").Integer = 2
999
self.assertEqual(self.Doc.UndoNames, ["Transaction2", "Transaction1"])
1000
self.assertEqual(self.Doc.UndoCount, 2)
1001
self.assertEqual(self.Doc.RedoNames, [])
1002
self.assertEqual(self.Doc.RedoCount, 0)
1004
# abort second transaction
1005
self.Doc.abortTransaction()
1006
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
1007
self.assertEqual(self.Doc.UndoCount, 1)
1008
self.assertEqual(self.Doc.RedoNames, [])
1009
self.assertEqual(self.Doc.RedoCount, 0)
1010
self.assertEqual(self.Doc.getObject("test1").Integer, 1)
1012
# again second transaction
1013
self.Doc.openTransaction("Transaction2")
1014
self.Doc.getObject("test1").Integer = 2
1015
self.assertEqual(self.Doc.UndoNames, ["Transaction2", "Transaction1"])
1016
self.assertEqual(self.Doc.UndoCount, 2)
1017
self.assertEqual(self.Doc.RedoNames, [])
1018
self.assertEqual(self.Doc.RedoCount, 0)
1021
self.Doc.openTransaction("Transaction3")
1022
self.Doc.getObject("test1").Integer = 3
1023
self.assertEqual(self.Doc.UndoNames, ["Transaction3", "Transaction2", "Transaction1"])
1024
self.assertEqual(self.Doc.UndoCount, 3)
1025
self.assertEqual(self.Doc.RedoNames, [])
1026
self.assertEqual(self.Doc.RedoCount, 0)
1028
# fourth transaction
1029
self.Doc.openTransaction("Transaction4")
1030
self.Doc.getObject("test1").Integer = 4
1032
self.Doc.UndoNames, ["Transaction4", "Transaction3", "Transaction2", "Transaction1"]
1034
self.assertEqual(self.Doc.UndoCount, 4)
1035
self.assertEqual(self.Doc.RedoNames, [])
1036
self.assertEqual(self.Doc.RedoCount, 0)
1038
# undo the fourth transaction
1040
self.assertEqual(self.Doc.getObject("test1").Integer, 3)
1041
self.assertEqual(self.Doc.UndoNames, ["Transaction3", "Transaction2", "Transaction1"])
1042
self.assertEqual(self.Doc.UndoCount, 3)
1043
self.assertEqual(self.Doc.RedoNames, ["Transaction4"])
1044
self.assertEqual(self.Doc.RedoCount, 1)
1046
# undo the third transaction
1048
self.assertEqual(self.Doc.getObject("test1").Integer, 2)
1049
self.assertEqual(self.Doc.UndoNames, ["Transaction2", "Transaction1"])
1050
self.assertEqual(self.Doc.UndoCount, 2)
1051
self.assertEqual(self.Doc.RedoNames, ["Transaction3", "Transaction4"])
1052
self.assertEqual(self.Doc.RedoCount, 2)
1054
# undo the second transaction
1056
self.assertEqual(self.Doc.getObject("test1").Integer, 1)
1057
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
1058
self.assertEqual(self.Doc.UndoCount, 1)
1059
self.assertEqual(self.Doc.RedoNames, ["Transaction2", "Transaction3", "Transaction4"])
1060
self.assertEqual(self.Doc.RedoCount, 3)
1062
# undo the first transaction
1064
self.assertTrue(self.Doc.getObject("test1") is None)
1065
self.assertTrue(self.Doc.getObject("Del").Integer == 2)
1066
self.assertEqual(self.Doc.UndoNames, [])
1067
self.assertEqual(self.Doc.UndoCount, 0)
1069
self.Doc.RedoNames, ["Transaction1", "Transaction2", "Transaction3", "Transaction4"]
1071
self.assertEqual(self.Doc.RedoCount, 4)
1073
# redo the first transaction
1075
self.assertEqual(self.Doc.getObject("test1").Integer, 1)
1076
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
1077
self.assertEqual(self.Doc.UndoCount, 1)
1078
self.assertEqual(self.Doc.RedoNames, ["Transaction2", "Transaction3", "Transaction4"])
1079
self.assertEqual(self.Doc.RedoCount, 3)
1081
# redo the second transaction
1083
self.assertEqual(self.Doc.getObject("test1").Integer, 2)
1084
self.assertEqual(self.Doc.UndoNames, ["Transaction2", "Transaction1"])
1085
self.assertEqual(self.Doc.UndoCount, 2)
1086
self.assertEqual(self.Doc.RedoNames, ["Transaction3", "Transaction4"])
1087
self.assertEqual(self.Doc.RedoCount, 2)
1089
# undo the second transaction
1091
self.assertEqual(self.Doc.getObject("test1").Integer, 1)
1092
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
1093
self.assertEqual(self.Doc.UndoCount, 1)
1094
self.assertEqual(self.Doc.RedoNames, ["Transaction2", "Transaction3", "Transaction4"])
1095
self.assertEqual(self.Doc.RedoCount, 3)
1097
# new transaction eight
1098
self.Doc.openTransaction("Transaction8")
1099
self.Doc.getObject("test1").Integer = 8
1100
self.assertEqual(self.Doc.UndoNames, ["Transaction8", "Transaction1"])
1101
self.assertEqual(self.Doc.UndoCount, 2)
1102
self.assertEqual(self.Doc.RedoNames, [])
1103
self.assertEqual(self.Doc.RedoCount, 0)
1104
self.Doc.abortTransaction()
1105
self.assertEqual(self.Doc.UndoNames, ["Transaction1"])
1106
self.assertEqual(self.Doc.UndoCount, 1)
1107
self.assertEqual(self.Doc.RedoNames, [])
1108
self.assertEqual(self.Doc.RedoCount, 0)
1110
# again new transaction eight
1111
self.Doc.openTransaction("Transaction8")
1112
self.Doc.getObject("test1").Integer = 8
1113
self.assertEqual(self.Doc.UndoNames, ["Transaction8", "Transaction1"])
1114
self.assertEqual(self.Doc.UndoCount, 2)
1115
self.assertEqual(self.Doc.RedoNames, [])
1116
self.assertEqual(self.Doc.RedoCount, 0)
1118
# again new transaction nine
1119
self.Doc.openTransaction("Transaction9")
1120
self.Doc.getObject("test1").Integer = 9
1121
self.assertEqual(self.Doc.UndoNames, ["Transaction9", "Transaction8", "Transaction1"])
1122
self.assertEqual(self.Doc.UndoCount, 3)
1123
self.assertEqual(self.Doc.RedoNames, [])
1124
self.assertEqual(self.Doc.RedoCount, 0)
1125
self.Doc.commitTransaction()
1126
self.assertEqual(self.Doc.UndoNames, ["Transaction9", "Transaction8", "Transaction1"])
1127
self.assertEqual(self.Doc.UndoCount, 3)
1128
self.assertEqual(self.Doc.RedoNames, [])
1129
self.assertEqual(self.Doc.RedoCount, 0)
1130
self.assertEqual(self.Doc.getObject("test1").Integer, 9)
1132
# undo the ninth transaction
1134
self.assertEqual(self.Doc.getObject("test1").Integer, 8)
1135
self.assertEqual(self.Doc.UndoNames, ["Transaction8", "Transaction1"])
1136
self.assertEqual(self.Doc.UndoCount, 2)
1137
self.assertEqual(self.Doc.RedoNames, ["Transaction9"])
1138
self.assertEqual(self.Doc.RedoCount, 1)
1140
# switch on the Undo OFF
1141
self.Doc.UndoMode = 0
1142
self.assertEqual(self.Doc.UndoNames, [])
1143
self.assertEqual(self.Doc.UndoCount, 0)
1144
self.assertEqual(self.Doc.RedoNames, [])
1145
self.assertEqual(self.Doc.RedoCount, 0)
1147
def testUndoInList(self):
1149
self.Doc.UndoMode = 1
1151
self.Doc.openTransaction("Box")
1152
self.Box = self.Doc.addObject("App::FeatureTest")
1153
self.Doc.commitTransaction()
1155
self.Doc.openTransaction("Cylinder")
1156
self.Cylinder = self.Doc.addObject("App::FeatureTest")
1157
self.Doc.commitTransaction()
1159
self.Doc.openTransaction("Fuse")
1160
self.Fuse1 = self.Doc.addObject("App::FeatureTest", "Fuse")
1161
self.Fuse1.LinkList = [self.Box, self.Cylinder]
1162
self.Doc.commitTransaction()
1165
self.assertTrue(len(self.Box.InList) == 0)
1166
self.assertTrue(len(self.Cylinder.InList) == 0)
1169
self.assertTrue(len(self.Box.InList) == 1)
1170
self.assertTrue(self.Box.InList[0] == self.Doc.Fuse)
1171
self.assertTrue(len(self.Cylinder.InList) == 1)
1172
self.assertTrue(self.Cylinder.InList[0] == self.Doc.Fuse)
1174
def testUndoIssue0003150Part1(self):
1176
self.Doc.UndoMode = 1
1178
self.Doc.openTransaction("Box")
1179
self.Box = self.Doc.addObject("App::FeatureTest")
1180
self.Doc.commitTransaction()
1182
self.Doc.openTransaction("Cylinder")
1183
self.Cylinder = self.Doc.addObject("App::FeatureTest")
1184
self.Doc.commitTransaction()
1186
self.Doc.openTransaction("Fuse")
1187
self.Fuse1 = self.Doc.addObject("App::FeatureTest")
1188
self.Fuse1.LinkList = [self.Box, self.Cylinder]
1189
self.Doc.commitTransaction()
1190
self.Doc.recompute()
1192
self.Doc.openTransaction("Sphere")
1193
self.Sphere = self.Doc.addObject("App::FeatureTest")
1194
self.Doc.commitTransaction()
1196
self.Doc.openTransaction("Fuse")
1197
self.Fuse2 = self.Doc.addObject("App::FeatureTest")
1198
self.Fuse2.LinkList = [self.Fuse1, self.Sphere]
1199
self.Doc.commitTransaction()
1200
self.Doc.recompute()
1202
self.Doc.openTransaction("Part")
1203
self.Part = self.Doc.addObject("App::Part")
1204
self.Doc.commitTransaction()
1206
self.Doc.openTransaction("Drag")
1207
self.Part.addObject(self.Fuse2)
1208
self.Doc.commitTransaction()
1210
# 3 undos show the problem of failing recompute
1214
self.assertTrue(self.Doc.recompute() >= 0)
1218
FreeCAD.closeDocument("UndoTest")
1221
class DocumentGroupCases(unittest.TestCase):
1223
self.Doc = FreeCAD.newDocument("GroupTests")
1225
def testGroup(self):
1226
# Add an object to the group
1227
L2 = self.Doc.addObject("App::FeatureTest", "Label_2")
1228
G1 = self.Doc.addObject("App::DocumentObjectGroup", "Group")
1230
self.assertTrue(G1.hasObject(L2))
1232
# Adding the group to itself must fail
1236
FreeCAD.Console.PrintLog("Cannot add group to itself, OK\n")
1238
self.fail("Adding the group to itself must not be possible")
1240
self.Doc.UndoMode = 1
1242
# Remove object from group
1243
self.Doc.openTransaction("Remove")
1244
self.Doc.removeObject("Label_2")
1245
self.Doc.commitTransaction()
1246
self.assertTrue(G1.getObject("Label_2") is None)
1248
self.assertTrue(G1.getObject("Label_2") is not None)
1250
# Remove first group and then the object
1251
self.Doc.openTransaction("Remove")
1252
self.Doc.removeObject("Group")
1253
self.Doc.removeObject("Label_2")
1254
self.Doc.commitTransaction()
1256
self.assertTrue(G1.getObject("Label_2") is not None)
1258
# Remove first object and then the group in two transactions
1259
self.Doc.openTransaction("Remove")
1260
self.Doc.removeObject("Label_2")
1261
self.Doc.commitTransaction()
1262
self.assertTrue(G1.getObject("Label_2") is None)
1263
self.Doc.openTransaction("Remove")
1264
self.Doc.removeObject("Group")
1265
self.Doc.commitTransaction()
1268
self.assertTrue(G1.getObject("Label_2") is not None)
1270
# Remove first object and then the group in one transaction
1271
self.Doc.openTransaction("Remove")
1272
self.Doc.removeObject("Label_2")
1273
self.assertTrue(G1.getObject("Label_2") is None)
1274
self.Doc.removeObject("Group")
1275
self.Doc.commitTransaction()
1277
# FIXME: See bug #1820554
1278
self.assertTrue(G1.getObject("Label_2") is not None)
1280
# Add a second object to the group
1281
L3 = self.Doc.addObject("App::FeatureTest", "Label_3")
1283
self.Doc.openTransaction("Remove")
1284
self.Doc.removeObject("Label_2")
1285
self.assertTrue(G1.getObject("Label_2") is None)
1286
self.Doc.removeObject("Label_3")
1287
self.assertTrue(G1.getObject("Label_3") is None)
1288
self.Doc.removeObject("Group")
1289
self.Doc.commitTransaction()
1291
self.assertTrue(G1.getObject("Label_3") is not None)
1292
self.assertTrue(G1.getObject("Label_2") is not None)
1294
self.Doc.UndoMode = 0
1297
self.Doc.removeObject("Group")
1298
self.Doc.removeObject("Label_2")
1299
self.Doc.removeObject("Label_3")
1301
def testGroupAndGeoFeatureGroup(self):
1303
# an object can only be in one group at once, that must be enforced
1304
obj1 = self.Doc.addObject("App::FeatureTest", "obj1")
1305
grp1 = self.Doc.addObject("App::DocumentObjectGroup", "Group1")
1306
grp2 = self.Doc.addObject("App::DocumentObjectGroup", "Group2")
1307
grp1.addObject(obj1)
1308
self.assertTrue(obj1.getParentGroup() == grp1)
1309
self.assertTrue(obj1.getParentGeoFeatureGroup() is None)
1310
self.assertTrue(grp1.hasObject(obj1))
1311
grp2.addObject(obj1)
1312
self.assertTrue(grp1.hasObject(obj1) == False)
1313
self.assertTrue(grp2.hasObject(obj1))
1315
# an object is allowed to be in a group and a geofeaturegroup
1316
prt1 = self.Doc.addObject("App::Part", "Part1")
1317
prt2 = self.Doc.addObject("App::Part", "Part2")
1319
prt1.addObject(grp2)
1320
self.assertTrue(grp2.getParentGeoFeatureGroup() == prt1)
1321
self.assertTrue(grp2.getParentGroup() is None)
1322
self.assertTrue(grp2.hasObject(obj1))
1323
self.assertTrue(prt1.hasObject(grp2))
1324
self.assertTrue(prt1.hasObject(obj1))
1326
# it is not allowed to be in 2 geofeaturegroups
1327
prt2.addObject(grp2)
1328
self.assertTrue(grp2.hasObject(obj1))
1329
self.assertTrue(prt1.hasObject(grp2) == False)
1330
self.assertTrue(prt1.hasObject(obj1) == False)
1331
self.assertTrue(prt2.hasObject(grp2))
1332
self.assertTrue(prt2.hasObject(obj1))
1339
self.assertTrue(prt1.Group == grp)
1341
self.fail("No exception thrown when object is in multiple Groups")
1343
# it is not allowed to be in 2 Groups
1344
prt2.addObject(grp1)
1352
self.fail("No exception thrown when object is in multiple Groups")
1354
# cross linking between GeoFeatureGroups is not allowed
1355
self.Doc.recompute()
1356
box = self.Doc.addObject("App::FeatureTest", "Box")
1357
cyl = self.Doc.addObject("App::FeatureTest", "Cylinder")
1358
fus = self.Doc.addObject("App::FeatureTest", "Fusion")
1359
fus.LinkList = [cyl, box]
1360
self.Doc.recompute()
1361
self.assertTrue(fus.State[0] == "Up-to-date")
1364
) # remove all links as addObject would otherwise transfer all linked objects
1366
fus.LinkList = [cyl, box]
1367
self.Doc.recompute()
1368
# self.assertTrue(fus.State[0] == 'Invalid')
1371
fus.LinkList = [cyl, box]
1372
self.Doc.recompute()
1373
# self.assertTrue(fus.State[0] == 'Invalid')
1376
fus.LinkList = [cyl, box]
1377
self.Doc.recompute()
1378
self.assertTrue(fus.State[0] == "Up-to-date")
1379
prt2.addObject(box) # this time addObject should move all dependencies to the new part
1380
self.Doc.recompute()
1381
self.assertTrue(fus.State[0] == "Up-to-date")
1383
# grouping must be resilient against cyclic links and not crash: #issue 0002567
1384
prt1.addObject(prt2)
1388
self.Doc.recompute()
1395
self.fail("Exception is expected")
1397
self.Doc.recompute()
1399
def testIssue0003150Part2(self):
1400
self.box = self.Doc.addObject("App::FeatureTest")
1401
self.cyl = self.Doc.addObject("App::FeatureTest")
1402
self.sph = self.Doc.addObject("App::FeatureTest")
1404
self.fus1 = self.Doc.addObject("App::FeatureTest")
1405
self.fus2 = self.Doc.addObject("App::FeatureTest")
1407
self.fus1.LinkList = [self.box, self.cyl]
1408
self.fus2.LinkList = [self.sph, self.cyl]
1410
self.prt = self.Doc.addObject("App::Part")
1411
self.prt.addObject(self.fus1)
1412
self.assertTrue(len(self.prt.Group) == 5)
1413
self.assertTrue(self.fus2.getParentGeoFeatureGroup() == self.prt)
1414
self.assertTrue(self.prt.hasObject(self.sph))
1416
self.prt.removeObject(self.fus1)
1417
self.assertTrue(len(self.prt.Group) == 0)
1421
FreeCAD.closeDocument("GroupTests")
1424
class DocumentPlatformCases(unittest.TestCase):
1426
self.Doc = FreeCAD.newDocument("PlatformTests")
1427
self.Doc.addObject("App::FeatureTest", "Test")
1428
self.TempPath = tempfile.gettempdir()
1429
self.DocName = self.TempPath + os.sep + "PlatformTests.FCStd"
1431
def testFloatList(self):
1432
self.Doc.Test.FloatList = [-0.05, 2.5, 5.2]
1434
# saving and restoring
1435
self.Doc.saveAs(self.DocName)
1436
FreeCAD.closeDocument("PlatformTests")
1437
self.Doc = FreeCAD.open(self.DocName)
1439
self.assertTrue(abs(self.Doc.Test.FloatList[0] + 0.05) < 0.01)
1440
self.assertTrue(abs(self.Doc.Test.FloatList[1] - 2.5) < 0.01)
1441
self.assertTrue(abs(self.Doc.Test.FloatList[2] - 5.2) < 0.01)
1443
def testColorList(self):
1444
self.Doc.Test.ColourList = [(1.0, 0.5, 0.0), (0.0, 0.5, 1.0)]
1446
# saving and restoring
1447
self.Doc.saveAs(self.DocName)
1448
FreeCAD.closeDocument("PlatformTests")
1449
self.Doc = FreeCAD.open(self.DocName)
1451
self.assertTrue(abs(self.Doc.Test.ColourList[0][0] - 1.0) < 0.01)
1452
self.assertTrue(abs(self.Doc.Test.ColourList[0][1] - 0.5) < 0.01)
1453
self.assertTrue(abs(self.Doc.Test.ColourList[0][2] - 0.0) < 0.01)
1454
self.assertTrue(abs(self.Doc.Test.ColourList[0][3] - 0.0) < 0.01)
1455
self.assertTrue(abs(self.Doc.Test.ColourList[1][0] - 0.0) < 0.01)
1456
self.assertTrue(abs(self.Doc.Test.ColourList[1][1] - 0.5) < 0.01)
1457
self.assertTrue(abs(self.Doc.Test.ColourList[1][2] - 1.0) < 0.01)
1458
self.assertTrue(abs(self.Doc.Test.ColourList[1][3] - 0.0) < 0.01)
1460
def testVectorList(self):
1461
self.Doc.Test.VectorList = [(-0.05, 2.5, 5.2), (-0.05, 2.5, 5.2)]
1463
# saving and restoring
1464
self.Doc.saveAs(self.DocName)
1465
FreeCAD.closeDocument("PlatformTests")
1466
self.Doc = FreeCAD.open(self.DocName)
1468
self.assertTrue(len(self.Doc.Test.VectorList) == 2)
1470
def testPoints(self):
1472
self.Doc.addObject("Points::Feature", "Points")
1474
# saving and restoring
1475
self.Doc.saveAs(self.DocName)
1476
FreeCAD.closeDocument("PlatformTests")
1477
self.Doc = FreeCAD.open(self.DocName)
1479
self.assertTrue(self.Doc.Points.Points.count() == 0)
1485
FreeCAD.closeDocument("PlatformTests")
1488
class DocumentBacklinks(unittest.TestCase):
1490
self.Doc = FreeCAD.newDocument("BackLinks")
1492
def testIssue0003323(self):
1493
self.Doc.UndoMode = 1
1494
self.Doc.openTransaction("Create object")
1495
obj1 = self.Doc.addObject("App::FeatureTest", "Test1")
1496
obj2 = self.Doc.addObject("App::FeatureTest", "Test2")
1498
self.Doc.commitTransaction()
1500
self.Doc.openTransaction("Create object")
1504
FreeCAD.closeDocument("BackLinks")
1507
class DocumentFileIncludeCases(unittest.TestCase):
1509
self.Doc = FreeCAD.newDocument("FileIncludeTests")
1511
self.Doc.UndoMode = 1
1513
def testApplyFiles(self):
1514
self.Doc.openTransaction("Transaction0")
1515
self.L1 = self.Doc.addObject("App::DocumentObjectFileIncluded", "FileObject1")
1516
self.assertTrue(self.L1.File == "")
1517
self.Filename = self.L1.File
1519
self.Doc.openTransaction("Transaction1")
1520
self.TempPath = tempfile.gettempdir()
1521
# creating a file in the Transient directory of the document
1522
file = open(self.Doc.getTempFileName("test"), "w")
1523
file.write("test No1")
1526
self.L1.File = (file.name, "Test.txt")
1527
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1529
file = open(self.L1.File, "r")
1530
self.assertTrue(file.read() == "test No1")
1532
file = open(self.TempPath + "/testNest.txt", "w")
1533
file.write("test No2")
1536
self.Doc.openTransaction("Transaction2")
1537
self.L1.File = file.name
1538
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1540
file = open(self.L1.File, "r")
1541
self.assertTrue(file.read() == "test No2")
1544
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1546
file = open(self.L1.File, "r")
1547
self.assertTrue(file.read() == "test No1")
1551
self.assertTrue(self.L1.File == "")
1553
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1555
file = open(self.L1.File, "r")
1556
self.assertTrue(file.read() == "test No1")
1559
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1561
file = open(self.L1.File, "r")
1562
self.assertTrue(file.read() == "test No2")
1565
FileName = self.TempPath + "/FileIncludeTests.fcstd"
1566
self.Doc.saveAs(FileName)
1567
FreeCAD.closeDocument("FileIncludeTests")
1568
self.Doc = FreeCAD.open(self.TempPath + "/FileIncludeTests.fcstd")
1569
# check if the file is still there
1570
self.L1 = self.Doc.getObject("FileObject1")
1571
file = open(self.L1.File, "r")
1573
FreeCAD.Console.PrintLog(res + "\n")
1574
self.assertTrue(res == "test No2")
1575
self.assertTrue(self.L1.File.split("/")[-1] == "Test.txt")
1578
# test for bug #94 (File overlap in PropertyFileIncluded)
1579
L2 = self.Doc.addObject("App::DocumentObjectFileIncluded", "FileObject2")
1580
L3 = self.Doc.addObject("App::DocumentObjectFileIncluded", "FileObject3")
1582
# creating two files in the Transient directory of the document
1583
file1 = open(self.Doc.getTempFileName("test"), "w")
1584
file1.write("test No1")
1586
file2 = open(self.Doc.getTempFileName("test"), "w")
1587
file2.write("test No2")
1590
# applying the file with the same base name
1591
L2.File = (file1.name, "Test.txt")
1592
L3.File = (file2.name, "Test.txt")
1594
file = open(L2.File, "r")
1595
self.assertTrue(file.read() == "test No1")
1597
file = open(L3.File, "r")
1598
self.assertTrue(file.read() == "test No2")
1601
# create a second document, copy a file and close the document
1602
# the test is about to put the file to the correct transient dir
1603
doc2 = FreeCAD.newDocument("Doc2")
1604
L4 = doc2.addObject("App::DocumentObjectFileIncluded", "FileObject")
1605
L5 = doc2.addObject("App::DocumentObjectFileIncluded", "FileObject")
1606
L6 = doc2.addObject("App::DocumentObjectFileIncluded", "FileObject")
1607
L4.File = (L3.File, "Test.txt")
1610
FreeCAD.closeDocument("FileIncludeTests")
1611
self.Doc = FreeCAD.open(self.TempPath + "/FileIncludeTests.fcstd")
1612
self.assertTrue(os.path.exists(L4.File))
1613
self.assertTrue(os.path.exists(L5.File))
1614
self.assertTrue(os.path.exists(L6.File))
1615
self.assertTrue(L5.File != L6.File)
1616
# copy file from L5 which is in the same directory
1617
L7 = doc2.addObject("App::DocumentObjectFileIncluded", "FileObject3")
1618
L7.File = (L5.File, "Copy.txt")
1619
self.assertTrue(os.path.exists(L7.File))
1620
FreeCAD.closeDocument("Doc2")
1624
FreeCAD.closeDocument("FileIncludeTests")
1627
class DocumentPropertyCases(unittest.TestCase):
1629
self.Doc = FreeCAD.newDocument("PropertyTests")
1630
self.Obj = self.Doc.addObject("App::FeaturePython", "Test")
1632
def testDescent(self):
1633
# testing the up and downstream stuff
1634
props = self.Obj.supportedProperties()
1636
self.Obj.addProperty(i, i.replace(":", "_"))
1637
tempPath = tempfile.gettempdir()
1638
tempFile = tempPath + os.sep + "PropertyTests.FCStd"
1639
self.Doc.saveAs(tempFile)
1640
FreeCAD.closeDocument("PropertyTests")
1641
self.Doc = FreeCAD.open(tempFile)
1643
def testRemoveProperty(self):
1645
self.Obj.addProperty("App::PropertyFloat", prop)
1646
self.Obj.Something = 0.01
1647
self.Doc.recompute()
1648
self.Doc.openTransaction("modify and remove property")
1649
self.Obj.Something = 0.00
1650
self.Obj.removeProperty(prop)
1651
self.Obj.recompute()
1652
self.Doc.abortTransaction()
1654
def testRemovePropertyExpression(self):
1655
p1 = self.Doc.addObject("App::FeaturePython", "params1")
1656
p2 = self.Doc.addObject("App::FeaturePython", "params2")
1657
p1.addProperty("App::PropertyFloat", "a")
1659
p2.addProperty("App::PropertyFloat", "b")
1660
p2.setExpression("b", "params1.a")
1661
self.Doc.recompute()
1662
p2.removeProperty("b")
1664
self.Doc.recompute()
1665
self.assertTrue(not p2 in p1.InList)
1667
def testRemovePropertyOnChange(self):
1669
def __init__(self, fp):
1671
fp.addProperty("App::PropertyString", "Test")
1673
def onBeforeChange(self, fp, prop):
1675
fp.removeProperty("Test")
1677
def onChanged(self, fp, prop):
1680
obj = self.Doc.addObject("App::FeaturePython")
1686
FreeCAD.closeDocument("PropertyTests")
1689
class DocumentExpressionCases(unittest.TestCase):
1691
self.Doc = FreeCAD.newDocument()
1693
def assertAlmostEqual(self, v1, v2):
1694
if math.fabs(v2 - v1) > 1e-12:
1695
self.assertEqual(v1, v2)
1697
def testExpression(self):
1698
self.Obj1 = self.Doc.addObject("App::FeatureTest", "Test")
1699
self.Obj2 = self.Doc.addObject("App::FeatureTest", "Test")
1700
# set the object twice to test that the backlinks are removed when overwriting the expression
1701
self.Obj2.setExpression(
1702
"Placement.Rotation.Angle", "%s.Placement.Rotation.Angle" % self.Obj1.Name
1704
self.Obj2.setExpression(
1705
"Placement.Rotation.Angle", "%s.Placement.Rotation.Angle" % self.Obj1.Name
1707
self.Obj1.Placement = FreeCAD.Placement(
1708
FreeCAD.Vector(0, 0, 0), FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 10)
1710
self.Doc.recompute()
1711
self.assertAlmostEqual(
1712
self.Obj1.Placement.Rotation.Angle, self.Obj2.Placement.Rotation.Angle
1715
# clear the expression
1716
self.Obj2.setExpression("Placement.Rotation.Angle", None)
1717
self.assertAlmostEqual(
1718
self.Obj1.Placement.Rotation.Angle, self.Obj2.Placement.Rotation.Angle
1720
self.Doc.recompute()
1721
self.assertAlmostEqual(
1722
self.Obj1.Placement.Rotation.Angle, self.Obj2.Placement.Rotation.Angle
1724
# touch the objects to perform a recompute
1725
self.Obj1.Placement = self.Obj1.Placement
1726
self.Obj2.Placement = self.Obj2.Placement
1727
# must not raise a topological error
1728
self.assertEqual(self.Doc.recompute(), 2)
1730
# add test for issue #6948
1731
self.Obj3 = self.Doc.addObject("App::FeatureTest", "Test")
1732
self.Obj3.setExpression("Float", "2*(5%3)")
1733
self.Doc.recompute()
1734
self.assertEqual(self.Obj3.Float, 4)
1735
self.assertEqual(self.Obj3.evalExpression(self.Obj3.ExpressionEngine[0][1]), 4)
1737
def testIssue4649(self):
1739
def __init__(self, obj):
1740
self.MonitorChanges = False
1742
obj.addProperty("App::PropertyFloat", "propA", "group")
1743
obj.addProperty("App::PropertyFloat", "propB", "group")
1744
self.MonitorChanges = True
1745
obj.setExpression("propB", "6*9")
1747
def onChanged(self, obj, prop):
1748
print("onChanged", self, obj, prop)
1749
if self.MonitorChanges and prop == "propA":
1750
print("Removing expression...")
1751
obj.setExpression("propB", None)
1753
obj = self.Doc.addObject("App::DocumentObjectGroupPython", "Obj")
1755
self.Doc.UndoMode = 1
1756
self.Doc.openTransaction("Expression")
1757
obj.setExpression("propA", "42")
1758
self.Doc.recompute()
1759
self.Doc.commitTransaction()
1760
self.assertTrue(("propB", None) in obj.ExpressionEngine)
1761
self.assertTrue(("propA", "42") in obj.ExpressionEngine)
1764
self.assertFalse(("propB", None) in obj.ExpressionEngine)
1765
self.assertFalse(("propA", "42") in obj.ExpressionEngine)
1768
self.assertTrue(("propB", None) in obj.ExpressionEngine)
1769
self.assertTrue(("propA", "42") in obj.ExpressionEngine)
1771
self.Doc.recompute()
1772
obj.ExpressionEngine
1774
TempPath = tempfile.gettempdir()
1775
SaveName = TempPath + os.sep + "ExpressionTests.FCStd"
1776
self.Doc.saveAs(SaveName)
1777
FreeCAD.closeDocument(self.Doc.Name)
1778
self.Doc = FreeCAD.openDocument(SaveName)
1780
def testCyclicDependencyOnPlacement(self):
1781
obj = self.Doc.addObject("App::FeaturePython", "Python")
1782
obj.addProperty("App::PropertyPlacement", "Placement")
1783
obj.setExpression(".Placement.Base.x", ".Placement.Base.y + 10mm")
1784
with self.assertRaises(RuntimeError):
1785
obj.setExpression(".Placement.Base.y", ".Placement.Base.x + 10mm")
1789
FreeCAD.closeDocument(self.Doc.Name)
1792
class DocumentObserverCases(unittest.TestCase):
1800
self.parameter2 = []
1802
def slotCreatedDocument(self, doc):
1803
self.signal.append("DocCreated")
1804
self.parameter.append(doc)
1806
def slotDeletedDocument(self, doc):
1807
self.signal.append("DocDeleted")
1808
self.parameter.append(doc)
1810
def slotRelabelDocument(self, doc):
1811
self.signal.append("DocRelabled")
1812
self.parameter.append(doc)
1814
def slotActivateDocument(self, doc):
1815
self.signal.append("DocActivated")
1816
self.parameter.append(doc)
1818
def slotRecomputedDocument(self, doc):
1819
self.signal.append("DocRecomputed")
1820
self.parameter.append(doc)
1822
def slotUndoDocument(self, doc):
1823
self.signal.append("DocUndo")
1824
self.parameter.append(doc)
1826
def slotRedoDocument(self, doc):
1827
self.signal.append("DocRedo")
1828
self.parameter.append(doc)
1830
def slotOpenTransaction(self, doc, name):
1831
self.signal.append("DocOpenTransaction")
1832
self.parameter.append(doc)
1833
self.parameter2.append(name)
1835
def slotCommitTransaction(self, doc):
1836
self.signal.append("DocCommitTransaction")
1837
self.parameter.append(doc)
1839
def slotAbortTransaction(self, doc):
1840
self.signal.append("DocAbortTransaction")
1841
self.parameter.append(doc)
1843
def slotBeforeChangeDocument(self, doc, prop):
1844
self.signal.append("DocBeforeChange")
1845
self.parameter.append(doc)
1846
self.parameter2.append(prop)
1848
def slotChangedDocument(self, doc, prop):
1849
self.signal.append("DocChanged")
1850
self.parameter.append(doc)
1851
self.parameter2.append(prop)
1853
def slotCreatedObject(self, obj):
1854
self.signal.append("ObjCreated")
1855
self.parameter.append(obj)
1857
def slotDeletedObject(self, obj):
1858
self.signal.append("ObjDeleted")
1859
self.parameter.append(obj)
1861
def slotChangedObject(self, obj, prop):
1862
self.signal.append("ObjChanged")
1863
self.parameter.append(obj)
1864
self.parameter2.append(prop)
1866
def slotBeforeChangeObject(self, obj, prop):
1867
self.signal.append("ObjBeforeChange")
1868
self.parameter.append(obj)
1869
self.parameter2.append(prop)
1871
def slotRecomputedObject(self, obj):
1872
self.signal.append("ObjRecomputed")
1873
self.parameter.append(obj)
1875
def slotAppendDynamicProperty(self, obj, prop):
1876
self.signal.append("ObjAddDynProp")
1877
self.parameter.append(obj)
1878
self.parameter2.append(prop)
1880
def slotRemoveDynamicProperty(self, obj, prop):
1881
self.signal.append("ObjRemoveDynProp")
1882
self.parameter.append(obj)
1883
self.parameter2.append(prop)
1885
def slotChangePropertyEditor(self, obj, prop):
1886
self.signal.append("ObjChangePropEdit")
1887
self.parameter.append(obj)
1888
self.parameter2.append(prop)
1890
def slotStartSaveDocument(self, obj, name):
1891
self.signal.append("DocStartSave")
1892
self.parameter.append(obj)
1893
self.parameter2.append(name)
1895
def slotFinishSaveDocument(self, obj, name):
1896
self.signal.append("DocFinishSave")
1897
self.parameter.append(obj)
1898
self.parameter2.append(name)
1900
def slotBeforeAddingDynamicExtension(self, obj, extension):
1901
self.signal.append("ObjBeforeDynExt")
1902
self.parameter.append(obj)
1903
self.parameter2.append(extension)
1905
def slotAddedDynamicExtension(self, obj, extension):
1906
self.signal.append("ObjDynExt")
1907
self.parameter.append(obj)
1908
self.parameter2.append(extension)
1917
self.parameter2 = []
1919
def slotCreatedDocument(self, doc):
1920
self.signal.append("DocCreated")
1921
self.parameter.append(doc)
1923
def slotDeletedDocument(self, doc):
1924
self.signal.append("DocDeleted")
1925
self.parameter.append(doc)
1927
def slotRelabelDocument(self, doc):
1928
self.signal.append("DocRelabled")
1929
self.parameter.append(doc)
1931
def slotRenameDocument(self, doc):
1932
self.signal.append("DocRenamed")
1933
self.parameter.append(doc)
1935
def slotActivateDocument(self, doc):
1936
self.signal.append("DocActivated")
1937
self.parameter.append(doc)
1939
def slotCreatedObject(self, obj):
1940
self.signal.append("ObjCreated")
1941
self.parameter.append(obj)
1943
def slotDeletedObject(self, obj):
1944
self.signal.append("ObjDeleted")
1945
self.parameter.append(obj)
1947
def slotChangedObject(self, obj, prop):
1948
self.signal.append("ObjChanged")
1949
self.parameter.append(obj)
1950
self.parameter2.append(prop)
1952
def slotInEdit(self, obj):
1953
self.signal.append("ObjInEdit")
1954
self.parameter.append(obj)
1956
def slotResetEdit(self, obj):
1957
self.signal.append("ObjResetEdit")
1958
self.parameter.append(obj)
1961
self.Obs = self.Observer()
1962
FreeCAD.addDocumentObserver(self.Obs)
1964
def testRemoveObserver(self):
1965
FreeCAD.removeDocumentObserver(self.Obs)
1967
self.Doc1 = FreeCAD.newDocument("Observer")
1968
FreeCAD.closeDocument(self.Doc1.Name)
1969
self.assertEqual(len(self.Obs.signal), 0)
1970
self.assertEqual(len(self.Obs.parameter2), 0)
1971
self.assertEqual(len(self.Obs.signal), 0)
1972
FreeCAD.addDocumentObserver(self.Obs)
1975
TempPath = tempfile.gettempdir()
1976
SaveName = TempPath + os.sep + "SaveRestoreTests.FCStd"
1977
self.Doc1 = FreeCAD.newDocument("Observer1")
1978
self.Doc1.saveAs(SaveName)
1979
self.assertEqual(self.Obs.signal.pop(), "DocFinishSave")
1980
self.assertEqual(self.Obs.parameter2.pop(), self.Doc1.FileName)
1981
self.assertEqual(self.Obs.signal.pop(), "DocStartSave")
1982
self.assertEqual(self.Obs.parameter2.pop(), self.Doc1.FileName)
1983
FreeCAD.closeDocument(self.Doc1.Name)
1985
def testDocument(self):
1986
# in case another document already exists then the tests cannot
1988
if FreeCAD.GuiUp and FreeCAD.activeDocument():
1991
# testing document level signals
1992
self.Doc1 = FreeCAD.newDocument("Observer1")
1994
self.assertEqual(self.Obs.signal.pop(0), "DocActivated")
1995
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
1996
self.assertEqual(self.Obs.signal.pop(0), "DocCreated")
1997
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
1998
self.assertEqual(self.Obs.signal.pop(0), "DocBeforeChange")
1999
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2000
self.assertEqual(self.Obs.parameter2.pop(0), "Label")
2001
self.assertEqual(self.Obs.signal.pop(0), "DocChanged")
2002
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2003
self.assertEqual(self.Obs.parameter2.pop(0), "Label")
2004
self.assertEqual(self.Obs.signal.pop(0), "DocRelabled")
2005
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2006
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2008
self.Doc2 = FreeCAD.newDocument("Observer2")
2010
self.assertEqual(self.Obs.signal.pop(0), "DocActivated")
2011
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc2)
2012
self.assertEqual(self.Obs.signal.pop(0), "DocCreated")
2013
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc2)
2014
self.assertEqual(self.Obs.signal.pop(0), "DocBeforeChange")
2015
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc2)
2016
self.assertEqual(self.Obs.parameter2.pop(0), "Label")
2017
self.assertEqual(self.Obs.signal.pop(0), "DocChanged")
2018
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc2)
2019
self.assertEqual(self.Obs.parameter2.pop(0), "Label")
2020
self.assertEqual(self.Obs.signal.pop(0), "DocRelabled")
2021
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc2)
2022
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2024
FreeCAD.setActiveDocument("Observer1")
2025
self.assertEqual(self.Obs.signal.pop(), "DocActivated")
2026
self.assertTrue(self.Obs.parameter.pop() is self.Doc1)
2027
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2029
# undo/redo is not enabled in cmd line mode by default
2030
self.Doc2.UndoMode = 1
2032
# Must set Doc2 as active document before start transaction test. If not,
2033
# then a transaction will be auto created inside the active document if a
2034
# new transaction is triggered from a non active document
2035
FreeCAD.setActiveDocument("Observer2")
2036
self.assertEqual(self.Obs.signal.pop(), "DocActivated")
2037
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2038
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2040
self.Doc2.openTransaction("test")
2041
# openTransaction() now only setup pending transaction, which will only be
2042
# created when there is actual change
2043
self.Doc2.addObject("App::FeatureTest", "test")
2044
self.assertEqual(self.Obs.signal[0], "DocOpenTransaction")
2045
self.assertEqual(self.Obs.signal.count("DocOpenTransaction"), 1)
2046
self.assertTrue(self.Obs.parameter[0] is self.Doc2)
2047
self.assertEqual(self.Obs.parameter2[0], "test")
2050
self.Doc2.commitTransaction()
2051
self.assertEqual(self.Obs.signal.pop(), "DocCommitTransaction")
2052
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2053
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2055
self.Doc2.openTransaction("test2")
2056
# openTransaction() now only setup pending transaction, which will only be
2057
# created when there is actual change
2058
self.Doc2.addObject("App::FeatureTest", "test")
2059
self.assertEqual(self.Obs.signal[0], "DocOpenTransaction")
2060
self.assertEqual(self.Obs.signal.count("DocOpenTransaction"), 1)
2061
self.assertTrue(self.Obs.parameter[0] is self.Doc2)
2062
self.assertEqual(self.Obs.parameter2[0], "test2")
2063
# there will be other signals because of the addObject()
2066
self.Doc2.abortTransaction()
2067
self.assertEqual(self.Obs.signal.pop(), "DocAbortTransaction")
2068
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2069
# there will be other signals because of aborting the above addObject()
2073
self.assertEqual(self.Obs.signal.pop(), "DocUndo")
2074
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2075
# there will be other signals because undoing the above addObject()
2079
self.assertEqual(self.Obs.signal.pop(), "DocRedo")
2080
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2081
# there will be other signals because redoing the above addObject()
2084
self.Doc1.Comment = "test comment"
2085
self.assertEqual(self.Obs.signal.pop(0), "DocBeforeChange")
2086
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2087
self.assertEqual(self.Obs.parameter2.pop(0), "Comment")
2088
self.assertEqual(self.Obs.signal.pop(0), "DocChanged")
2089
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2090
self.assertEqual(self.Obs.parameter2.pop(0), "Comment")
2092
FreeCAD.closeDocument(self.Doc2.Name)
2093
self.assertEqual(self.Obs.signal.pop(), "DocDeleted")
2094
self.assertTrue(self.Obs.parameter.pop() is self.Doc2)
2096
# only has document activated signal when running in GUI mode
2097
self.assertEqual(self.Obs.signal.pop(), "DocActivated")
2098
self.assertTrue(self.Obs.parameter.pop() is self.Doc1)
2099
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2101
FreeCAD.closeDocument(self.Doc1.Name)
2102
self.assertEqual(self.Obs.signal.pop(), "DocDeleted")
2103
self.assertEqual(self.Obs.parameter.pop(), self.Doc1)
2104
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2106
def testObject(self):
2107
# testing signal on object changes
2109
self.Doc1 = FreeCAD.newDocument("Observer1")
2112
obj = self.Doc1.addObject("App::DocumentObject", "obj")
2113
self.assertTrue(self.Obs.signal.pop() == "ObjCreated")
2114
self.assertTrue(self.Obs.parameter.pop() is obj)
2115
# there are multiple object change signals
2119
self.assertTrue(self.Obs.signal.pop(0) == "ObjBeforeChange")
2120
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2121
self.assertTrue(self.Obs.parameter2.pop(0) == "Label")
2122
self.assertTrue(self.Obs.signal.pop(0) == "ObjChanged")
2123
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2124
self.assertTrue(self.Obs.parameter2.pop(0) == "Label")
2125
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2127
obj.enforceRecompute()
2129
self.assertTrue(self.Obs.signal.pop(0) == "ObjRecomputed")
2130
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2131
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2133
obj.enforceRecompute()
2134
self.Doc1.recompute()
2135
self.assertTrue(self.Obs.signal.pop(0) == "ObjRecomputed")
2136
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2137
self.assertTrue(self.Obs.signal.pop(0) == "DocRecomputed")
2138
self.assertTrue(self.Obs.parameter.pop(0) is self.Doc1)
2139
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2141
FreeCAD.ActiveDocument.removeObject(obj.Name)
2142
self.assertTrue(self.Obs.signal.pop(0) == "ObjDeleted")
2143
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2144
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2146
pyobj = self.Doc1.addObject("App::FeaturePython", "pyobj")
2148
pyobj.addProperty("App::PropertyLength", "Prop", "Group", "test property")
2149
self.assertTrue(self.Obs.signal.pop() == "ObjAddDynProp")
2150
self.assertTrue(self.Obs.parameter.pop() is pyobj)
2151
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2152
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2154
pyobj.setEditorMode("Prop", ["ReadOnly"])
2155
self.assertTrue(self.Obs.signal.pop() == "ObjChangePropEdit")
2156
self.assertTrue(self.Obs.parameter.pop() is pyobj)
2157
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2158
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2160
pyobj.removeProperty("Prop")
2161
self.assertTrue(self.Obs.signal.pop() == "ObjRemoveDynProp")
2162
self.assertTrue(self.Obs.parameter.pop() is pyobj)
2163
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2164
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2166
pyobj.addExtension("App::GroupExtensionPython")
2167
self.assertTrue(self.Obs.signal.pop() == "ObjDynExt")
2168
self.assertTrue(self.Obs.parameter.pop() is pyobj)
2169
self.assertTrue(self.Obs.parameter2.pop() == "App::GroupExtensionPython")
2170
self.assertTrue(self.Obs.signal.pop(0) == "ObjBeforeDynExt")
2171
self.assertTrue(self.Obs.parameter.pop(0) is pyobj)
2172
self.assertTrue(self.Obs.parameter2.pop(0) == "App::GroupExtensionPython")
2173
# a proxy property was changed, hence those events are also in the signal list
2176
FreeCAD.closeDocument(self.Doc1.Name)
2179
def testUndoDisabledDocument(self):
2181
# testing document level signals
2182
self.Doc1 = FreeCAD.newDocument("Observer1")
2183
self.Doc1.UndoMode = 0
2186
self.Doc1.openTransaction("test")
2187
self.Doc1.commitTransaction()
2190
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2192
FreeCAD.closeDocument(self.Doc1.Name)
2195
def testGuiObserver(self):
2197
if not FreeCAD.GuiUp:
2200
# in case another document already exists then the tests cannot
2202
if FreeCAD.activeDocument():
2205
self.GuiObs = self.GuiObserver()
2206
FreeCAD.Gui.addDocumentObserver(self.GuiObs)
2207
self.Doc1 = FreeCAD.newDocument("Observer1")
2208
self.GuiDoc1 = FreeCAD.Gui.getDocument(self.Doc1.Name)
2210
self.assertTrue(self.GuiObs.signal.pop(0) == "DocCreated")
2211
self.assertTrue(self.GuiObs.parameter.pop(0) is self.GuiDoc1)
2212
self.assertTrue(self.GuiObs.signal.pop(0) == "DocActivated")
2213
self.assertTrue(self.GuiObs.parameter.pop(0) is self.GuiDoc1)
2214
self.assertTrue(self.GuiObs.signal.pop(0) == "DocRelabled")
2215
self.assertTrue(self.GuiObs.parameter.pop(0) is self.GuiDoc1)
2217
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2220
self.Doc1.Label = "test"
2221
self.assertTrue(self.Obs.signal.pop() == "DocRelabled")
2222
self.assertTrue(self.Obs.parameter.pop() is self.Doc1)
2223
# not interested in the change signals
2225
self.assertTrue(self.GuiObs.signal.pop(0) == "DocRelabled")
2226
self.assertTrue(self.GuiObs.parameter.pop(0) is self.GuiDoc1)
2228
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2231
FreeCAD.setActiveDocument(self.Doc1.Name)
2232
self.assertTrue(self.Obs.signal.pop() == "DocActivated")
2233
self.assertTrue(self.Obs.parameter.pop() is self.Doc1)
2234
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2235
self.assertTrue(self.GuiObs.signal.pop() == "DocActivated")
2236
self.assertTrue(self.GuiObs.parameter.pop() is self.GuiDoc1)
2238
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2241
obj = self.Doc1.addObject("App::FeaturePython", "obj")
2242
self.assertTrue(self.Obs.signal.pop() == "ObjCreated")
2243
self.assertTrue(self.Obs.parameter.pop() is obj)
2244
# there are multiple object change signals
2246
self.assertTrue(self.GuiObs.signal.pop() == "ObjCreated")
2247
self.assertTrue(self.GuiObs.parameter.pop() is obj.ViewObject)
2249
# There are object change signals, caused by sync of obj.Visibility. Same below.
2252
obj.ViewObject.Visibility = False
2253
self.assertTrue(self.Obs.signal.pop() == "ObjChanged")
2254
self.assertTrue(self.Obs.parameter.pop() is obj)
2255
self.assertTrue(self.Obs.parameter2.pop() == "Visibility")
2256
self.assertTrue(self.Obs.signal.pop() == "ObjBeforeChange")
2257
self.assertTrue(self.Obs.parameter.pop() is obj)
2258
self.assertTrue(self.Obs.parameter2.pop() == "Visibility")
2259
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2260
self.assertTrue(self.GuiObs.signal.pop(0) == "ObjChanged")
2261
self.assertTrue(self.GuiObs.parameter.pop(0) is obj.ViewObject)
2262
self.assertTrue(self.GuiObs.parameter2.pop(0) == "Visibility")
2264
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2267
obj.ViewObject.addProperty("App::PropertyLength", "Prop", "Group", "test property")
2268
self.assertTrue(self.Obs.signal.pop() == "ObjAddDynProp")
2269
self.assertTrue(self.Obs.parameter.pop() is obj.ViewObject)
2270
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2271
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2273
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2276
obj.ViewObject.setEditorMode("Prop", ["ReadOnly"])
2277
self.assertTrue(self.Obs.signal.pop() == "ObjChangePropEdit")
2278
self.assertTrue(self.Obs.parameter.pop() is obj.ViewObject)
2279
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2280
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2282
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2285
obj.ViewObject.removeProperty("Prop")
2286
self.assertTrue(self.Obs.signal.pop() == "ObjRemoveDynProp")
2287
self.assertTrue(self.Obs.parameter.pop() is obj.ViewObject)
2288
self.assertTrue(self.Obs.parameter2.pop() == "Prop")
2289
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2291
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2294
self.GuiDoc1.setEdit("obj", 0)
2295
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2296
self.assertTrue(self.GuiObs.signal.pop(0) == "ObjInEdit")
2297
self.assertTrue(self.GuiObs.parameter.pop(0) is obj.ViewObject)
2299
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2302
self.GuiDoc1.resetEdit()
2303
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2304
self.assertTrue(self.GuiObs.signal.pop(0) == "ObjResetEdit")
2305
self.assertTrue(self.GuiObs.parameter.pop(0) is obj.ViewObject)
2307
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2310
obj.ViewObject.addExtension("Gui::ViewProviderGroupExtensionPython")
2311
self.assertTrue(self.Obs.signal.pop() == "ObjDynExt")
2312
self.assertTrue(self.Obs.parameter.pop() is obj.ViewObject)
2313
self.assertTrue(self.Obs.parameter2.pop() == "Gui::ViewProviderGroupExtensionPython")
2314
self.assertTrue(self.Obs.signal.pop() == "ObjBeforeDynExt")
2315
self.assertTrue(self.Obs.parameter.pop() is obj.ViewObject)
2316
self.assertTrue(self.Obs.parameter2.pop() == "Gui::ViewProviderGroupExtensionPython")
2317
# a proxy property was changed, hence those events are also in the signal list (but of GUI observer)
2321
FreeCAD.ActiveDocument.removeObject(obj.Name)
2322
self.assertTrue(self.Obs.signal.pop(0) == "ObjDeleted")
2323
self.assertTrue(self.Obs.parameter.pop(0) is obj)
2324
self.assertTrue(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
2325
self.assertTrue(self.GuiObs.signal.pop() == "ObjDeleted")
2326
self.assertTrue(self.GuiObs.parameter.pop() is vo)
2328
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2331
FreeCAD.closeDocument(self.Doc1.Name)
2333
self.assertTrue(self.GuiObs.signal.pop() == "DocDeleted")
2334
self.assertTrue(self.GuiObs.parameter.pop() is self.GuiDoc1)
2336
not self.GuiObs.signal and not self.GuiObs.parameter and not self.GuiObs.parameter2
2339
FreeCAD.Gui.removeDocumentObserver(self.GuiObs)
2344
FreeCAD.removeDocumentObserver(self.Obs)
2349
class FeatureTestColumn(unittest.TestCase):
2351
doc = FreeCAD.newDocument("TestColumn")
2352
self.obj = doc.addObject("App::FeatureTestColumn", "Column")
2354
def testEmpty(self):
2355
value = self.obj.Value
2356
self.obj.Column = ""
2357
self.assertFalse(self.obj.recompute())
2358
self.assertEqual(self.obj.Value, value)
2361
self.obj.Column = "A"
2362
self.obj.recompute()
2363
self.assertEqual(self.obj.Value, 0)
2366
self.obj.Column = "Z"
2367
self.obj.recompute()
2368
self.assertEqual(self.obj.Value, 25)
2371
self.obj.Column = "AA"
2372
self.obj.recompute()
2373
self.assertEqual(self.obj.Value, 26)
2376
self.obj.Column = "AB"
2377
self.obj.recompute()
2378
self.assertEqual(self.obj.Value, 27)
2381
self.obj.Column = "AZ"
2382
self.obj.recompute()
2383
self.assertEqual(self.obj.Value, 51)
2386
self.obj.Column = "BA"
2387
self.obj.recompute()
2388
self.assertEqual(self.obj.Value, 52)
2391
self.obj.Column = "CB"
2392
self.obj.recompute()
2393
self.assertEqual(self.obj.Value, 79)
2396
self.obj.Column = "ZA"
2397
self.obj.recompute()
2398
self.assertEqual(self.obj.Value, 676)
2401
self.obj.Column = "ZZ"
2402
self.obj.recompute()
2403
self.assertEqual(self.obj.Value, 701)
2406
self.obj.Column = "AAA"
2407
self.obj.recompute()
2408
self.assertEqual(self.obj.Value, 702)
2411
self.obj.Column = "AAZ"
2412
self.obj.recompute()
2413
self.assertEqual(self.obj.Value, 727)
2416
self.obj.Column = "CBA"
2417
self.obj.recompute()
2418
self.assertEqual(self.obj.Value, 2080)
2421
self.obj.Column = "AZA"
2422
self.obj.recompute()
2423
self.assertEqual(self.obj.Value, 1352)
2426
self.obj.Column = "ZZA"
2427
self.obj.recompute()
2428
self.assertEqual(self.obj.Value, 18252)
2431
self.obj.Column = "ZZZ"
2432
self.obj.recompute()
2433
self.assertEqual(self.obj.Value, 18277)
2436
self.obj.Column = "ALL"
2437
self.obj.recompute()
2438
self.assertEqual(self.obj.Value, 999)
2441
value = self.obj.Value
2442
self.obj.Column = "Ab"
2443
self.assertFalse(self.obj.recompute())
2444
self.assertEqual(self.obj.Value, value)
2447
value = self.obj.Value
2448
self.obj.Column = "ABCD"
2449
self.assertFalse(self.obj.recompute())
2450
self.assertEqual(self.obj.Value, value)
2452
def testEmptySilent(self):
2453
self.obj.Column = ""
2454
self.obj.Silent = True
2455
self.assertTrue(self.obj.recompute())
2456
self.assertEqual(self.obj.Value, -1)
2458
def testAbSilent(self):
2459
self.obj.Column = "Ab"
2460
self.obj.Silent = True
2461
self.assertTrue(self.obj.recompute())
2462
self.assertEqual(self.obj.Value, -1)
2464
def testABCDSilent(self):
2465
self.obj.Column = "ABCD"
2466
self.obj.Silent = True
2467
self.assertTrue(self.obj.recompute())
2468
self.assertEqual(self.obj.Value, -1)
2471
FreeCAD.closeDocument("TestColumn")
2474
class FeatureTestRow(unittest.TestCase):
2476
doc = FreeCAD.newDocument("TestRow")
2477
self.obj = doc.addObject("App::FeatureTestRow", "Row")
2479
def testEmpty(self):
2480
self.obj.Silent = True
2482
self.obj.recompute()
2483
self.assertEqual(self.obj.Value, -1)
2486
self.obj.Silent = True
2488
self.obj.recompute()
2489
self.assertEqual(self.obj.Value, -1)
2491
def testException(self):
2492
value = self.obj.Value
2494
self.assertFalse(self.obj.recompute())
2495
self.assertEqual(self.obj.Value, value)
2498
self.obj.Silent = True
2500
self.obj.recompute()
2501
self.assertEqual(self.obj.Value, -1)
2504
self.obj.Silent = True
2506
self.obj.recompute()
2507
self.assertEqual(self.obj.Value, 0)
2509
def test16384(self):
2510
self.obj.Silent = True
2511
self.obj.Row = "16384"
2512
self.obj.recompute()
2513
self.assertEqual(self.obj.Value, 16383)
2515
def test16385(self):
2516
self.obj.Silent = True
2517
self.obj.Row = "16385"
2518
self.obj.recompute()
2519
self.assertEqual(self.obj.Value, -1)
2522
FreeCAD.closeDocument("TestRow")
2525
class FeatureTestAbsAddress(unittest.TestCase):
2527
doc = FreeCAD.newDocument("TestAbsAddress")
2528
self.obj = doc.addObject("App::FeatureTestAbsAddress", "Cell")
2530
def testAbsoluteA12(self):
2531
self.obj.Address = "$A$12"
2532
self.obj.recompute()
2533
self.assertEqual(self.obj.Valid, True)
2535
def testAbsoluteA13(self):
2536
self.obj.Address = "A$13"
2537
self.obj.recompute()
2538
self.assertEqual(self.obj.Valid, True)
2540
def testAbsoluteAA13(self):
2541
self.obj.Address = "AA$13"
2542
self.obj.recompute()
2543
self.assertEqual(self.obj.Valid, True)
2545
def testAbsoluteZZ12(self):
2546
self.obj.Address = "$ZZ$12"
2547
self.obj.recompute()
2548
self.assertEqual(self.obj.Valid, True)
2550
def testAbsoluteABC1(self):
2551
self.obj.Address = "$ABC1"
2552
self.obj.recompute()
2553
self.assertEqual(self.obj.Valid, False)
2555
def testAbsoluteABC2(self):
2556
self.obj.Address = "ABC$2"
2557
self.obj.recompute()
2558
self.assertEqual(self.obj.Valid, False)
2560
def testRelative(self):
2561
self.obj.Address = "A1"
2562
self.obj.recompute()
2563
self.assertEqual(self.obj.Valid, False)
2565
def testInvalid(self):
2566
self.obj.Address = "A"
2567
self.obj.recompute()
2568
self.assertEqual(self.obj.Valid, False)
2570
def testEmpty(self):
2571
self.obj.Address = ""
2572
self.obj.recompute()
2573
self.assertEqual(self.obj.Valid, False)
2576
FreeCAD.closeDocument("TestAbsAddress")
2579
class FeatureTestAttribute(unittest.TestCase):
2581
self.doc = FreeCAD.newDocument("TestAttribute")
2582
self.doc.UndoMode = 0
2584
def testValidAttribute(self):
2585
obj = self.doc.addObject("App::FeatureTestAttribute", "Attribute")
2587
obj.Attribute = "Name"
2588
self.doc.recompute()
2589
self.assertIn("Up-to-date", obj.State)
2591
def testInvalidAttribute(self):
2592
obj = self.doc.addObject("App::FeatureTestAttribute", "Attribute")
2594
obj.Attribute = "Name123"
2595
self.doc.recompute()
2596
self.assertIn("Invalid", obj.State)
2597
self.assertIn("Touched", obj.State)
2599
def testRemoval(self):
2600
obj = self.doc.addObject("App::FeatureTestAttribute", "Attribute")
2602
self.assertEqual(self.doc.removeObject("Attribute"), None)
2605
FreeCAD.closeDocument("TestAttribute")