Coverage for src/robotide/controller/filecontrollers.py: 75%
945 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-06 10:40 +0100
1# Copyright 2008-2015 Nokia Networks
2# Copyright 2016- Robot Framework Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
16import os 1ab
17import shutil 1ab
18import stat 1ab
19import subprocess 1ab
20import sys 1ab
21from itertools import chain 1ab
22from .dataloader import ExcludedDirectory, test_data 1ab
23from ..publish import (RideDataFileRemoved, RideInitFileRemoved, RideDataChangedToDirty, RideDataDirtyCleared, 1ab
24 RideSuiteAdded, RideItemSettingsChanged)
25from ..publish.messages import RideDataFileSet, RideOpenResource 1ab
26from ..robotapi import TestDataDirectory, TestCaseFile, ResourceFile 1ab
27from .. import utils 1ab
29from .basecontroller import WithUndoRedoStacks, _BaseController, WithNamespace, ControllerWithParent 1ab
30from .robotdata import new_test_case_file, new_test_data_directory 1ab
31from .settingcontrollers import (DocumentationController, FixtureController, TimeoutController, TemplateController, 1ab
32 DefaultTagsController, ForceTagsController, TestTagsController)
33from .tablecontrollers import (VariableTableController, TestCaseTableController, KeywordTableController, 1ab
34 ImportSettingsController, MetadataListController)
35from .macrocontrollers import TestCaseController, UserKeywordController 1ab
38def _get_controller(project, data, parent, tasks=False): 1ab
39 if isinstance(data, TestCaseFile): 2a V B A X Y p e M C { | } ~ ab0 [ 1 2 3 ] 4 5 6 bb
40 return TestCaseFileController(data, project, parent, tasks=tasks) 2a V B A p e M C { | } ~ ab0 [ 1 2 3 ] 4 5 6 bb
41 if isinstance(data, ExcludedDirectory): 41 ↛ 42line 41 didn't jump to line 42 because the condition on line 41 was never true1aXY
42 return ExcludedDirectoryController(data, project, parent)
43 if isinstance(data, ResourceFile): 1aXY
44 from ..controller.project import Project
45 from ..namespace import Namespace
46 import tempfile
47 if not data.parent: 47 ↛ 59line 47 didn't jump to line 59 because the condition on line 47 was always true
48 data.parent = Project(Namespace(data.settings), data.settings)
49 content = bytes(f"*** Settings ***\n"
50 f"Resource {data.source}\n\n"
51 f"*** Test Cases ***\n"
52 f"Empty\n"
53 f" No Operation\n",
54 encoding='utf-8')
55 stub = tempfile.NamedTemporaryFile(delete=False)
56 with stub:
57 stub.write(content)
58 data.parent.load_data(stub.name)
59 return TestCaseFileController(data, project, data.parent) # DEBUG Here we create a dummy Project
60 return TestDataDirectoryController(data, project, parent, tasks=tasks) 1aXY
63def data_controller(data, project, parent=None, tasks=False): 1ab
64 return _get_controller(project, data, parent, tasks=tasks) 2a V B A X Y p e M C { | } ~ ab0 [ 1 2 3 ] 4 5 6 bb
67def explorer_linux(folder): 1ab
68 try: 2,c
69 subprocess.Popen(["nautilus", folder]) 2,c
70 except OSError: 2,c
71 try: 2,c
72 subprocess.Popen(["dolphin", folder]) 2,c
73 except OSError: 2,c
74 try: 2,c
75 subprocess.Popen(["konqueror", folder]) 2,c
76 except OSError: 2,c
77 print("Could not launch explorer. Tried nautilus, dolphin and konqueror.") 2,c
80def explorer_mac(folder): 1ab
81 try: 2!e]b1c
82 subprocess.Popen(["finder", folder]) 2!e]b1c
83 except OSError: 2!e]b1c
84 subprocess.Popen(["open", folder]) 2!e]b1c
87def start_filemanager(path=None, tool=None): 1ab
88 if not os.path.exists(path): 2wf]b1c
89 return 2wf
90 if not os.path.isfile(path): 90 ↛ 91line 90 didn't jump to line 91 because the condition on line 90 was never true2]b1c
91 folder = path
92 else:
93 folder = os.path.dirname(path) 2]b1c
94 if tool: 2]b1c
95 try: 2]b
96 subprocess.Popen([tool, folder]) 2]b
97 return
98 except OSError: 2]b
99 print(f"DEBUG: Error when launching tool={tool}") 2]b
100 if sys.platform == 'win32': 100 ↛ 101line 100 didn't jump to line 101 because the condition on line 100 was never true2]b1c
101 os.startfile(folder, 'explore')
102 elif sys.platform.startswith('linux'): 102 ↛ 103line 102 didn't jump to line 103 because the condition on line 102 was never true2]b1c
103 explorer_linux(folder)
104 else:
105 explorer_mac(folder) 2]b1c
108class _FileSystemElement(object): 1ab
110 def __init__(self, filename, directory): 1ab
111 self.filename = filename 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebmdh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
112 self.directory = directory 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebmdh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
113 self._stat = self._get_stat(filename) 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebmdh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
115 @staticmethod 1ab
116 def _get_stat(path): 1ab
117 if path and os.path.isfile(path): 2a J K E V F D w x ^ U L s t v G u q r :c9b;cy jbP Q kblbR S T B A X Y _ obH cbdbeb-cPemdh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
118 stats = os.stat(path) 2a V F p e z ? M C mbN ` nbZ f c i k l j 0 [ 1 2 3 ] 4 5 6
119 return stats.st_mtime, stats.st_size 2a V F p e z ? M C mbN ` nbZ f c i k l j 0 [ 1 2 3 ] 4 5 6
120 return 0, 0 2a J K E D w x ^ U L s t v G u q r :c9b;cy jbP Q kblbR S T B A X Y _ obH cbdbeb-cPemdh g d m o n 7 8 9 fbgbhbe f c i k l j W @ pbqbrbsb{ | } ~ abbb! # $ % ' ( ) * + , - . / : ; =
122 def refresh_stat(self): 1ab
123 self._stat = self._get_stat(self.filename) 2a :c9b;cP Q R S T -cPeh g d N f c i k l j
125 def has_been_modified_on_disk(self): 1ab
126 return self._get_stat(self.filename) != self._stat 2M mbN nb
128 def has_been_removed_from_disk(self): 1ab
129 return self._stat != (0, 0) and not self.exists()
131 def relative_path_to(self, other): 1ab
132 other_path = os.path.join(other.directory, other.filename) 2md
133 return os.path.relpath(other_path, start=self.directory).replace('\\', '/') 2md
135 def is_readonly(self): 1ab
136 return not os.access(self.filename, os.W_OK) 2a bc2c3cccdc?b4cecfcgchc5c=c[b^b_b`b{b6cacmcncocic?cjc|bkc7c8cZb=b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJcKcO N #b(b;b9cLcMc!cBbEbtbiblc
138 def exists(self): 1ab
139 return self.filename and os.path.isfile(self.filename) 2a bc2c3cccdc?b4cecfcgchc5c=c[b^b_b`b{b6cacmcncocic?cjc|bkcE F D s t v G u q r :c9b;cndodpd#c$c%c_eqdrdsdtdudvdwdxdydzdAdBdCdDd`eEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d{e4d5d6d7d8d9d!d#d$d%d'd|e(d)d*d+d,d-d.d/d:d}e;d=d?d@d[d]d~e^d_d`d{d|d}d~daebeafce'c(c7c8cP Q R S T )bZb=b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJch g d m o n deeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDebfcfdfefEeFeGeHeIeJeKeffgfhfifLeMeNcOcPcQcRcScTcUcVc)cWcXc*c7 8 9 KcO p e z N Z #b(b;b9cLcMc!cFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbBbEbtbf c i k l j .c@c[c]c^c_c`cW @ iblc
141 @property 1ab
142 def basename(self): 1ab
143 return os.path.splitext(os.path.basename(self.filename))[0]
145 @property 1ab
146 def source(self): 1ab
147 """Deprecated, use ``filename`` or ``directory`` instead."""
148 # DEBUG: remove when backwards compatibility with plugin API can break
149 return self.filename or self.directory 2a y ebWbxbybiblc
152class _DataController(_BaseController, WithUndoRedoStacks, WithNamespace): 1ab
153 directory = None 1ab
155 def __init__(self, data, project=None, parent=None): 1ab
156 self.data = data 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
157 self._variables_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
158 self._testcase_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
159 self._keywords_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
160 self._imports = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
161 self._project = project 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
162 if project: 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
163 self._set_namespace_from(project) 1aJKEVFDyHhgdmonpez?Nfciklj
164 self._resource_file_controller_factory =\ 1aJKEVFDyHhgdmonpez?Nfciklj
165 project.resource_file_controller_factory
166 else:
167 self._resource_file_controller_factory = None 2a J K w x ^ U L s t v G u q r jbP Q kblbR S T B A X Y _ obcbdbeb7 8 9 fbgbhbM C mb` nbZ W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
168 self.parent = parent 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
169 try: 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
170 self._language = self.data._language 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
171 # print(f"DEBUG: filecontrollers.py _DataController language set = {self._language}")
172 except AttributeError: 2a 7 8 9 fbgbhb
173 self._language = ['en'] 2a 7 8 9 fbgbhb
174 self.set_datafile(data) 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
175 self.dirty = False 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
176 self.children = self._children(data) 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
177 # Filename needs to be set when creating a new datafile
178 if hasattr(self.data, 'initfile'): 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
179 self.filename = self.data.initfile 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
180 else:
181 self.filename = self.data.source 2a J K E V F D w x L s t v G u q r jbP Q kblbR S T B A h g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
183 def set_datafile(self, datafile): 1ab
184 self.data = datafile 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
185 self._variables_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
186 self._testcase_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
187 self._keywords_table_controller = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
188 self._imports = None 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
189 RideDataFileSet(item=self).publish() 2a J K E V F D w x ^ U L s t v G u q r y jbP Q kblbR S T B A X Y _ obH cbdbebh g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
191 def _children(self, data): 1ab
192 _ = data 2a J K E V F D w x L s t v G u q r jbP Q kblbR S T B A h g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
193 return [] 2a J K E V F D w x L s t v G u q r jbP Q kblbR S T B A h g d m o n 7 8 9 fbgbhbp e z ? M C mbN ` nbZ f c i k l j W @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
195 @property 1ab
196 def name(self): 1ab
197 return self.data.name 2a xfzbfdE F D w x ^ U L G y #eY Zbz :bAbI Dbubvbwbj Ne{c|ciblc
199 @property 1ab
200 def settings(self): 1ab
201 return self.internal_settings() 2Yc_ C *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbyb
203 def internal_settings(self): 1ab
204 ss = self.data.setting_table 2Yc_ C *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
205 return [DocumentationController(self, ss.doc), 2Yc_ C *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
206 FixtureController(self, ss.suite_setup),
207 FixtureController(self, ss.suite_teardown),
208 FixtureController(self, ss.test_setup),
209 FixtureController(self, ss.test_teardown),
210 self.force_tags, self.test_tags]
212 @property 1ab
213 def setting_table(self): 1ab
214 return self.data.setting_table 29b#c$c%cYc_ }c~cC *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxb.c@c[c]c^c_cQeReSeTeUe`c$eadgdybW @ hdVe%e
216 @property 1ab
217 def force_tags(self): 1ab
218 return ForceTagsController(self, self.setting_table.force_tags) 29b#c$c%cYc_ }c~cC *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxb.c@c[c]c^c_cQeReSeTeUe`c$eadgdybW @ hdVe%e
220 @property 1ab
221 def test_tags(self): 1ab
222 return TestTagsController(self, self.setting_table.test_tags) 29b#c$c%cYc_ }c~cC *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxb.c@c[c]c^c_cQeReSeTeUe`c$eadgdybW @ hdVe%e
224 @property 1ab
225 def variables(self): 1ab
226 if self._variables_table_controller is None: 2a 7c8c=bLcMc!cAbVbI Db@bbd
227 self._variables_table_controller = VariableTableController(self, self.data.variable_table) 2a 7c8c=bLcMcAb
228 return self._variables_table_controller 2a 7c8c=bLcMc!cAbVbI Db@bbd
230 @property 1ab
231 def tests(self): 1ab
232 if self._testcase_table_controller is None: 2a J yfzfAfBfCfDfK w x L 9b+ccd)b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJc)c*c` #b(b;b9c*b!b$b+b,b-b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbadgdybWe2 ! # $ % ' ( {c@bbd
233 self._testcase_table_controller = TestCaseTableController(self, self.data.testcase_table) 2a J K w x L +ccd)b}b)c*c` #b*bFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYbXbxbadyb2 ! # $ % ' (
234 return self._testcase_table_controller 2a J yfzfAfBfCfDfK w x L 9b+ccd)b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJc)c*c` #b(b;b9c*b!b$b+b,b-b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbadgdybWe2 ! # $ % ' ( {c@bbd
236 @property 1ab
237 def datafile(self): 1ab
238 return self.data 2a bc2c3cccdc?b4cecidjdfcgchc5c=c[b^b_b`b{b6cacmckdncocic?cjc|bkcw x L 9b#c$c%cXeYeZe'c(c7c8c+cddedcd)b/bYfZf0f1f2f0e3f4fNcOcPcQcRcScTcUcVc)cWcXc*c}c~c5f1e2eEf3eN #b(b;b9cLcMc!cCbWbtbf c i k l j 4e5e6eld7eadgdybWeFfGfHfIfJfKfLfMf6f7f8f9f!f#f$f%f'f(f)f*f0 +f,f[ -f.f/f:f;f=f?fNf@f[f1 2 3 ] 4 ]f5 6 bb! # $ % ' ( ) * + , - . / : ; = {c|c
240 @property 1ab
241 def datafiles(self): 1ab
242 return chain([self], (df for df in self._project.datafiles 2a zbh g d m o n O *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbc ybib
243 if df != self))
245 @property 1ab
246 def datafile_controller(self): 1ab
247 return self 2a J K bc2c3cccdc?b4cecidjdfcgchc5c=c[b^b_b`b{b6cacmckdncocic?cjc|bkcw x L :c9b;cndodpd#c$c%c_eqdrdsdtdudvdwdxdydzdAdBdCdDd`eEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d{e4d5d6d7d8d9d!d#d$d%d'd|e(d)d*d+d,d-d.d/d:d}e;d=d?d@d[d]d~e^d_d`d{d|d}d~daebeafce'e(e)e*e8e+e,e-e.e/e:eXeYeZe'c(c7c8cP Q R S T +cddedcd)b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJch g d m n deeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDebfcfdfefEeFeGeHeIeJeKeffgfhfifLeMeNcOcPcQcRcScTcUcVc)cWcXc*c}c~c1e2eEf3e;e=eO N ` Z #b(b;b9cLcMc!c*b!b$b+b,b-b:b.b%b'bAbVbI DbjfFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j 4e5e6e.c@c[c]c^c_cQeReSeTeUe`c$eld7eadgdybW @ pbqbrbsb{ | } ~ abhdVe%e^fWeFfGfHfIfJf_fKfLfMf0 1 2 3 4 5 6 ! # $ % ' ( ) * + , - . / : ; = {c|cib/clc
249 @property 1ab
250 def keywords(self): 1ab
251 if self._keywords_table_controller is None: 2a ?b9b'c(cddedZbNcOcPcQcRcScTcUcVcWcXcZ #b(b;b!b$b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j ld7eyb0 1 3 4 5 6 ) * + , - . / : ; = |cOfPf@bbd
252 self._keywords_table_controller = KeywordTableController(self, self.data.keyword_table) 2a 9b'c(cddedZbNcOcPcQcRcScTcUcVcWcXcZ #b(b!bFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYbXbxbf c i k l j ldyb0 1 3 4 5 6 ) * + , - . / : ; =
253 return self._keywords_table_controller 2a ?b9b'c(cddedZbNcOcPcQcRcScTcUcVcWcXcZ #b(b;b!b$b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j ld7eyb0 1 3 4 5 6 ) * + , - . / : ; = |cOfPf@bbd
255 @property 1ab
256 def imports(self): 1ab
257 if not self._imports: 2a zb[b^b_b`b{bE F D h g d m o n 0eO z AbVbI Dbf c i k l j ib/cQflc
258 self._imports = ImportSettingsController(self, self.data.setting_table, 2a zb[bE F D h g d m o n 0eO z AbI f c i k l j ib
259 self._resource_file_controller_factory)
260 return self._imports 2a zb[b^b_b`b{bE F D h g d m o n 0eO z AbVbI Dbf c i k l j ib/cQflc
262 @property 1ab
263 def metadata(self): 1ab
264 return MetadataListController(self, self.data.setting_table)
266 def is_user_keyword(self, datafile, value): 1ab
267 _ = datafile 2bc2c3cccdc?b4cecidjdfcgchc5c[b^b_b`b{b6cacmckdncocicjc|bkc/b#b(b;bf c i
268 # print(f"DEBUG: filecontrollers.py _DataController is_user_keyword datafile={datafile} "
269 # f" value={value}")
270 return WithNamespace.is_user_keyword(self, self.datafile, value) 2bc2c3cccdc?b4cecidjdfcgchc5c[b^b_b`b{b6cacmckdncocicjc|bkc/b#b(b;bf c i
272 def is_library_keyword(self, datafile, value): 1ab
273 _ = datafile 2ccdc?becidjdfcgchc[b^b_b`b{bacmckdncocicjc|bkc/bf c i
274 return WithNamespace.is_library_keyword(self, self.datafile, value) 2ccdc?becidjdfcgchc[b^b_b`b{bacmckdncocicjc|bkc/bf c i
276 def keyword_info(self, datafile, keyword_name): 1ab
277 _ = datafile 2bc2c3cccdc?b4cecidjdfcgchc5c=c[b^b_b`b{b6cacmckdncocic?cjc|bkc/b#b(b;b*b!b$b+b,b-b:b.b%b'bAbVbI DbjfFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i yb
278 return WithNamespace.keyword_info(self, self.data, keyword_name) 2bc2c3cccdc?b4cecidjdfcgchc5c=c[b^b_b`b{b6cacmckdncocic?cjc|bkc/b#b(b;b*b!b$b+b,b-b:b.b%b'bAbVbI DbjfFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i yb
280 def mark_dirty(self): 1ab
281 if not self.dirty: 2a bc2c3cccdc?b4cecfcgchc5c=c[b^b_b`b{b6cacmcncocic?cjc|bkcw x L 9bndodpd#c$c%cqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]d^d_d`d{d|d}d~daebece'e(e)e*e8e+e,e-e.e/e:ekflfXeYemfZenfofOe'c(c7c8c+cddedcd)bB A cb-cpfqfZb=b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJcd m n deeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNcOcPcQcRcScTcUcVc)cWcXc*c}c~crfsf1e2e3etf;e=eO #b(b;b9cLcMc!cFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbBbEbtbxbf c i k l j 4e5e6e.c@c[c]c^c_c`cld7eadgdW hd! # $ % ' ( ) * + , - . / : ; = {c|c@bbd/c
282 self.dirty = True 2a bcac|bw x L 9bndodpd#c$c%cqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]d^d_d`d{d|d}d~daebece'e(e)e*e8e+e,e-e.e/e:ekflfXeYemfZenfofOe'c(c7c8c+cddedcd)bB A cb-cpfqfZb=b}bd m n deeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNcOcPcQcRcScTcUcVc)cWcXc*c}c~crfsf1e2e3etf;e=eO #b(bFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbBbtbxbf c i k l j 4e5e6e.c@c[c]c^c_c`cldW hd! # $ % ' ( ) * + , - . / : ; = {c|c@bbd/c
283 RideDataChangedToDirty(datafile=self).publish() 2a bcac|bw x L 9bndodpd#c$c%cqdrdsdtdudvdwdxdydzdAdBdCdDdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d4d5d6d7d8d9d!d#d$d%d'd(d)d*d+d,d-d.d/d:d;d=d?d@d[d]d^d_d`d{d|d}d~daebece'e(e)e*e8e+e,e-e.e/e:ekflfXeYemfZenfofOe'c(c7c8c+cddedcd)bB A cb-cpfqfZb=b}bd m n deeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDeEeFeGeHeIeJeKeLeMeNcOcPcQcRcScTcUcVc)cWcXc*c}c~crfsf1e2e3etf;e=eO #b(bFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbBbtbxbf c i k l j 4e5e6e.c@c[c]c^c_c`cldW hd! # $ % ' ( ) * + , - . / : ; = {c|c@bbd/c
285 def unmark_dirty(self): 1ab
286 self.refresh_stat() 2a :c9b;cP Q R S T -cPeh g d N f c i k l j
287 if self.dirty: 2a :c9b;cP Q R S T -cPeh g d N f c i k l j
288 self.dirty = False 29b-cf c i k l j
289 # print(f"DEBUG: filecontrollers unmark_dirty PUBLISH RideDataDirtyCleared")
290 RideDataDirtyCleared(datafile=self).publish() 29b-cf c i k l j
292 @property 1ab
293 def is_dirty(self): 1ab
294 return self.dirty 2We
296 def create_keyword(self, name, argstr=''): 1ab
297 return self.keywords.new(name, argstr) 2?b'c(cddedNcOcPcQcRcScTcUcVcWcXcf c i k l j ) * + , - . / : ; = |c
299 def add_test_or_keyword(self, item): 1ab
300 if isinstance(item, TestCaseController): 2+c)b#b(b;b9cLcMc!c
301 self.tests.add(item) 2+c)b9c
302 item.set_parent(self.tests) 2+c)b9c
303 elif isinstance(item, UserKeywordController): 2#b(b;bLcMc!c
304 self.keywords.add(item) 2#b(b;b
305 item.set_parent(self.keywords) 2#b(b;b
306 else:
307 self.variables.add_variable(item.name, item.value, item.comment) 2LcMc!c
309 def sort_tests(self): 1ab
310 if self.tests: 310 ↛ 315line 310 didn't jump to line 315 because the condition on line 310 was always true2)b
311 index_difference = self.tests.sort() 2)b
312 self.mark_dirty() 2)b
313 RideDataFileSet(item=self).publish() 2)b
314 return index_difference 2)b
315 return None
317 def sort_keywords(self): 1ab
318 if self.keywords: 318 ↛ 323line 318 didn't jump to line 323 because the condition on line 318 was always true2Zb
319 index_difference = self.keywords.sort() 2Zb
320 self.mark_dirty() 2Zb
321 RideDataFileSet(item=self).publish() 2Zb
322 return index_difference 2Zb
323 return None
325 def sort_variables(self): 1ab
326 if self.variables: 326 ↛ 331line 326 didn't jump to line 331 because the condition on line 326 was always true2=b
327 index_difference = self.variables.sort() 2=b
328 self.mark_dirty() 2=b
329 RideDataFileSet(item=self).publish() 2=b
330 return index_difference 2=b
331 return None
333 def restore_test_order(self, index_difference): 1ab
334 if self.tests and index_difference: 334 ↛ exitline 334 didn't return from function 'restore_test_order' because the condition on line 334 was always true2)b
335 self.tests.restore_test_order(index_difference) 2)b
336 self.mark_dirty() 2)b
337 RideDataFileSet(item=self).publish() 2)b
339 def restore_keyword_order(self, index_difference): 1ab
340 if self.keywords and index_difference: 340 ↛ exitline 340 didn't return from function 'restore_keyword_order' because the condition on line 340 was always true2Zb
341 self.keywords.restore_keyword_order(index_difference) 2Zb
342 self.mark_dirty() 2Zb
343 RideDataFileSet(item=self).publish() 2Zb
345 def restore_variable_order(self, index_difference): 1ab
346 if self.variables and index_difference: 346 ↛ exitline 346 didn't return from function 'restore_variable_order' because the condition on line 346 was always true2=b
347 self.variables.restore_variable_order(index_difference) 2=b
348 self.mark_dirty() 2=b
349 RideDataFileSet(item=self).publish() 2=b
351 def get_keyword_names(self): 1ab
352 if self.keywords: 352 ↛ 354line 352 didn't jump to line 354 because the condition on line 352 was always true2Zbxb
353 return [kw.name for kw in self.keywords.items] 2Zbxb
354 return None
356 def has_format(self): 1ab
357 return True 2a `f
359 def get_format(self): 1ab
360 if not self.filename: 360 ↛ 361line 360 didn't jump to line 361 because the condition on line 360 was never true2a jbP Q kblbR S T Rfh g d
361 return None
362 return os.path.splitext(self.filename)[1].replace('.', '') 2a jbP Q kblbR S T Rfh g d
364 def set_format(self, formatt): 1ab
365 self.data.source = utils.replace_extension(self.filename, formatt) 2a Sfm o n
366 self.filename = self.data.source 2a Sfm o n
368 def is_same_format(self, formatt): 1ab
369 if formatt and self.has_format():
370 return formatt.lower() == self.get_format().lower()
371 return False
373 def set_basename(self, basename): 1ab
374 from .ctrlcommands import SaveFile 1PQRSThgd
376 old_file = self.filename 1PQRSThgd
377 self.data.source = os.path.join(self.directory, '%s.%s' % (basename, self.get_format())) 1PQRSThgd
378 self.filename = self.data.source 1PQRSThgd
379 self.execute(SaveFile()) 1PQRSThgd
380 if old_file != self.filename: 380 ↛ exitline 380 didn't return from function 'set_basename' because the condition on line 380 was always true1PQRSThgd
381 self.remove_from_filesystem(old_file) 1PQRSThgd
383 def remove_readonly(self, path=None): 1ab
384 path = path or self.filename
385 os.chmod(path, stat.S_IWRITE)
387 def open_filemanager(self, path=None, tool=None): 1ab
388 path = path or self.filename
389 start_filemanager(path, tool)
391 def remove_from_filesystem(self, path=None): 1ab
392 path = path or self.filename 2KcO
393 if os.path.exists(path): 393 ↛ exitline 393 didn't return from function 'remove_from_filesystem' because the condition on line 393 was always true2KcO
394 os.remove(path) 2KcO
396 def remove_folder_from_filesystem(self, path=None): 1ab
397 shutil.rmtree(path or self.data.directory)
399 def save_with_new_format(self, formatt): 1ab
400 self._project.change_format(self, formatt)
402 def save_with_new_format_recursive(self, formatt): 1ab
403 self._project.change_format_recursive(self, formatt)
405 def validate_keyword_name(self, name): 1ab
406 return self.keywords.validate_name(name) 2?bNcOcPcQcRcScTcUcVcWcXc
408 def is_directory_suite(self): 1ab
409 return False 1ahgdmon
411 def resource_import_modified(self, path): 1ab
412 return self._project.resource_import_modified(path, self.directory) 28ef c i k l j /c
414 def notify_settings_changed(self, old_name=None): 1ab
415 _ = old_name 2ubvbwbxbW
416 RideItemSettingsChanged(item=self).publish() 2ubvbwbxbW
418 def notify_steps_changed(self): 1ab
419 for test in self.tests:
420 test.notify_steps_changed()
422 def iter_datafiles(self): 1ab
423 yield self 2a zbfdV s t v u q r y ?eZb}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJch g d m o n O e *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j ybNeib
424 for child in self.children: 2a zbfdV s t v u q r y ?eZb}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJch g d m o n O e *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j ybNeib
425 for datafile in child.iter_datafiles(): 2a zbfds t q r y ?eZb}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJcO e AbVbI DbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbf c i k l j ybNeib
426 yield datafile 2a zbfds t q r y ?eZb}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJcO e AbVbI DbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbf c i k l j ybNeib
428 def save(self): 1ab
429 self._project.save(self) 2a :c9b;cN f c i k l j
431 @staticmethod 1ab
432 def get_local_variables(): 1ab
433 return {} 2[ Nf] bb
435 def is_inside_top_suite(self, res): 1ab
436 _ = res
437 return False
439 @staticmethod 1ab
440 def refresh_stat(): 1ab
441 return NotImplemented
444class TestDataDirectoryController(_DataController, _FileSystemElement, _BaseController): 1ab
445 __test__ = False 1ab
447 def __init__(self, data, project=None, parent=None, tasks=False): 1ab
448 dir_ = data.directory 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
449 dir_ = os.path.abspath(dir_) if isinstance(dir_, str) else dir_ 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
450 _FileSystemElement.__init__(self, self._filename(data), dir_) 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
451 _DataController.__init__(self, data, project, parent) 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
452 self._dir_controllers = {} 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
453 self.tasks = tasks 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
455 @staticmethod 1ab
456 def _filename(data): 1ab
457 return data.initfile 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
459 @property 1ab
460 def default_dir(self): 1ab
461 return self.data.source 2ob
463 @property 1ab
464 def display_name(self): 1ab
465 return self.data.name 2a dbyb
467 @property 1ab
468 def language(self): 1ab
469 return self._language
471 @property 1ab
472 def longname(self): 1ab
473 if self.parent: 2db
474 return self.parent.longname + '.' + self.display_name 2db
475 return self.display_name 2db
477 @property 1ab
478 def suites(self): 1ab
479 return [child for child in self.children if 2a xfw x U Oe0e
480 isinstance(child, TestDataDirectoryController) or
481 isinstance(child, TestCaseFileController)]
483 def add_child(self, controller): 1ab
484 assert controller not in self.children 1awxUstvuqrefciklj
485 self.children.append(controller) 1awxUstvuqrefciklj
487 def contains_tests(self): 1ab
488 for suite in self.suites:
489 if suite.contains_tests(): 489 ↛ 488line 489 didn't jump to line 488 because the condition on line 489 was always true
490 return True
491 return False
493 def find_controller_by_longname(self, longname, testname=None): 1ab
494 return self.find_controller_by_names(longname.split("."), testname) 1wx^U
496 def find_controller_by_names(self, names, testname): 1ab
497 namestring = '.'.join(names) 1wx^U
498 if not namestring.startswith(self.name): 498 ↛ 499line 498 didn't jump to line 499 because the condition on line 498 was never true1wx^U
499 return None
500 if namestring == self.name: 1wx^U
501 return self 1^U
502 for suite in self.suites: 502 ↛ exitline 502 didn't return from function 'find_controller_by_names' because the loop on line 502 didn't complete1wxU
503 res = suite.find_controller_by_names(namestring[len(self.name)+1:].split('.'), testname) 1wxU
504 if res: 1wxU
505 return res 1wxU
507 def is_excluded(self): 1ab
508 return self._project.is_excluded(self.source) if self._project else False
510 def _children(self, data): 1ab
511 children = [data_controller(child, self._project, self) for child in data.children] 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
512 if self._can_add_directory_children(data): 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
513 self._add_directory_children(children, data.source, data.initfile) 1aype
514 return children 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
516 def _can_add_directory_children(self, data): 1ab
517 return data.source and os.path.isdir(data.source) and self.namespace 2a J K w x ^ U s t v G u q r y B A X Y _ obH cbdbebp e M C
519 def _add_directory_children(self, children, path, initfile): 1ab
520 if not children: 1aype
521 return 1ay
522 for filename in self._get_unknown_files_in_directory(children, path, initfile): 1ape
523 if not self._is_robot_ignored_name(filename): 1ape
524 self._add_directory_child(children, filename) 1ape
526 @staticmethod 1ab
527 def _is_robot_ignored_name(filename): 1ab
528 base = os.path.basename(filename) 1ape
529 robotformat = (".txt", ".robot", ".resource", ".rst", " .rest", ".tsv") # Removed ".htm", ".html" 1ape
530 nonrobot_file = os.path.isfile(filename) and not base.endswith(robotformat) 1ape
531 hidden = base.startswith('.') 1ape
532 private = base.startswith('_') 1ape
533 return hidden or private or nonrobot_file 1ape
535 def _add_directory_child(self, children, filename): 1ab
536 if os.path.isdir(filename): 1ape
537 children.append(self._directory_controller(filename))
538 else:
539 r = self.namespace.get_resource(filename, report_status=False) 1ape
540 if self._is_valid_resource(r): 1ape
541 children.append(self._resource_controller(r)) 1ape
543 def _directory_controller(self, path): 1ab
544 dc = TestDataDirectoryController(TestDataDirectory(source=path),
545 project=self._project,
546 parent=self)
547 self._add_directory_children(dc.children, dc.source, None)
548 return dc
550 @staticmethod 1ab
551 def _is_valid_resource(resource): 1ab
552 return resource and (resource.setting_table or resource.variable_table or 1ape
553 resource.keyword_table or os.stat(resource.source)[6] == 0)
555 def _resource_controller(self, resource): 1ab
556 resource_control = self._resource_file_controller_factory.create(resource) 1ape
557 resource_control.parent = self 1ape
558 return resource_control 1ape
560 def _get_unknown_files_in_directory(self, children, path, initfile): 1ab
561 already_in_use = [c.filename for c in children] + [initfile] 1ape
562 already_in_use += [c.directory for c in children] 1ape
563 return [f for f in self._get_filenames_in_directory(path) if f not in already_in_use] 1ape
565 @staticmethod 1ab
566 def _get_filenames_in_directory(path): 1ab
567 return [os.path.join(path, f) for f in os.listdir(path)] 1ape
569 def has_format(self): 1ab
570 return self.data.initfile is not None 2a cbebe
572 def set_format(self, formatt): 1ab
573 self.data.initfile = os.path.join(self.data.source, '__init__.%s' 2a eb
574 % formatt.lower())
575 self.filename = self.data.initfile 2a eb
577 def new_test_case_file(self, path): 1ab
578 ctrl = self._new_data_controller(new_test_case_file(path, tasks=self.tasks)) 1BA
579 ctrl.mark_dirty() 1BA
580 return ctrl 1BA
582 def new_test_data_directory(self, path): 1ab
583 return self._new_data_controller(new_test_data_directory(path, tasks=self.tasks)) 1XY
585 def _new_data_controller(self, datafile): 1ab
586 self.data.children.append(datafile) 1BAXY
587 datafile.parent = self.data 1BAXY
588 self.children.append(data_controller(datafile, self._project, self, tasks=self.tasks)) 1BAXY
589 return self.children[-1] 1BAXY
591 def notify_suite_added(self, suite): 1ab
592 RideSuiteAdded(parent=self, suite=suite).publish() 1AX
594 def is_directory_suite(self): 1ab
595 return True 1aefciklj
597 def reload(self): 1ab
598 self.__init__(TestDataDirectory(source=self.directory, parent=self.data.parent, tasks=self.tasks).populate(), 1eC
599 self._project, parent=self.parent)
601 def remove(self): 1ab
602 path = self.filename 1e
603 self.data.initfile = None 1e
604 self._stat = self._get_stat(None) 1e
605 self.reload() 1e
606 RideInitFileRemoved(path=path, datafile=self).publish() 1e
608 def _remove_resources(self): 1ab
609 for resource in self._find_resources_recursively(self):
610 self._project.remove_resource(resource)
611 RideDataFileRemoved(path=resource.filename, datafile=resource).publish()
613 def remove_from_model(self): 1ab
614 self._project.remove_datafile(self)
615 self._remove_resources()
616 RideDataFileRemoved(path=self.filename, datafile=self).publish()
618 def remove_child(self, controller): 1ab
619 if controller in self.children: 619 ↛ 622line 619 didn't jump to line 622 because the condition on line 619 was always true1p
620 self.children.remove(controller) 1p
621 else:
622 for child in self.children:
623 child.remove_child(controller)
625 def is_inside_top_suite(self, ctrl): 1ab
626 return ctrl.filename.startswith(self.directory) 1astvGuqrfciklj
628 def _is_inside_test_data_directory(self, directory): 1ab
629 return any(True for s in [self] + self.children
630 if s.is_directory_suite() and s.directory == directory)
632 def remove_static_imports_to_this(self): 1ab
633 for resource_import in self.get_where_used():
634 resource_import[1].remove()
636 def get_where_used(self): 1ab
637 for imp in self._get_recursive_imports():
638 yield imp
640 def _all_imports(self): 1ab
641 for df in self.datafiles:
642 for imp in df.imports:
643 yield imp
645 def _get_recursive_imports(self): 1ab
646 all_imports = self._all_imports()
647 ctrls = self._find_controllers_recursively(self)
648 for res in self._find_resources_recursively(self):
649 for imp in all_imports:
650 if imp.get_imported_controller() == res and imp.parent.parent not in ctrls:
651 yield res, imp
653 def _find_resources_recursively(self, controller): 1ab
654 resources = []
655 if controller.children:
656 for child in controller.children:
657 resources += self._find_resources_recursively(child)
658 elif isinstance(controller, ResourceFileController):
659 resources.append(controller)
660 return resources
662 def _find_controllers_recursively(self, controller): 1ab
663 resources = []
664 if controller.children:
665 for child in controller.children:
666 resources += self._find_controllers_recursively(child)
667 resources.append(controller)
668 return resources
670 def insert_to_test_data_directory(self, res): 1ab
671 res_dir = os.path.dirname(res.filename) 1astvuqrfciklj
672 if res_dir in self._dir_controllers: 672 ↛ 673line 672 didn't jump to line 673 because the condition on line 672 was never true1astvuqrfciklj
673 self._dir_controllers[res_dir].add_child(res)
674 else:
675 target = self._find_closest_directory(res) 1astvuqrfciklj
676 if target is self: 1astvuqrfciklj
677 self._create_target_dir_controller(res, res_dir, target) 1astvuqrfciklj
678 else:
679 target.insert_to_test_data_directory(res) 1astqr
681 def _find_closest_directory(self, res): 1ab
682 target = self 1astvuqrfciklj
683 for s in self.iter_datafiles(): 1astvuqrfciklj
684 if not isinstance(s, TestDataDirectoryController): 1astvuqrfciklj
685 continue 1asqrfciklj
686 if res.filename.startswith(s.directory): 1astvuqrfciklj
687 target = s 1astvuqrfciklj
688 return target 1astvuqrfciklj
690 def _create_target_dir_controller(self, res, res_dir, target): 1ab
691 for dirname in res_dir[len(self.directory):].split(os.sep): 1astvuqrfciklj
692 if not dirname: 1astvuqrfciklj
693 continue 1astvuqrfciklj
694 target_dir = os.path.join(target.directory, dirname) 1stvuqr
695 dir_ctrl = TestDataDirectoryController(TestDataDirectory(source=target_dir, tasks=self.tasks), 1stvuqr
696 self._project, self, tasks=self.tasks)
697 target._dir_controllers[target.directory] = dir_ctrl 1stvuqr
698 target.add_child(dir_ctrl) 1stvuqr
699 if target_dir == res_dir: 1stvuqr
700 dir_ctrl.add_child(res) 1stvuqr
701 return 1stvuqr
702 target = dir_ctrl 1uq
703 if res not in self.children: 1aqrfciklj
704 self.add_child(res) 1qr
706 def new_resource(self, path): 1ab
707 ctrl = self._project.new_resource(path, parent=self)
708 ctrl.mark_dirty()
709 return ctrl
711 def exclude(self): 1ab
712 if self._project.is_datafile_dirty(self): 2y OeH
713 raise DirtyRobotDataException() 2Oe
714 self._project.internal_settings.excludes.update_excludes([self.directory]) 1yH
715 index = self.parent.children.index(self) 1yH
716 result = ExcludedDirectoryController(self.data, self._project, self.parent) 1yH
717 self.parent.children[index] = result 1yH
718 return result 1yH
720 def retrieve_test_controllers(self): 1ab
721 controllers: list[TestCaseController] = []
722 for child in self.children:
723 if isinstance(child, TestCaseFileController) or isinstance(child, TestDataDirectoryController):
724 controllers += child.retrieve_test_controllers()
725 return controllers
728class DirtyRobotDataException(Exception): 1ab
729 """
730 Raised when data is dirty, and you are trying to do an operation that requires undirty data.
731 """
732 pass 1ab
735class TestCaseFileController(_FileSystemElement, _DataController): 1ab
736 __test__ = False 1ab
738 def __init__(self, data, project=None, parent=None, tasks=False, lang=''): 1ab
739 _FileSystemElement.__init__(self, data.source if data else None, data.directory) 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
740 _DataController.__init__(self, data, project, parent) 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
741 self.tasks = tasks 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
742 self._language = lang if lang else self.get_language_from_settings() 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
744 def internal_settings(self): 1ab
745 ss = self.setting_table 2Yc*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
746 sett = _DataController.internal_settings(self) 2Yc*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
747 sett.insert(-1, TemplateController(self, ss.test_template)) 2Yc*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
748 sett.insert(-1, TimeoutController(self, ss.test_timeout)) 2Yc*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
749 return sett + [self.default_tags] 2Yc*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxbyb
751 def get_language_from_settings(self): 1ab
752 from ..preferences import RideSettings 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
753 _settings = RideSettings() 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
754 lang = _settings.get('doc language', '') 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
755 self.file_language = lang 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
756 return lang 2a J K V w x L jbP Q kblbR S T B A h g d m o n fbgbhbp e ? M C mbN ` nbW @ pbqbrbsb{ | } ~ ab0 [ 1 2 3 ] 4 5 6 bb! # $ % ' ( ) * + , - . / : ; =
758 @property 1ab
759 def longname(self): 1ab
760 if self.parent: 2w x #e
761 return self.parent.longname + '.' + self.name 2#e
762 return self.name 2w x #e
764 @property 1ab
765 def suites(self): 1ab
766 return ()
768 @property 1ab
769 def preamble(self): 1ab
770 return self.data.preamble
772 @property 1ab
773 def language(self): 1ab
774 return self.data.language 2a { | } ~ ab
776 def contains_tests(self): 1ab
777 return bool(self.tests)
779 def find_controller_by_longname(self, longname, node_testname=None): 1ab
780 return self.find_controller_by_names(longname.split("."), node_testname) 1L
782 def find_controller_by_names(self, names, node_testname=None): 1ab
783 names = '.'.join(names) 1wxL
784 if not names.startswith(self.name): 1wxL
785 return None 1x
786 if len(self.name) < len(names) and not names.startswith(self.name+'.'): 1wxL
787 return None 1w
788 if len(names) == 1: 788 ↛ 789line 788 didn't jump to line 789 because the condition on line 788 was never true1wxL
789 return self
790 for test in self.tests: 790 ↛ 793line 790 didn't jump to line 793 because the loop on line 790 didn't complete1wxL
791 if test.name == node_testname: 791 ↛ 790line 791 didn't jump to line 790 because the condition on line 791 was always true1wxL
792 return test 1wxL
793 return None
795 @property 1ab
796 def default_tags(self): 1ab
797 return DefaultTagsController(self, self.setting_table.default_tags) 29b#c$c%cYc}c~c*b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb2b3b4bBbEbtbxb.cQeReSeTeUeybW @ hdVe
799 def is_modifiable(self): 1ab
800 return not self.exists() or not self.is_readonly() 2a bc2c3cccdc?b4cecfcgchc5c=c[b^b_b`b{b6cacmcncocic?cjc|bkc:c9b;cndodpd#c$c%c_eqdrdsdtdudvdwdxdydzdAdBdCdDd`eEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd0d1d2d3d{e4d5d6d7d8d9d!d#d$d%d'd|e(d)d*d+d,d-d.d/d:d}e;d=d?d@d[d]d~e^d_d`d{d|d}d~daebeafce'c(c7c8cP Q R S T )b}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJcdeeefegeheiejekelemeneoepeqereseteuevewexeyezeAeBeCeDebfcfdfefEeFeGeHeIeJeKeffgfhfifLeMeNcOcPcQcRcScTcUcVc)cWcXc*cfbgbhbN (b;b9cMc!cFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbBbEb.c@c[c]c^c_c`cW @
802 def create_test(self, name): 1ab
803 return self.tests.new(name) 2a w x L cd)c*c! # $ % ' ( {c
805 def validate_test_name(self, name): 1ab
806 return self.tests.validate_name(name)
808 def remove_child(self, controller): 1ab
809 if controller is self:
810 self.remove()
812 def remove(self): 1ab
813 self._project.remove_datafile(self) 1p?
814 RideDataFileRemoved(path=self.filename, datafile=self).publish() 1p?
816 def reload(self): 1ab
817 self.__init__(TestCaseFile(parent=self.data.parent, source=self.filename, tasks=self.tasks, 1`
818 language=self._language).populate(),
819 project=self._project,
820 parent=self.parent)
822 def get_template(self): 1ab
823 return self.data.setting_table.test_template 2bc2c3cccdc?b4cecfcgchc5c=c[b^b_b`b{b6cic?cjc|bkc/b#b(b;bf c i
825 def exclude(self): 1ab
826 if self._project.is_datafile_dirty(self):
827 raise DirtyRobotDataException()
828 self._project.internal_settings.excludes.update_excludes([self.source])
829 if self.parent and self.parent.children:
830 index = self.parent.children.index(self)
831 result = ExcludedFileController(self.data, self._project, self.parent)
832 if self.parent and self.parent.children:
833 self.parent.children[index] = result
834 return result
836 def retrieve_test_controllers(self): 1ab
837 controllers = []
838 for test_ctrl in iter(self.tests):
839 controllers.append(test_ctrl)
840 return controllers
843class ResourceFileControllerFactory(object): 1ab
845 def __init__(self, namespace, project): 1ab
846 self._resources = [] 2a @eV s t v G u q r h g d m o n 7 8 9 p e z ? N Z [e]e^e
847 self._namespace = namespace 2a @eV s t v G u q r h g d m o n 7 8 9 p e z ? N Z [e]e^e
848 self._project = project 2a @eV s t v G u q r h g d m o n 7 8 9 p e z ? N Z [e]e^e
849 self._all_resource_imports_resolved = False 2a @eV s t v G u q r h g d m o n 7 8 9 p e z ? N Z [e]e^e
851 @property 1ab
852 def resources(self): 1ab
853 return self._resources 2a zbfdE V F D s t v G u q r y Zb}bpcqcrcsctcuc/bvcwcxcyczcAcBcCcDcEcFcGcHcIcJch g d m o n Zc0cKcO p e z *b!b$b+b,b-b:b.b%b'bAbVbI DbFbGbHbIbJbubvbwbKbLbMbNbObCbPbQbRbSbTbUbYb5b6b7b8bXb0b1bWb~b2b3b4bBbEbtbxbf c i k l j ybNe@bib
855 def find(self, data): 1ab
856 return self._find_with_source(data.source) 2a zbE F D h g d m o n Zc0cO z I f c i k l j ib
858 def _find_with_source(self, source): 1ab
859 for other in self.resources: 2a zbE F D h g d m o n Zc0cO z I f c i k l j ib
860 if other.filename == source: 2a zbD h g d m o n Zc0cO I f c i k l j ib
861 return other 2a zbD h g d m o n Zc0cO I f c k l j ib
862 return None 1aEFDzfciklj
864 def find_with_import(self, import_): 1ab
865 resource_model = self._namespace.find_resource_with_import(import_) 2a zbh g d m o n Zcuf0cO I f c i k l j ib/c
866 if not resource_model: 2a zbh g d m o n Zcuf0cO I f c i k l j ib/c
867 return None 2a h g o ufi /c
868 res = self.find(resource_model) 2a zbh g d m o n Zc0cO I f c k l j ib
869 if not res: 869 ↛ 870line 869 didn't jump to line 870 because the condition on line 869 was never true2a zbh g d m o n Zc0cO I f c k l j ib
870 res = self.create(resource_model)
871 self._project.insert_into_suite_structure(res)
872 assert(res is not None) 2a zbh g d m o n Zc0cO I f c k l j ib
873 return res 2a zbh g d m o n Zc0cO I f c k l j ib
875 def create(self, data, parent=None): 1ab
876 rfc = ResourceFileController(data, self._project, parent, self) 1aEFDhgdmonpezfciklj
877 self.resources.append(rfc) 1aEFDhgdmonpezfciklj
878 self.set_all_resource_imports_unresolved() 1aEFDhgdmonpezfciklj
879 return rfc 1aEFDhgdmonpezfciklj
881 def set_all_resource_imports_resolved(self): 1ab
882 self._all_resource_imports_resolved = True 2a zbh g d m o n O I c 9evfib
884 def set_all_resource_imports_unresolved(self): 1ab
885 self._all_resource_imports_resolved = False 2a E F D h g d m o n KcO p e z f c i k l j 9evf
887 def is_all_resource_file_imports_resolved(self): 1ab
888 return self._all_resource_imports_resolved 2a zbh g d m o n O I c 9evf@biblc
890 def remove(self, controller): 1ab
891 self._resources.remove(controller) 2KcO z 9e
892 self.set_all_resource_imports_unresolved() 2KcO z 9e
895class ResourceFileController(_FileSystemElement, _DataController): 1ab
897 def __init__(self, data, project=None, parent=None, resource_file_controller_factory=None): 1ab
898 if resource_file_controller_factory: 1aEFDstvGuqrhgdmon789pezZfciklj
899 self._resource_file_controller_factory = resource_file_controller_factory 1aEFDhgdmonpezfciklj
900 else:
901 self._resource_file_controller_factory = ResourceFileControllerFactory(self.namespace, project) 1astvGuqr789Z
902 self._known_imports = set() 1aEFDstvGuqrhgdmon789pezZfciklj
903 _FileSystemElement.__init__(self, data.source if data else None, data.directory) 1aEFDstvGuqrhgdmon789pezZfciklj
904 _DataController.__init__(self, data, project, 1aEFDstvGuqrhgdmon789pezZfciklj
905 parent or self._find_parent_for(project, data.source))
906 if self.parent and self not in self.parent.children: 1aEFDstvGuqrhgdmon789pezZfciklj
907 self.parent.add_child(self) 1aeZfciklj
908 self._unresolve_all_if_none_existing() 1aEFDstvGuqrhgdmon789pezZfciklj
910 def _unresolve_all_if_none_existing(self): 1ab
911 if not self.exists() and self._resource_file_controller_factory: 1aEFDstvGuqrhgdmon789pezZfciklj
912 self._resource_file_controller_factory.set_all_resource_imports_unresolved() 1aEDhgdmonfciklj
913 # Some import may have referred to this none existing resource
915 def _find_parent_for(self, project, source): 1ab
916 if not project: 1aEFDstvGuqrhgdmon789pezfciklj
917 return None 1astvGuqr789
918 ddir = os.path.dirname(source) 1aEFDhgdmonpezfciklj
919 for ctrl in project.datafiles: 1aEFDhgdmonpezfciklj
920 if ctrl.is_directory_suite() and self._to_os_style(ctrl.directory) == ddir: 1ahgdmonefciklj
921 return ctrl 1aefciklj
922 return None 1aEFDhgdmonpez
924 @staticmethod 1ab
925 def _to_os_style(path): 1ab
926 return path.replace('/', os.sep) 1aefciklj
928 @property 1ab
929 def display_name(self): 1ab
930 _, tail = os.path.split(self.data.source) 2a TfybUfVfWfXf@bib
931 return tail 2a TfybUfVfWfXf@bib
933 @property 1ab
934 def language(self): 1ab
935 return self._language
937 def is_modifiable(self): 1ab
938 return not self.exists() or not self.is_readonly() 2a Zb=bh g d 7 8 9 KcO #bLctbf c i k l j iblc
940 def set_format(self, formatt): 1ab
941 self._modify_file_name(lambda: _DataController.set_format(self, formatt), 1amon
942 lambda imp: imp.change_format(formatt))
944 def set_basename(self, basename): 1ab
945 self._modify_file_name(lambda: _DataController.set_basename(self, basename), 1h
946 lambda imp: imp.unresolve())
948 def set_basename_and_modify_imports(self, basename): 1ab
949 old = self.filename 1gd
950 self._modify_file_name(lambda: _DataController.set_basename(self, basename), 1gd
951 lambda imp: imp.change_name(os.path.basename(old),
952 os.path.basename(self.filename)))
954 def remove_static_imports_to_this(self): 1ab
955 name = os.path.basename(self.filename) 1O
956 # have to resolve imports before deleting
957 # see: http://code.google.com/p/robotframework-ride/issues/detail?id=1119
958 imports = [import_ for import_ in self.get_where_used()] 1O
959 for resource_import in imports: 1O
960 if resource_import.name.endswith(name): 960 ↛ 959line 960 didn't jump to line 959 because the condition on line 960 was always true1O
961 resource_import.remove() 1O
963 def _modify_file_name(self, modification, notification): 1ab
964 old = self.filename 1ahgdmon
965 modification() 1ahgdmon
966 resource_imports = [resource_import_ for resource_import_ in self.get_where_used()] 1ahgdmon
967 for resource_import in resource_imports: 1ahgdmon
968 notification(resource_import) 1hgdmon
969 self.namespace.resource_filename_changed(old, self.filename) 1ahgdmon
971 def internal_settings(self): 1ab
972 return [DocumentationController(self, self.data.setting_table.doc)] 2AbVbI DbXb0b1bWb~b2b3b4bBbEbtbyb
974 def validate_name(self, name): 1ab
975 for uk in self.data.keyword_table.keywords:
976 if uk != name and utils.eq(uk.name, name):
977 return 'User keyword with this name already exists.'
978 return None
980 def reload(self): 1ab
981 self.__init__(ResourceFile(source=self.filename).populate(), self._project, 1Z
982 parent=self.parent)
984 def remove(self): 1ab
985 self._project.remove_resource(self) 2KcO z
986 RideDataFileRemoved(path=self.filename, datafile=self).publish() 2KcO z
988 def remove_known_import(self, _import): 1ab
989 self._known_imports.remove(_import) 1hgdmonOcj
991 def add_known_import(self, _import): 1ab
992 self._known_imports.add(_import) 2a zbh g d m o n Zc0cO I f c k l j ib
994 def notify_opened(self): 1ab
995 RideOpenResource(path=self.filename, datafile=self).publish() 1aEFDzfciklj
996 for _import in [imp for imp in self.imports if imp.is_resource]: 996 ↛ 997line 996 didn't jump to line 997 because the loop on line 996 never started1aEFDzfciklj
997 _import.import_loaded_or_modified()
999 def is_used(self): 1ab
1000 if self._known_imports: 2a zbfdc @b
1001 return True 2a fdc
1002 if not self._resource_file_controller_factory: 1002 ↛ 1003line 1002 didn't jump to line 1003 because the condition on line 1002 was never true2a zbc @b
1003 return False
1004 if self._resource_file_controller_factory.is_all_resource_file_imports_resolved(): 2a zbc @b
1005 return False 2a c @b
1006 return any(self._resolve_known_imports()) 2a zbc
1008 def get_where_used(self): 1ab
1009 if self._resource_file_controller_factory.is_all_resource_file_imports_resolved(): 2a h g d m o n O I iblc
1010 source = self._known_imports 2I lc
1011 else:
1012 source = self._resolve_known_imports() 2a h g d m o n O I ib
1014 for usage in source: 2a h g d m o n O I iblc
1015 yield usage 2h g d m o n O I iblc
1017 def _resolve_known_imports(self): 1ab
1018 for imp in self._all_imports(): 2a zbh g d m o n O I c ib
1019 if imp.get_imported_controller() is self: 2a zbh g d m o n O I c ib
1020 yield imp 2a h g d m o n O I ib
1021 self._resource_file_controller_factory.set_all_resource_imports_resolved() 2a zbh g d m o n O I c ib
1023 def _all_imports(self): 1ab
1024 for df in self.datafiles: 2a zbh g d m o n O I c ib
1025 for imp in df.imports: 2a zbh g d m o n O I c ib
1026 yield imp 2a zbh g d m o n O I c ib
1028 def remove_child(self, controller): 1ab
1029 """ Does not have children """
1030 pass
1032 def exclude(self): 1ab
1033 if self._project.is_datafile_dirty(self):
1034 raise DirtyRobotDataException()
1035 self._project.internal_settings.excludes.update_excludes([self.source])
1036 if self.parent and self.parent.children:
1037 index = self.parent.children.index(self)
1038 result = ExcludedFileController(self.data, self._project, self.parent)
1039 if self.parent and self.parent.children:
1040 self.parent.children[index] = result
1041 return result
1044class ExcludedDirectoryController(_FileSystemElement, ControllerWithParent, WithNamespace): 1ab
1046 def __init__(self, data, project, parent): 1ab
1047 self.data = data 1yH
1048 self._project = project 1yH
1049 if self._project: 1049 ↛ 1053line 1049 didn't jump to line 1053 because the condition on line 1049 was always true1yH
1050 self._set_namespace_from(self._project) 1yH
1051 self._resource_file_controller_factory = self._project.resource_file_controller_factory 1yH
1052 else:
1053 self._resource_file_controller_factory = None
1054 self._parent = parent 1yH
1055 self.children = [] 1yH
1056 self.keywords = [] 1yH
1057 self.variables = tuple() 1yH
1058 self.tests = tuple() 1yH
1059 self.imports = tuple() 1yH
1060 _FileSystemElement.__init__(self, '', data.directory) 1yH
1062 @property 1ab
1063 def settings(self): 1ab
1064 return self.internal_settings()
1066 def internal_settings(self): 1ab
1067 ss = self.data.setting_table
1068 return [DocumentationController(self, ss.doc),
1069 FixtureController(self, ss.suite_setup),
1070 FixtureController(self, ss.suite_teardown),
1071 FixtureController(self, ss.test_setup),
1072 FixtureController(self, ss.test_teardown),
1073 self.force_tags, self.test_tags]
1075 @property 1ab
1076 def setting_table(self): 1ab
1077 return self.data.setting_table
1079 @property 1ab
1080 def force_tags(self): 1ab
1081 return ForceTagsController(self, self.setting_table.force_tags)
1083 @property 1ab
1084 def test_tags(self): 1ab
1085 return TestTagsController(self, self.setting_table.test_tags)
1087 @property 1ab
1088 def dirty(self): 1ab
1089 return False
1091 def keyword_info(self, datafile, keyword_name): 1ab
1092 _ = datafile
1093 return WithNamespace.keyword_info(self, self.data, keyword_name)
1095 def is_excluded(self): 1ab
1096 return True 1H
1098 def remove_from_excludes(self): 1ab
1099 self._project.internal_settings.excludes.remove_path(self.source) 1y
1100 index = self.parent.children.index(self) 1y
1101 td = test_data(self.data.source, self.parent.data, self._project.internal_settings) 1y
1102 # We can reach here not from Directory, so proper test must be done
1103 if isinstance(td, TestDataDirectory): 1103 ↛ 1105line 1103 didn't jump to line 1105 because the condition on line 1103 was always true1y
1104 result = TestDataDirectoryController(td, self._project, self.parent) 1y
1105 elif isinstance(td, ResourceFile):
1106 result = ResourceFileController(td, self._project, self.parent)
1107 else:
1108 result = TestCaseFileController(td, self._project, self.parent)
1109 self.parent.children[index] = result 1y
1110 return result 1y
1112 def iter_datafiles(self): 1ab
1113 return [self] 1y
1115 @property 1ab
1116 def name(self): 1ab
1117 return self.data.name 1y
1119 @staticmethod 1ab
1120 def is_directory_suite(): 1ab
1121 return True
1123 def add_child(self, child): 1ab
1124 self.children.append(child)
1127class ExcludedFileController(_FileSystemElement, _DataController): 1ab
1128 __test__ = False 1ab
1130 def __init__(self, data, project, parent): 1ab
1131 self.data = data
1132 self._project = project
1133 if self._project:
1134 self._set_namespace_from(self._project)
1135 self._resource_file_controller_factory = self._project.resource_file_controller_factory
1136 else:
1137 self._resource_file_controller_factory = None
1138 self._parent = parent
1139 self.children = []
1140 self._variables_table_controller = None
1141 self._testcase_table_controller = None
1142 self._keywords_table_controller = None
1143 _FileSystemElement.__init__(self, data.source if data else None, data.directory)
1144 # _DataController.__init__(self, data, project, parent)
1146 def internal_settings(self): 1ab
1147 ss = self.setting_table
1148 sett = _DataController.internal_settings(self)
1149 sett.insert(-1, TemplateController(self, ss.test_template))
1150 sett.insert(-1, TimeoutController(self, ss.test_timeout))
1151 return sett + [self.default_tags, self.force_tags, self.test_tags] # OK doing some cheating here ;)
1153 @property 1ab
1154 def longname(self): 1ab
1155 if self.parent:
1156 return self.parent.longname + '.' + self.name
1157 return self.name
1159 @property 1ab
1160 def suites(self): 1ab
1161 return ()
1163 @property 1ab
1164 def tests(self): 1ab
1165 return ()
1167 @property 1ab
1168 def imports(self): 1ab
1169 return ()
1171 @property 1ab
1172 def datafile(self): 1ab
1173 return None
1175 def contains_tests(self): 1ab
1176 return False
1178 def find_controller_by_longname(self, longname, node_testname=None): 1ab
1179 return self.find_controller_by_names(longname.split("."), node_testname)
1181 def find_controller_by_names(self, names, node_testname=None): 1ab
1182 names = '.'.join(names)
1183 if not names.startswith(self.name):
1184 return None
1185 if len(self.name) < len(names) and not names.startswith(self.name + '.'):
1186 return None
1187 if len(names) == 1:
1188 return self
1189 for test in self.tests:
1190 if test.name == node_testname:
1191 return test
1192 return None
1194 @property 1ab
1195 def default_tags(self): 1ab
1196 return None # DefaultTagsController(self, self.setting_table.default_tags)
1198 def is_modifiable(self): 1ab
1199 return not self.exists() or not self.is_readonly()
1201 def create_test(self, name): 1ab
1202 return self.tests.new(name)
1204 def validate_test_name(self, name): 1ab
1205 return self.tests.validate_name(name)
1207 def remove_child(self, controller): 1ab
1208 if controller is self:
1209 self.remove()
1211 def remove(self): 1ab
1212 self._project.remove_datafile(self)
1213 RideDataFileRemoved(path=self.filename, datafile=self).publish()
1215 def reload(self): 1ab
1216 self.__init__(TestCaseFile(parent=self.data.parent, source=self.filename, language=self._language).populate(),
1217 project=self._project,
1218 parent=self._parent)
1220 def get_template(self): 1ab
1221 return self.data.setting_table.test_template
1223 @property 1ab
1224 def settings(self): 1ab
1225 return self.internal_settings()
1227 @property 1ab
1228 def setting_table(self): 1ab
1229 return self.data.setting_table
1231 @property 1ab
1232 def force_tags(self): # Yes, I know this is impossible, but is Exclude file, right? 1ab
1233 return None # ForceTagsController(self, self.setting_table.force_tags)
1235 @property 1ab
1236 def test_tags(self): # Yes, I know this is impossible, but is Exclude file, right? 1ab
1237 return None
1239 @property 1ab
1240 def dirty(self): 1ab
1241 return False
1243 def keyword_info(self, datafile, keyword_name): 1ab
1244 return NotImplemented
1245 # _ = datafile
1246 # return WithNamespace.keyword_info(self, self.data, keyword_name)
1248 def is_excluded(self): 1ab
1249 return True
1251 def remove_from_excludes(self): 1ab
1252 self._project.internal_settings.excludes.remove_path(self.source)
1253 if self._parent.children:
1254 index = self._parent.children.index(self)
1255 td = test_data(self.data.source, self._parent.data, self._project.internal_settings)
1256 # We can reach here not from Directory, so proper test must be done
1257 if isinstance(td, TestDataDirectory):
1258 result = TestDataDirectoryController(td, self._project, self._parent)
1259 elif isinstance(td, ResourceFile):
1260 result = ResourceFileController(td, self._project, self._parent)
1261 else:
1262 result = TestCaseFileController(td, self._project, self._parent)
1263 if self._parent.children:
1264 self._parent.children[index] = result
1265 return result
1267 def iter_datafiles(self): 1ab
1268 return []
1270 @property 1ab
1271 def name(self): 1ab
1272 return self.data.name
1274 def add_child(self, child): 1ab
1275 self.children.append(child)