Coverage for src/robotide/controller/stepcontrollers.py: 67%
621 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 re 1ac
18from .. import robotapi, utils 1ac
19from .basecontroller import _BaseController 1ac
20from .cellinfo import CellPosition, CellType, CellInfo, CellContent, ContentType, UPPERCASE_KWS 1ac
21from ..publish.messages import RideItemNameChanged 1ac
22from ..namespace.local_namespace import local_namespace 1ac
23from ..utils import variablematcher 1ac
25BDD_ENGLISH = 'given|when|then|and|but' 1ac
27def obtain_bdd_prefixes(language): 1ac
28 from robotide.lib.compat.parsing.language import Language
29 lang = Language.from_name(language[0] if isinstance(language, list) else language)
30 bdd_prefixes = [f"{x}|" for x in lang.bdd_prefixes]
31 bdd_prefixes = "".join(bdd_prefixes).strip('|')
32 return bdd_prefixes
35class StepController(_BaseController): 1ac
37 indent = None 1ac
39 def __init__(self, parent, step): 1ac
40 self.continuing_kw = None 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
41 self._init(parent, step) 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
42 if hasattr(self.parent, 'language'): 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
43 self._language = self.parent.language[0] if isinstance(self.parent.language, list) else self.parent.language 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
44 else:
45 self._language = 'en' 2Tc
46 if self._language and self._language.lower() not in ['en', 'english']: 46 ↛ 47line 46 didn't jump to line 47 because the condition on line 46 was never true2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
47 bdd_prefix = f"{obtain_bdd_prefixes(self._language)}|{BDD_ENGLISH}"
48 else:
49 bdd_prefix = BDD_ENGLISH 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
50 self._GIVEN_WHEN_THEN_MATCHER = re.compile(fr'^({bdd_prefix})\s*', re.IGNORECASE) 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
51 # print(f"DEBUG: stepcontrollers.py StepController INIT {self.parent.language}")
52 self.step_controller_step.args = self._change_last_empty_to_empty_var( 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
53 self.step_controller_step.args, self.step_controller_step.comment)
55 def _init(self, parent, step): 1ac
56 self.parent = parent 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
57 self.step_controller_step = step 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
58 self.indent = [] 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
59 index = 0 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
60 if isinstance(self.step_controller_step, list): 60 ↛ 61line 60 didn't jump to line 61 because the condition on line 60 was never true2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
61 while index < len(self.step_controller_step) and self.step_controller_step[index] == '':
62 self.indent.append('')
63 elif isinstance(self.step_controller_step, robotapi.Step): 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
64 cells = self.step_controller_step.as_list() 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
65 for index in range(0, len(cells)): 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
66 if cells[index] == '': 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H HcFcnczcBcMcNcOcPc
67 self.increase_indent() 2a B y h e m n o pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcFb0bwb1b2b!bb Ob%b'b(b3bcc/ K PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y zcBcMcNcOcPc
68 else:
69 self.step_controller_step.args = self.step_controller_step.comment = [] 2Tc
71 @property 1ac
72 def display_name(self): 1ac
73 return 'Step'
75 @property 1ac
76 def datafile_controller(self): 1ac
77 return self.parent.datafile_controller 2k i p y I h q e m J n o d g A x Tc
79 @staticmethod 1ac
80 def _change_last_empty_to_empty_var(args, comment): 1ac
81 if not args: # and not comment: 2a k i z j l r p B y v s w F h t u C D E q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H ]c^c_c`cHcFcnczcBcMcNcOcPc
82 return [] 2a i z j l r p B y v s w F h t u C D E q e m n o d g f A pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcScUcVcWcTc: ; = ocAcpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H `cFcnczcBcMcNcOcPc
83 if comment: 2a k i z j p B y v s w h t u q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb0bwb1b2bb Ob%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcSc: ; = ocpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H ]c^c_cHcFcnczcBcMcNcOcPc
84 return args 2a pbP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ gcmchcIcicCbHbDbEbbbTbUbVbIbzbsbtbhbubvb3 Cc#bDc$bEcJb- . 6bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* wb]cnc
85 return args[:-1] + ['${EMPTY}'] if args[-1] == '' else args 2a k i z j p B y v s w h t u q e m n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb0bwb1b2bb Ob%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S RcSc: ; = ocpc{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxcqckclc~bO G H ^c_cHcFcnczcBcMcNcOcPc
87 def get_keyword_info(self, kw): 1ac
88 if not kw: 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
89 return None 1kijlrpByIvswFhqeJf
90 return self.parent.get_keyword_info(kw) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
92 def __eq__(self, other): 1ac
93 if self is other: 2TcHcFc
94 return True 2Tc
95 if not isinstance(other, StepController): 95 ↛ 96line 95 didn't jump to line 96 because the condition on line 95 was never true2HcFc
96 return False
97 return self._steps_are_equal(self.step_controller_step, other.step_controller_step) 2HcFc
99 @staticmethod 1ac
100 def _steps_are_equal(fst, snd): 1ac
101 if fst is snd: 101 ↛ 102line 101 didn't jump to line 102 because the condition on line 101 was never true2HcFc
102 return True
103 if not snd: 103 ↛ 104line 103 didn't jump to line 104 because the condition on line 103 was never true2HcFc
104 return False
105 return (fst.assign == snd.assign and 2HcFc
106 fst.name == snd.name and
107 fst.args == snd.args)
109 def get_value(self, col): 1ac
110 values = self.as_list() 2a k i z j l r p B y I v s w F h t u C D E q e m J n o d g f A x pb)b*b+bRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWb3 #b$bJb- . 6b7bZb/b8b9bAbBbobKbZ 0 LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b5b-b+ PbQb4b: ; = T U V W X Y O G H
111 if len(values) <= col: 2a k i z j l r p B y I v s w F h t u C D E q e m J n o d g f A x pb)b*b+bRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWb3 #b$bJb- . 6b7bZb/b8b9bAbBbobKbZ 0 LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b5b-b+ PbQb4b: ; = T U V W X Y O G H
112 return '' 2a k i z j l r p B y I v s w F h t u C D E q e J d g f pb)bCbSbDbEbzb3 #b- . /bAbBbZ 0 * Fb5b+ PbQbT U V W X Y
113 return values[col] 2a k i z j l r p B y I v s w F h t u C D E q e m J n o d g f A x )b*b+bRbyb_ GbHbbbTbUbVbIbzbWb3 #b$bJb6b7bZb8b9bAbBbobKbZ 0 LbMbNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b5b-b+ PbQb4b: ; = O G H
115 def get_cell_info(self, col): 1ac
116 position = self._get_cell_position(col) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
117 content = self._get_content_with_type(col, position) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
118 if content.type == ContentType.COMMENTED: 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
119 return self._build_cell_info(content, CellPosition(CellType.OPTIONAL, None)) 1zjl
120 return self._build_cell_info(content, position) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
122 @property 1ac
123 def assignments(self): 1ac
124 return self.step_controller_step.assign 2r y I h t u C D E J d g f A x b G H zcBcMcNcOcPc
126 def is_assigning(self, value): 1ac
127 for assignment in self.assignments: 2r y I h t u C D E J d g f A x b G H zcBc
128 if assignment.replace('=', '').strip() == value.replace('=', '').strip(): 2y I h d g f A x b zcBc
129 return True 2h g f x zc
130 if value.strip().endswith('='): 130 ↛ 131line 130 didn't jump to line 131 because the condition on line 130 was never true2r y I h t u C D E J d g f A x b G H zcBc
131 return True
132 return False 2r y I h t u C D E J d g f A x b G H zcBc
134 def _build_cell_info(self, content, position): 1ac
135 return CellInfo(content, position) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
137 def _get_cell_position(self, column): 1ac
138 col = column 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
139 if self.parent.has_template(): 139 ↛ 140line 139 didn't jump to line 140 because the condition on line 139 was never true1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
140 return CellPosition(CellType.UNKNOWN, None)
141 column -= len(self.step_controller_step.assign) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
142 value_at_col = self.get_value(col) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
143 info = self.get_keyword_info(value_at_col) # Getting info for the keyword cell 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
144 keyword_col = col if col >= self._keyword_column else self._keyword_column 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
145 if info: 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
146 casesensitive = (value_at_col.upper() != value_at_col and value_at_col.upper() in UPPERCASE_KWS) 1kizjlrpyIvswFtuCDEqemJnodfAxb:;=OGH
147 if casesensitive: 147 ↛ 148line 147 didn't jump to line 148 because the condition on line 147 was never true1kizjlrpyIvswFtuCDEqemJnodfAxb:;=OGH
148 return CellPosition(CellType.UNKNOWN, ContentType.STRING)
149 return CellPosition(CellType.KEYWORD, None) 1kizjlrpyIvswFtuCDEqemJnodfAxb:;=OGH
150 else:
151 while not info and keyword_col > 0 and keyword_col > self._keyword_column: 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
152 keyword_col -= 1 1kizjlrpByIvswFhtuqemJnodgfAxbOGH
153 value_at_col = self.get_value(keyword_col) 1kizjlrpByIvswFhtuqemJnodgfAxbOGH
154 info = self.get_keyword_info(value_at_col) # Getting info for the previous cell 1kizjlrpByIvswFhtuqemJnodgfAxbOGH
155 casesensitive = (value_at_col.upper() != value_at_col and value_at_col.upper() in UPPERCASE_KWS) 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
156 if casesensitive: 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
157 return CellPosition(CellType.UNKNOWN, None) 1e
158 if info: 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
159 args = info.arguments 1kizjlrpByIvswFhtuqemJnodgfAxbOGH
160 else:
161 args = [] 1rtuCDEJgfGH
162 value_at_col = self.get_value(col) 1rtuCDEJgfGH
163 if self.keyword == '...' and self._index() > 0: # Any block starting with ... is in error 163 ↛ 164line 163 didn't jump to line 164 because the condition on line 163 was never true1rtuCDEJgfGH
164 if value_at_col == '...':
165 drow = 1
166 self.continuing_kw = self.parent.step(self._index()-drow).keyword
167 while self.continuing_kw == '...' and self._index()-drow > 0:
168 drow += 1
169 self.continuing_kw = self.parent.step(self._index() - drow).keyword
170 info = self.get_keyword_info(self.continuing_kw) # Getting info for the previous step kw
171 if info:
172 args = info.arguments
173 args_amount = len(args) 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
174 if (column > keyword_col and (self.get_value(keyword_col) == "FOR" or self.get_value(keyword_col) == "VAR") 174 ↛ 178line 174 didn't jump to line 178 because the condition on line 174 was never true1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
175 and self.is_assigning(value_at_col)):
176 # print(f"DEBUG: stepcontrollers.py StepController _get_cell_position VAR or FOR assign "
177 # f"value_at_col={value_at_col}")
178 return CellPosition(CellType.ASSIGN, None)
179 if column <= keyword_col and self.is_assigning(value_at_col): 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
180 return CellPosition(CellType.ASSIGN, None) 1gf
181 if col < keyword_col: 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
182 return CellPosition(CellType.UNKNOWN, None) 1J
183 if not info and not self.is_assigning(value_at_col)\ 1kizjlrpByIvswFhtuCDEqemJnodgfAxbOGH
184 and not self.is_assigning(self.get_value(self._keyword_column)) and col >= keyword_col:
185 return CellPosition(CellType.UNKNOWN, None) 1rtuCDEGH
186 if args_amount == 0: 1kizjlrpByIvswFhtuqemJnodgfAxbOGH
187 return CellPosition(CellType.MUST_BE_EMPTY, None) 1FJO
188 mandatory_args_amount = self._number_of_mandatory_arguments(args, args_amount) 1kizjlrpByIvswhtuqemJnodgfAxbGH
189 """ 1kizjlrpByIvswhtuqemJnodgfAxbGH
190 # DEBUG: This causes @ or & cells unknown, disable for now
191 if self._has_list_or_dict_var_value_before(col - 1):
192 return CellPosition(CellType.UNKNOWN, None)
193 """
194 if col <= keyword_col + mandatory_args_amount: 1kizjlrpByIvswhtuqemJnodgfAxbGH
195 return CellPosition(CellType.MANDATORY, args[col-keyword_col - 1]) 1kizrpByIvtuqmJnoxGH
196 if col >= keyword_col + args_amount - mandatory_args_amount and self._last_argument_is_varargs(args): 1kizjlyIvswhedgfAxb
197 # print(f"DEBUG: stepcontrollers _get_cell_position last is vararg={args[-1]}")
198 return CellPosition(CellType.OPTIONAL, args[-1]) 1jlyIswedgfAxb
199 if keyword_col + mandatory_args_amount < col <= keyword_col + args_amount: 1kizvshdAx
200 return CellPosition(CellType.OPTIONAL, args[col-keyword_col-1]) 1kizvshdAx
201 return CellPosition(CellType.MUST_BE_EMPTY, None) 1kiv
203 def _number_of_mandatory_arguments(self, args, args_amount): 1ac
204 defaults = [arg for arg in args if '=' in arg] 1kizjlrpByIvswhtuqemJnodgfAxbGH
205 n = args_amount - len(defaults) 1kizjlrpByIvswhtuqemJnodgfAxbGH
206 # detect if @{}, named only indicator is present and decrease counter
207 for arg in args: 1kizjlrpByIvswhtuqemJnodgfAxbGH
208 if arg == '@{}' or arg.startswith('*'): 1kizjlrpByIvswhtuqemJnodgfAxbGH
209 n -= 1 1jlyIswedgfAxb
210 break 1jlyIswedgfAxb
211 if self._last_argument_is_varargs(args): 1kizjlrpByIvswhtuqemJnodgfAxbGH
212 n -= 1 1jlyIswedgfAxb
213 return n if n >= 0 else 0 1kizjlrpByIvswhtuqemJnodgfAxbGH
215 @staticmethod 1ac
216 def _last_argument_is_varargs(args): 1ac
217 return args[-1].startswith('*') or args[-1].startswith('&{') 1kizjlrpByIvswhtuqemJnodgfAxbGH
219 """ 1ac
220 # DEBUG: This is not used anywhere
221 def _has_list_or_dict_var_value_before(self, arg_index):
222 if self.args:
223 for idx, value in enumerate(self.args):
224 if idx > arg_index:
225 return False
226 if variablematcher.is_list_variable(value) and \
227 not variablematcher.is_list_variable_subitem(value):
228 return True
229 if robotapi.is_dict_var(value) and \
230 not variablematcher.is_dict_var_access(value):
231 return True
232 return False
233 """
235 def _get_content_with_type(self, col, position): 1ac
236 value = self.get_value(col) 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
237 if self._is_commented(col): 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
238 return CellContent(ContentType.COMMENTED, value) 1zjl
239 last_none_empty = self._get_last_none_empty_col_idx() 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
240 if isinstance(last_none_empty, int) and last_none_empty < col: 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
241 return CellContent(ContentType.EMPTY, value) 1kirpyIvswFqeJf
242 if variablematcher.is_variable(value): 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
243 if self._is_unknow_variable(value, position): 1kipyIhqemJnodgfAx
244 return CellContent(ContentType.UNKNOWN_VARIABLE, value) 1kiyIemJnodgAx
245 return CellContent(ContentType.VARIABLE, value) 1phqgfx
246 if self.is_user_keyword(value): 1kizjlrpByIvswFtuCDEqemJnodfAxb:;=OGH
247 return CellContent( 1kizrpvswFqAx:;=OGH
248 ContentType.USER_KEYWORD, value,
249 self.get_keyword_info(value).source)
250 if self.is_library_keyword(value): 1jlrByIvswtuCDEemJnodfAxbOGH
251 return CellContent( 1jlyItuCDEemJnodfAxb
252 ContentType.LIBRARY_KEYWORD, value,
253 self.get_keyword_info(value).source)
254 if value == 'END': # DEBUG Don't consider start column (col == 0 and) 254 ↛ 255line 254 didn't jump to line 255 because the condition on line 254 was never true1rByIvswtuCDEeJdfAxbOGH
255 return CellContent(ContentType.END, value)
256 return CellContent(ContentType.STRING, value) 1rByIvswtuCDEeJdfAxbOGH
258 def _is_unknow_variable(self, value, position): 1ac
259 if position.type == CellType.ASSIGN: 1kipyIhqemJnodgfAx
260 return False 1gf
261 try: 1kipyIhqemJnodgAx
262 is_known = self._get_local_namespace().has_name(value) 1kipyIhqemJnodgAx
263 except AttributeError:
264 return False
265 if is_known: 1kipyIhqemJnodgAx
266 return False 1x
267 inner_value = value[2:-1] 1kipyIhqemJnodgAx
268 modified = re.split(r'\W', inner_value, 1)[0] 1kipyIhqemJnodgAx
269 return not self._get_local_namespace().has_name('%s{%s}' % (value[0], modified)) 1kipyIhqemJnodgAx
271 def _get_local_namespace(self): 1ac
272 index = self.parent.index_of_step(self.step_controller_step) 1kipyIhqemJnodgAx
273 return local_namespace( 1kipyIhqemJnodgAx
274 self.parent, self.datafile_controller.namespace, index)
276 def _get_last_none_empty_col_idx(self): 1ac
277 values = self.as_list() 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
278 for i in reversed(range(len(values))): 278 ↛ 281line 278 didn't jump to line 281 because the loop on line 278 didn't complete1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
279 if values[i].strip() != '': 279 ↛ 278line 279 didn't jump to line 278 because the condition on line 279 was always true1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
280 return i 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
281 return None
283 def is_modifiable(self): 1ac
284 return self.datafile_controller.is_modifiable() 2Tc
286 def is_user_keyword(self, value): 1ac
287 return self.parent.is_user_keyword(value) 1kizjlrpByIvswFtuCDEqemJnodfAxb:;=OGH
289 def is_library_keyword(self, value): 1ac
290 return self.parent.is_library_keyword(value) 1jlrByIvswtuCDEemJnodfAxbOGH
292 def as_list(self): 1ac
293 # print(f"\nDEBUG: Stepcontrollers enter as_list")
294 return self.step_controller_step.as_list() 2a k i z j l r p B y I v s w F h t u C D E q e m J n o d g f A x pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb{c- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcQcNb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb|c}c~cad( R 7 8 M N 9 bdcdddedS RcScUcVc: ; = pcYcZc0c1cT U V .bW X Y O G H HcfdFcgd
296 def contains_variable(self, name): 1ac
297 return any(variablematcher.value_contains_variable(item, name) 2pcYcZc0c1c
298 for item in self.as_list())
300 def contains_variable_assignment(self, name): 1ac
301 return any(variablematcher.value_contains_variable(item, "%s=" % name) 2pcYcZc0c1c
302 for item in self.as_list())
304 def contains_keyword(self, name): 1ac
305 for item in [self.keyword or ''] + self.args: 2ocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b,c-c.c/c:c;c=c?c@c[cnc
306 matching = self._kw_name_match(item, name) 2ocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b,c-c.c/c:c;c=c?c@c[cnc
307 if matching is not None: 2ocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b,c-c.c/c:c;c=c?c@c[cnc
308 return matching 2oc2c3c+c4c{bT U V @b|b.bW }bX Y [b]b^bqc5c6cXckclc~b,c-c.c/c:c;c=c@c[cnc
309 return False 2ocAc7c2c3c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b?cnc
310 """
311 return any(self._kw_name_match(item, name)
312 for item in [self.keyword or ''] + self.args)
313 """
315 def _kw_name_match(self, item, expected): 1ac
316 if isinstance(expected, str): 2ocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b,c-c.c/c:c;c=c?c@c[cnc
317 return utils.eq(item, expected) or (self._GIVEN_WHEN_THEN_MATCHER.match(item) and 2ocAc7c2c3c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~b,c-c.c/c:c;c=c?c@c[cnc
318 utils.eq(self._GIVEN_WHEN_THEN_MATCHER.sub('', item), expected))
319 matcher = expected.match(item) 2ocAc7c2c3c+c4c8c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~bnc
320 # if matcher:
321 # old_prefix = matcher.group(1)
322 # print(f"DEBUG: stepcontrollers.py StepController kw_name_match: RE expected={expected}"
323 # f" matcher={matcher} old_prefix={old_prefix}")
324 return matcher 2ocAc7c2c3c+c4c8c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~bnc
326 def replace_keyword(self, new_name, old_name): 1ac
327 # DEBUG: Create setters for Step.name and Step.args
328 new_match = self._kw_name_match(self.keyword or '', old_name) 2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
329 if new_match: 2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
330 # print(f"DEBUG: stepcontrollers.py StepController replace_keyword: ACTUAL CHANGE old_name={old_name}"
331 # f" new_name={new_name} new_match={new_match}")
332 self.step_controller_step.name = self.step_controller_step.cells[self.step_controller_step.inner_kw_pos] = \ 2{bT U V @b|b.bW }bX Y [b]b^b~b
333 self._kw_name_replace(self.keyword, new_name, old_name)
334 for index, value in enumerate(self.args): 2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
335 if self._kw_name_match(value, old_name): 2@b.b[b]b^b
336 self.step_controller_step.args[index] = self.step_controller_step.cells[ 2.b
337 self.step_controller_step.inner_kw_pos + 1 + index] = \
338 self._kw_name_replace(value, new_name, old_name)
340 def _kw_name_replace(self, old_value, new_match, old_match): 1ac
341 # Here we should have a match for keywords prefixed with resource name
342 # print(f"DEBUG: stepcontrollers.py StepController _kw_name_replace: ENTER old_value={old_value}"
343 # f" old_match={old_match} new_match={new_match}")
344 old_prefix_matcher = self._GIVEN_WHEN_THEN_MATCHER.match(old_value) 2{bT U V @b|b.bW }bX Y [b]b^b~b
345 if not old_prefix_matcher: 2{bT U V @b|b.bW }bX Y [b]b^b~b
346 return new_match 2{b@b|b.b}b[b]b^b~b
347 old_prefix = old_prefix_matcher.group(0) 1TUVWXY
348 old_match_matcher = self._GIVEN_WHEN_THEN_MATCHER.match(old_match) 1TUVWXY
349 if old_match_matcher and old_match_matcher.group(0) == old_prefix: 1TUVWXY
350 return new_match 1X
351 return old_prefix + new_match 1TUVWY
353 @property 1ac
354 def datafile(self): 1ac
355 return self.parent.datafile 2Xcnc
357 @property 1ac
358 def keyword(self): 1ac
359 return self.step_controller_step.name 2k i z j l r p B y I v s w F h t u C D E q e m J n o d g f A x RbHbEbIbKbLbMbb Wc: ; = ocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~bO G H nc
361 @property 1ac
362 def assign(self): 1ac
363 return self.step_controller_step.assign
365 @property 1ac
366 def args(self): 1ac
367 return self.step_controller_step.args 2CbDbocAc7c2c3c+c4c8cpcYcZc0c1c{bT U V @brcsctcucvc|b.bW }bX Y [b]b^bwcxc9c!c#c$cqc5c6cXc%c'c(c)ckclc*c~bnc
369 @property 1ac
370 def vars(self): 1ac
371 return self.step_controller_step.vars
373 def change(self, col, new_value): 1ac
374 cells = self.as_list() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
375 if col >= len(cells): 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
376 cells = cells + ['' for _ in range(col - len(cells) + 1)] 2a i z j l r p B v s w F h t u C D E q d g f pbCbSbDbEbzb3 - . AbBbZ 0 * Fb5b+ PbQbT U V W X Y
377 cells[col] = new_value 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
378 comment = self._get_comment(cells) 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
379 if comment: 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
380 cells.pop() 2z yb_ GbWbhb! Fb+
381 self.recreate(cells, comment) 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbyb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . AbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
383 def insert_value_before(self, col, new_value): 1ac
384 self.shift_right(col) 2j l bbsbtbhbubvb$ Z 0 ! % +
385 self.change(col, new_value) 2j l bbsbtbhbubvb$ Z 0 ! % +
387 def comment(self): 1ac
388 col = self._first_non_empty_cell() # .step_controller_step.inner_kw_pos 2j l sbtbhbubvb$ Z 0 ! %
389 self.insert_value_before(col, 'Comment') 2j l sbtbhbubvb$ Z 0 ! %
391 def sharp_comment(self): 1ac
392 col = self._first_non_empty_cell() 2yb_
393 self.insert_sharp_comment(col) 2yb_
395 def insert_sharp_comment(self, col): 1ac
396 cell_value = self.get_value(col) 2yb_
397 new_value = "# " + cell_value 2yb_
398 self.change(col, new_value) 2yb_
400 def sharp_uncomment(self): 1ac
401 col = self._first_non_empty_cell() 1_
402 self.remove_sharp_comment(col) 1_
404 def remove_sharp_comment(self, col): 1ac
405 cell_value = self.get_value(col) 1_
406 if cell_value.startswith('#'): 406 ↛ 409line 406 didn't jump to line 409 because the condition on line 406 was always true1_
407 new_value = cell_value.lstrip('#').lstrip(' ').replace('\\ ', ' ') 1_
408 else:
409 return
410 self.change(col, new_value) 1_
412 def _is_commented(self, col): 1ac
413 if self._has_comment_keyword(): 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
414 return col > self._keyword_column 1jl
415 for i in range(min(col + 1, len(self.as_list()))): 1kizrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
416 if self.get_value(i).startswith('#'): 1kizrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
417 return True 1z
418 return False 1kizrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
420 def _first_non_empty_cell(self): 1ac
421 index = self.step_controller_step.first_non_empty_cell() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) _b`b? L @ Q 2 qbrb, yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
422 return index 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) _b`b? L @ Q 2 qbrb, yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3bcc/ K 5b-b+ PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
424 @property 1ac
425 def _keyword_column(self): 1ac
426 return self.step_controller_step.inner_kw_pos # ._first_non_empty_cell() 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
428 def recalculate_keyword_column(self): 1ac
429 index = self._first_non_empty_cell() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
430 cells = self.as_list() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
431 if 0 < len(cells) == index: 431 ↛ 432line 431 didn't jump to line 432 because the condition on line 431 was never true2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
432 self.step_controller_step.inner_kw_pos = index - 1
433 return
434 if index < len(cells) and cells[index] == '': 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
435 return 23 obOb
436 while index < len(cells) and (len(cells[index]) > 0 and cells[index][0] in ['$', '@', '&', '%']): 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
437 index += 1 2h g f pb*b+bGb3 $bJbmbnbobZ 0 ~ 6 R M N S
438 self.step_controller_step.inner_kw_pos = index 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
440 def _has_comment_keyword(self): 1ac
441 if self.keyword is None: 441 ↛ 442line 441 didn't jump to line 442 because the condition on line 441 was never true1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
442 return False
443 return self.keyword.strip().lower() == "comment" or self.keyword.strip().lower() == 'builtin.comment' 1kizjlrpByIvswFhtuCDEqemJnodgfAxb:;=OGH
445 def uncomment(self): 1ac
446 index_of_comment = self._first_non_empty_cell() 2$ ycZ 0 ! %
447 if self.step_controller_step.as_list()[index_of_comment].lower() == 'comment' or\ 2$ ycZ 0 ! %
448 self.step_controller_step.as_list()[index_of_comment].lower() == 'builtin.comment':
449 self.shift_left(index_of_comment, True) 1$Z0!%
450 self.recalculate_keyword_column() 1$Z0!%
452 def shift_right(self, from_column): 1ac
453 cells = self.as_list() 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb/b8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
454 comment = self._get_comment(cells) 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb/b8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
455 if len(cells) > from_column: 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb/b8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
456 if comment: 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
457 cells.pop() 2^ ) hb7b! wb
458 cells = cells[:from_column] + [''] + cells[from_column:] 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
459 self.recreate(cells, comment) 2j l lb^ ) L 2 bbsbtbhbubvb3 6b7bZb8b9b$ Z 0 ! % wbb %b'b(b/ K + xbfb1 5 # ' 6 ( R 7 M N 9 S
461 def shift_left(self, from_column, delete=False): 1ac
462 cells = self.as_list() 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
463 while not delete and from_column > 0 and cells[from_column] != '': 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
464 from_column -= 1 2P ab] cbQ b K gbjb# ~ ' 6 kb(
465 if not delete and from_column == 0 and cells[from_column] != '': 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
466 return 1K46
467 if len(cells) > from_column: 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
468 cells = cells[:from_column] + cells[from_column + 1:] 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
469 self.recreate(cells) 2)b*b+bP ab] cb? L @ Q 2 3 #b$b$ Z 0 ! % Nbwbb XbK + dbibebgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S
471 @staticmethod 1ac
472 def first_non_empty_cell(cells): 1ac
473 index = 0
474 while index < len(cells) and cells[index] == '':
475 index += 1
476 return index
478 def insert_before(self, new_step): 1ac
479 steps = self.parent.get_raw_steps() 2P ) ? L @ Q 2 Ybacqbrb, gcmchcic- . mbnbbc* b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
480 index = steps.index(self.step_controller_step) 2P ) ? L @ Q 2 Ybacqbrb, gcmchcic- . mbnbbc* b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
481 if not new_step or not new_step.as_list(): 2P ) ? L @ Q 2 Ybacqbrb, gcmchcic- . mbnbbc* b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
482 new_step = robotapi.Step([]) 2gcmchcic- . mbnbbc*
483 if index > 0: 2P ) ? L @ Q 2 Ybacqbrb, gcmchcic- . mbnbbc* b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
484 upper_indent = steps[index-1].first_non_empty_cell() # self.first_non_empty_cell(steps[index-1].as_list()) 2P ) ? L @ Q 2 Yb, gchcicmbnbbcb / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
485 current_indent = new_step.first_non_empty_cell() # self.first_non_empty_cell(new_step.as_list()) 2P ) ? L @ Q 2 Yb, gchcicmbnbbcb / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
486 delta_indent = upper_indent - current_indent 2P ) ? L @ Q 2 Yb, gchcicmbnbbcb / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
487 if delta_indent > 0: 2P ) ? L @ Q 2 Yb, gchcicmbnbbcb / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
488 e_list = [] 2L @ 2 hcK ` 1 { | 4 } 5 R 7 M N 9 S
489 for _ in range(1, delta_indent): 489 ↛ 490line 489 didn't jump to line 490 because the loop on line 489 never started2L @ 2 hcK ` 1 { | 4 } 5 R 7 M N 9 S
490 e_list.append('')
491 new_step = robotapi.Step(e_list + new_step.as_list(indent=True)) 2L @ 2 hcK ` 1 { | 4 } 5 R 7 M N 9 S
492 elif delta_indent < 0 and len(new_step.as_list()) > 1: 2P ) ? L Q Yb, gcicmbnbbcb / K 1 4 ;b=b?b[ R 8 M N S
493 for _ in range(delta_indent, 0): 2? L / ;b[ R 8 M N S
494 if new_step.as_list()[0] == '': 494 ↛ 493line 494 didn't jump to line 493 because the condition on line 494 was always true2? L / ;b[ R 8 M N S
495 new_step = robotapi.Step(new_step.as_list(indent=True)[1:]) 2? L / ;b[ R 8 M N S
496 elif delta_indent == 0 and len(steps[index-1].as_list()) > upper_indent: 2P ) L Q Yb, gcicmbnbbcb K 1 4 =b?bR M N S
497 if steps[index-1].as_list()[upper_indent-1] in ['END'] \ 2P ) L Q Yb, gcicmbnbbcb K 1 4 =b?bR M N S
498 or steps[index-1].as_list()[upper_indent] in ['FOR']:
499 new_step = robotapi.Step([''] + new_step.as_list(indent=True)) 1PQK1MN
500 self.parent.set_raw_steps(steps[:index] + [new_step] + steps[index:]) 2P ) ? L @ Q 2 Yb, gchcicmbnbbcb / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
501 else:
502 current_indent = len(new_step.indent) 2Ybacqbrb, mc- . * b K 4 8 M N
503 delta_indent = current_indent - len(self.step_controller_step.indent) 2Ybacqbrb, mc- . * b K 4 8 M N
504 if delta_indent > 0: 2Ybacqbrb, mc- . * b K 4 8 M N
505 for _ in range(0, delta_indent): 18MN
506 if new_step.as_list()[0] == '': 506 ↛ 505line 506 didn't jump to line 505 because the condition on line 506 was always true18MN
507 new_step = robotapi.Step(new_step.as_list(indent=False)[1:]) 18MN
508 else:
509 new_step = robotapi.Step(new_step.as_list(indent=False)) 2Ybacqbrb, mc- . * b K 4
510 self.parent.set_raw_steps([new_step] + steps[index:]) 2Ybacqbrb, mc- . * b K 4 8 M N
512 def insert_after(self, new_step): 1ac
513 steps = self.parent.get_raw_steps() 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
514 index = steps.index(self.step_controller_step) + 1 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
515 if not self._is_end_step(new_step.as_list()): 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
516 if self._is_intended_step(steps[index-1].as_list()): 2P ab] cb^ _b`bL Q qbrb, b ccK dbibebfbgbdcecfcjb# ~ ' 6 kb(
517 if not self._is_intended_step(new_step.as_list()): 2P ab] L Q dbibebgbdc# ~ ' 6 kb(
518 new_step.increase_indent() # shift_right(0) # DEBUG Hard coded! 2P ab] Q dbibebgb# ~
519 else:
520 if self._is_intended_step(new_step.as_list()) and isinstance(new_step, StepController): 520 ↛ 521line 520 didn't jump to line 521 because the condition on line 520 was never true2] cb^ _b`bqbrb, b ccK dbebfbecfcjb# ~ 6
521 new_step.decrease_indent() # shift_left(1) # DEBUG Hard coded!
522 self.parent.set_raw_steps(steps[:index] + [new_step] + steps[index:]) 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
524 def remove_empty_columns_from_end(self): 1ac
525 cells = self.as_list() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbGbCbSbHbDbEbbbTbUbVbIbzbWb3 Jb- . AbBbmbnbobKbZ 0 LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
526 while cells != [] and cells[-1].strip() == '': 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbGbCbSbHbDbEbbbTbUbVbIbzbWb3 Jb- . AbBbmbnbobKbZ 0 LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
527 cells.pop() 2zb3 - . AbBbobOb
528 self.recreate(cells) 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRbGbCbSbHbDbEbbbTbUbVbIbzbWb3 Jb- . AbBbmbnbobKbZ 0 LbMb* Nb,bFb:b0b1b2b!bXbOb3b5b-b+ PbQb4bT U V W X Y
530 def remove_empty_columns_from_beginning(self): 1ac
531 cells = self.step_controller_step.as_list()
532 if cells != [] and cells[0].strip() == '':
533 cells = cells[1:]
534 self.recreate(cells)
536 def remove(self): 1ac
537 self.parent.data.steps.remove(self.step_controller_step) 2a A x pbP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, CcGcDcEcZbmbnbobbc* b cc/ K dbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S
538 self.parent.clear_cached_steps() 2a A x pbP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, CcGcDcEcZbmbnbobbc* b cc/ K dbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S
540 def move_up(self): 1ac
541 previous_step = self.parent.step(self._index() - 1) 2P ) ? L @ Q 2 Ybacqbrb, b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
542 self.remove() 2P ) ? L @ Q 2 Ybacqbrb, b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
543 previous_step.insert_before(self.step_controller_step) 2P ) ? L @ Q 2 Ybacqbrb, b / K ` 1 { | 4 } 5 ;b=b?b[ R 7 8 M N 9 S
545 def move_down(self): 1ac
546 next_step = self.parent.step(self._index() + 1) 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
547 self.remove() 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
548 next_step.insert_after(self.step_controller_step) 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
550 def _index(self): 1ac
551 return self.parent.index_of_step(self.step_controller_step) 2P ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, b cc/ K dbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S
553 def has_only_comment(self): 1ac
554 non_empty_cells = [cell for cell
555 in self.step_controller_step.as_list() if cell.strip() != '']
556 return len(non_empty_cells) == 1 and \
557 non_empty_cells[0].startswith('#')
559 def _get_comment(self, cells): 1ac
560 if not cells: 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRblb^ ) L 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . 6b7bZb/b8b9bAbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bxbfb1 5 # ' 6 ( R 7 M N 9 S T U V W X Y
561 return None 13
562 return cells[-1].strip() if cells[-1].startswith('#') else None 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pbRblb^ ) L 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Jb- . 6b7bZb/b8b9bAbBbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bxbfb1 5 # ' 6 ( R 7 M N 9 S T U V W X Y
564 def recreate(self, cells, comment=None): 1ac
565 self.step_controller_step.__init__(cells, comment) 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
566 self.recalculate_keyword_column() 2a k i z j l r p B v s w F h t u C D E q e m n o d g f pb)b*b+bRbP ab] cblb^ ) ? L @ Q 2 yb_ GbCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 #b$bJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ Z 0 ! % LbMb* Nb,bFb:b0bwb1b2b!bb XbOb%b'b(b3b/ K 5b-b+ PbQb4bdbibebxbfbgbjb` 1 { | 4 } 5 [ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y
568 def _is_partial_for_loop_step(self, cells): 1ac
569 return cells and (cells[self._keyword_column].replace(' ', '').upper() == ':FOR'
570 or cells[self._keyword_column] == 'FOR')
572 def _is_for_loop(self): 1ac
573 return self.keyword == 'FOR'
575 def _is_intended_step(self, cells): 1ac
576 return cells and not cells[0].strip() and any(c.strip() for c in cells) and self._index() > 0 2P ab] cb^ _b`bL Q qbrb, b ccK dbibebfbgbdcecfcjb# ~ ' 6 kb(
578 @staticmethod 1ac
579 def _is_end_step(cells): 1ac
580 return cells and ('END' in cells) # cells[0] == 'END' # DEBUG: Improve check 2P ab] cblb^ _b`bL Q qbrb, b ccK dbibebjcxbfbgbdcecfcjb# ~ ' 6 kb(
582 def _recreate_as_intended_step(self, for_loop_step, cells, comment, index): 1ac
583 self.remove()
584 for_loop_step.add_step(robotapi.Step(cells[:], comment))
585 self._recreate_next_step(index)
587 def _recreate_next_step(self, index): 1ac
588 if len(self.parent.steps) > index + 1:
589 next_step = self.parent.step(index + 1)
590 next_step.recreate(next_step.as_list())
592 def notify_value_changed(self, old_name=None, new_name=None): 1ac
593 # print(f"DEBUG: stepcontrollers.py StepController notify_value_changed: ENTER old_name={old_name}"
594 # f" parent={self.parent.name} new_name={new_name} calling self.parent.notify_steps_changed()")
595 if old_name is not None: 595 ↛ 597line 595 didn't jump to line 597 because the condition on line 595 was always true2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
596 RideItemNameChanged(item=self, old_name=old_name, new_name=new_name).publish() 2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
597 self.parent.notify_steps_changed(old_name) 2{bT U V @b|b.bW }bX Y [b]b^bkclc~b
599 def increase_indent(self): 1ac
600 self.indent.append('') 2a B y h e m n o pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcFb0bwb1b2b!bb Ob%b'b(b3bcc/ K PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y zcBcMcNcOcPc
601 return len(self.indent) 2a B y h e m n o pb)b*b+bRbJcKcP ab] cblb^ ) _b`b? L @ Q 2 Ybacqbrb, yb_ GbgcmchcIcicCbSbHbDbEbbbTbUbVbIbzbWbsbtbhbubvb3 Cc#bGcDc$bEcJb- . 6b7bZb/b8b9bAbBbmbnbobKb$ ycZ 0 ! % bcLbMb* LcFb0bwb1b2b!bb Ob%b'b(b3bcc/ K PbQb4bdbibebjcxbfbgbdcecfcjb` 1 { | 4 } 5 ;b=b?b[ # ~ ' 6 kb( R 7 8 M N 9 S T U V W X Y zcBcMcNcOcPc
603 def decrease_indent(self): 1ac
604 self.indent = self.indent[:-1] if len(self.indent) > 0 else []
605 return len(self.indent)
607 @property 1ac
608 def steps(self): 1ac
609 return [IntendedStepController(self, sub_step)
610 for sub_step in self.get_raw_steps()]
612 def __len__(self): 1ac
613 return len(self.step_controller_step)
616class ForLoopStepController(StepController): 1ac
618 def __init__(self, parent, step): 1ac
619 StepController.__init__(self, parent, step)
620 self.inner_kw_pos = self._first_non_empty_cell()
622 @property 1ac
623 def name(self): 1ac
624 return self.parent.name
626 @property 1ac
627 def assignments(self): 1ac
628 return self.step_controller_step.vars
630 """ 1ac
631 @property
632 def _keyword_column(self):
633 return self.inner_kw_pos
634 """
636 def move_up(self): 1ac
637 previous_step = self.parent.step(self._index() - 1)
638 if isinstance(previous_step, ForLoopStepController):
639 self._swap_forloop_headers(previous_step)
640 else:
641 self.get_raw_steps().insert(0, previous_step.step_controller_step)
642 previous_step.remove()
644 def _swap_forloop_headers(self, previous_step): 1ac
645 previous_step.step_controller_step.steps = self.step_controller_step.steps
646 self.step_controller_step.steps = []
647 steps = self.parent.get_raw_steps()
648 i = steps.index(self.step_controller_step)
649 steps[i - 1] = self.step_controller_step
650 steps[i] = previous_step.step_controller_step
651 self.parent.set_raw_steps(steps)
653 def move_down(self): 1ac
654 next_step = self.step(self._index() + 1)
655 next_step.move_up()
656 if len(self.step_controller_step.steps) == 0:
657 self._recreate_complete_for_loop_header(cells=self.as_list())
659 def insert_after(self, new_step): 1ac
660 self.get_raw_steps().insert(0, new_step)
662 def step(self, index): 1ac
663 return self.parent.step(index)
665 def _has_comment_keyword(self): 1ac
666 return False
668 def get_raw_steps(self): 1ac
669 return self.step_controller_step.steps
671 def set_raw_steps(self, steps): 1ac
672 self.step_controller_step.steps = steps
674 def _get_cell_position(self, col): 1ac
675 until_range = len(self.step_controller_step.vars) + 1
676 flavor = self.step_controller_step.flavor
677 if col == self._keyword_column:
678 return CellPosition(CellType.KEYWORD, None)
679 if col < self._keyword_column + until_range:
680 return CellPosition(CellType.ASSIGN, self.step_controller_step.vars[:])
681 if col == self._keyword_column + until_range:
682 return CellPosition(CellType.MANDATORY, None)
683 if 'IN RANGE' not in flavor:
684 return CellPosition(CellType.OPTIONAL, None)
685 if col <= self._keyword_column + until_range + 1:
686 return CellPosition(CellType.MANDATORY, None)
687 if col <= self._keyword_column + until_range + 3:
688 return CellPosition(CellType.OPTIONAL, None)
689 return CellPosition(CellType.MUST_BE_EMPTY, None)
691 def get_cell_info(self, col): 1ac
692 position = self._get_cell_position(col)
693 content = self._get_content_with_type(col, position)
694 return self._build_cell_info(content, position)
696 def _build_cell_info(self, content, position): 1ac
697 return CellInfo(content, position, for_loop=True)
699 @property 1ac
700 def steps(self): 1ac
701 return [IntendedStepController(self, sub_step)
702 for sub_step in self.get_raw_steps()]
704 def index_of_step(self, step): 1ac
705 index_in_for_loop = self.get_raw_steps().index(step)
706 return self._index() + index_in_for_loop + 1
708 def _get_comment(self, cells): 1ac
709 return None
711 def comment(self): 1ac
712 print(f"\nDEBUG: ForLoopStepController RAW STEPS: {self.get_raw_steps()}")
713 for i in self.get_raw_steps():
714 print(f"\nDEBUG: ForLoopStepController PRINT STEPS: {i.as_list()}")
715 col = self.step_controller_step.inner_kw_pos
716 header = self.as_list()
717 if col > 0:
718 self._replace_with_new_cells(header[0:col-1] + ['Comment'] + header[col:])
719 else:
720 self._replace_with_new_cells(['Comment'] + header)
722 def contains_keyword(self, name): 1ac
723 return False
725 def add_step(self, step): 1ac
726 print(f"\nDEBUG: ForLoopStepController enter add_step step={step.as_list()}")
727 self.get_raw_steps().append(step)
729 def recreate(self, cells, comment=None, delete=False): 1ac
730 kw_index = None
731 for idx in range(0, len(cells)):
732 if cells[idx] == '':
733 continue
734 if cells[idx] == 'FOR':
735 kw_index = idx
736 break
737 if kw_index and not delete: # Avoid IndentedStep when DeleteCells
738 if comment:
739 self._recreate_complete_for_loop_header(['', cells[:], comment[:]])
740 else:
741 self._recreate_complete_for_loop_header([''] + cells)
742 else:
743 new_cells = cells[:]
744 index = self._index()
745 self.parent.replace_step(index, robotapi.Step(new_cells, comment))
746 self.recalculate_keyword_column()
748 def _recreate_complete_for_loop_header(self, cells): 1ac
749 self.step_controller_step.__init__(self.parent, cells[:])
751 def remove(self): 1ac
752 steps = self.parent.data.steps
753 index = steps.index(self.step_controller_step)
754 steps.remove(self.step_controller_step)
755 self.parent.data.steps = \
756 steps[:index] + self.get_raw_steps() + steps[index:]
757 self.step_controller_step.steps = []
759 def _represent_valid_for_loop_header(self, cells): 1ac
760 if not cells:
761 return False
762 if cells[0] != self.as_list()[0]:
763 return False
764 in_token_index = len(self.vars) + 1
765 if len(cells) <= in_token_index:
766 return False
767 if len(self.as_list()) <= in_token_index:
768 return False
769 if cells[in_token_index] != self.as_list()[in_token_index]:
770 return False
771 return True
773 def _replace_with_new_cells(self, cells): 1ac
774 index = self.parent.index_of_step(self.step_controller_step)
775 self.parent.replace_step(index, robotapi.Step(cells))
776 self.get_raw_steps().reverse()
777 for substep in self.steps:
778 self.parent.add_step(index + 1, robotapi.Step(substep.as_list()))
780 def notify_steps_changed(self): 1ac
781 self.notify_value_changed()
783 def has_template(self): 1ac
784 return self.parent.has_template()
787class IntendedStepController(StepController): 1ac
789 _invalid = False 1ac
791 def _get_cell_position(self, col): 1ac
792 if col < self._keyword_column:
793 return CellPosition(CellType.MUST_BE_EMPTY, None)
794 return StepController._get_cell_position(self, col)
796 def _get_local_namespace(self): 1ac
797 p = self.parent.parent
798 index = p.index_of_step(self.step_controller_step)
799 return local_namespace(p, self.datafile_controller.namespace, index)
801 def _get_content_with_type(self, col, position): 1ac
802 if col < self._keyword_column:
803 return CellContent(ContentType.EMPTY, None)
804 return StepController._get_content_with_type(self, col, position)
806 def recreate(self, cells, comment=None, delete=False): 1ac
807 if (cells == [] or cells[0] == '') and not delete: # Avoid IndentedStep when DeleteCells
808 self.step_controller_step.__init__(cells[:], comment=comment)
809 if self.step_controller_step not in self.parent.get_raw_steps():
810 self.parent.add_step(self.step_controller_step)
811 else:
812 self.step_controller_step.__init__(cells[:], comment=comment)
813 if self.step_controller_step not in self.parent.get_raw_steps():
814 self.parent.add_step(self.step_controller_step)
815 if not delete:
816 self._recreate_as_normal_step(cells, comment)
817 self.recalculate_keyword_column()
819 def _recreate_as_normal_step(self, cells, comment=None): 1ac
820 steps = self.parent.steps
821 index = [s.step_controller_step for s in steps].index(self.step_controller_step)
822 for i, step in reversed(list(enumerate(steps))):
823 if i == index:
824 break
825 step.replace_with_normal_step(i, step.as_list())
826 self.replace_with_normal_step(index, cells, comment)
828 def replace_with_normal_step(self, index, cells=None, comment=None): 1ac
829 index_of_parent = self.parent.parent.index_of_step(self.parent.step_controller_step)
830 self.parent.parent.add_step(
831 index_of_parent + index + 2,
832 robotapi.Step(cells or self.as_list(), comment=comment))
833 self.parent.get_raw_steps().pop(index)
835 def remove(self): 1ac
836 self.parent.get_raw_steps().remove(self.step_controller_step)
838 def remove_empty_columns_from_end(self): 1ac
839 if self._invalid:
840 return
841 StepController.remove_empty_columns_from_end(self)