How to use _push_context method in autotest

Best Python code snippet using autotest_python

mwparser.py

Source:mwparser.py Github

copy

Full Screen

...124 return125 def invalid_token(self, pos, token):126 print(self._parse, pos, token, file=sys.stderr)127 return128 def _push_context(self, tree, parse, stoptokens=None, xmlcontext=None):129 if self.maxdepth <= len(self._stack): raise WikiParserStackOverflow130 self._tree.append(tree)131 self._tree = tree132 self._parse = parse133 self._stoptokens = stoptokens134 if xmlcontext is not None:135 self._xmlcontext = [xmlcontext]+self._xmlcontext136 self._stack.append((self._tree, self._parse, self._stoptokens, self._xmlcontext))137 return138 def _pop_context(self):139 assert self._stack140 self._tree.finish()141 self._stack.pop()142 (self._tree, self._parse, self._stoptokens, self._xmlcontext) = self._stack[-1]143 return144 def _is_xml_closing(self, t):145 def getuntil(*names):146 for name in self._xmlcontext:147 if name in names: break148 yield name149 return150 if isinstance(t, XMLEndTagToken) and t.name in XMLTagToken.TABLE_TAG:151 return 'table' in self._xmlcontext152 elif isinstance(t, XMLTagToken) and t.name in XMLTagToken.TABLE_ROW_TAG:153 return 'tablerow' in getuntil('table')154 elif isinstance(t, XMLTagToken) and t.name in XMLTagToken.PAR_TAG:155 return 'par' in getuntil('tablerow','table')156 else:157 return False158 # _parse_top: initial state.159 def _parse_top(self, pos, t):160 if isinstance(t, ExtensionToken):161 # Extention tag.162 self._push_context(WikiExtensionTree(t), self._parse_par)163 return True164 else:165 return self._parse_par(pos, t)166 # _parse_par: beginning of paragraph.167 def _parse_par(self, pos, t):168 if t in (169 WikiToken.HR,170 WikiToken.PAR):171 self._tree.append(t)172 return True173 elif isinstance(t, WikiItemizeToken):174 self._push_context(WikiItemizeTree(t), self._parse_itemize)175 return True176 elif isinstance(t, WikiHeadlineToken):177 self._push_context(WikiHeadlineTree(t), self._parse_headline)178 return True179 elif t is WikiToken.PRE:180 self._push_context(WikiPreTree(t), self._parse_pre)181 return True182 elif t is WikiToken.TABLE_OPEN:183 self._push_context(WikiTableTree(t), self._parse_table)184 return True185 else:186 return self._parse_base(pos, t)187 # _parse_itemize: *:#188 def _parse_itemize(self, pos, t):189 assert isinstance(self._tree, WikiItemizeTree), self._tree190 if t is WikiToken.EOL:191 # End of itemize.192 self._pop_context()193 return True194 else:195 return self._parse_par(pos, t)196 # _parse_headline: === ... ===197 def _parse_headline(self, pos, t):198 assert isinstance(self._tree, WikiHeadlineTree), self._tree199 if t is self._tree.token:200 # End of headline.201 self._pop_context()202 return True203 elif t is WikiToken.EOL:204 # FAILSAFE: missing headline token.205 self._pop_context()206 return True207 else:208 return self._parse_base(pos, t)209 # _parse_pre:210 def _parse_pre(self, pos, t):211 assert isinstance(self._tree, WikiPreTree), self._tree212 if t is WikiToken.EOL:213 # End of pre.214 self._pop_context()215 return True216 else:217 return self._parse_base(pos, t)218 # _parse_table: {| ...219 def _parse_table(self, pos, t):220 assert isinstance(self._tree, WikiTableTree), self._tree221 if self._is_xml_closing(t):222 self._pop_context()223 return False224 elif t is WikiToken.TABLE_CLOSE:225 # End of table.226 self._pop_context()227 return True228 elif t is WikiToken.TABLE_CAPTION:229 # Start of table caption.230 self._push_context(WikiTableCaptionTree(t), self._parse_table_caption)231 return True232 elif t is WikiToken.TABLE_ROW:233 # Start of table row.234 self._push_context(WikiTableRowTree(t), self._parse_table_row)235 return True236 elif t in (237 WikiToken.TABLE_HEADER,238 WikiToken.TABLE_HEADER_SEP,239 WikiToken.TABLE_DATA,240 WikiToken.TABLE_DATA_SEP):241 # FAILSAFE: missing table row token.242 self._push_context(WikiTableRowTree(t), self._parse_table_row)243 return False244 else:245 # Anything else is table argument.246 self._push_context(WikiArgTree(), self._parse_table_arg)247 return False248 # _parse_table_caption: |+ ...249 def _parse_table_caption(self, pos, t):250 assert isinstance(self._tree, WikiTableCaptionTree), self._tree251 if self._is_xml_closing(t):252 self._pop_context()253 return False254 elif t is WikiToken.EOL:255 # End of table caption.256 self._pop_context()257 return True258 elif t in (259 WikiToken.TABLE_CLOSE,260 WikiToken.TABLE_CAPTION,261 WikiToken.TABLE_ROW,262 WikiToken.TABLE_HEADER,263 WikiToken.TABLE_HEADER_SEP,264 WikiToken.TABLE_DATA,265 WikiToken.TABLE_DATA_SEP):266 # FAILSAFE: missing tokens.267 self._pop_context()268 return False269 else:270 # Anything else is table argument.271 self._push_context(WikiArgTree(), self._parse_table_arg)272 return False273 # _parse_table_row: |- ...274 def _parse_table_row(self, pos, t):275 assert isinstance(self._tree, WikiTableRowTree), self._tree276 if self._is_xml_closing(t):277 self._pop_context()278 return False279 elif t is WikiToken.EOL:280 # End of table row.281 self._pop_context()282 return True283 elif t in (284 WikiToken.TABLE_HEADER,285 WikiToken.TABLE_HEADER_SEP):286 # Start of table header.287 self._push_context(WikiTableHeaderTree(t), self._parse_table_header)288 return True289 elif t in (290 WikiToken.TABLE_DATA,291 WikiToken.TABLE_DATA_SEP):292 # Start of table data.293 self._push_context(WikiTableDataTree(t), self._parse_table_data)294 return True295 elif t in (296 WikiToken.TABLE_CLOSE,297 WikiToken.TABLE_CAPTION,298 WikiToken.TABLE_ROW):299 # FAILSAFE: missing tokens.300 self._pop_context()301 return False302 else:303 # Anything else is table argument.304 self._push_context(WikiArgTree(), self._parse_table_arg)305 return False306 # _parse_table_header: ! ... !! ...307 def _parse_table_header(self, pos, t):308 assert isinstance(self._tree, WikiTableHeaderTree), self._tree309 if self._is_xml_closing(t):310 self._pop_context()311 return False312 elif t is WikiToken.EOL:313 # End of table header.314 self._pop_context()315 return True316 elif t is WikiToken.TABLE_HEADER_SEP:317 # Next table header.318 self._pop_context()319 return False320 elif t in (321 WikiToken.TABLE_CLOSE,322 WikiToken.TABLE_CAPTION,323 WikiToken.TABLE_ROW,324 WikiToken.TABLE_HEADER,325 WikiToken.TABLE_DATA,326 WikiToken.TABLE_DATA_SEP):327 # FAILSAFE: missing tokens.328 self._pop_context()329 return False330 else:331 # Anything else is table argument.332 self._push_context(WikiArgTree(), self._parse_table_arg)333 return False334 # _parse_table_data: | ... || ...335 def _parse_table_data(self, pos, t):336 assert isinstance(self._tree, WikiTableDataTree), self._tree337 if self._is_xml_closing(t):338 self._pop_context()339 return False340 elif t is WikiToken.EOL:341 # End of table data.342 self._pop_context()343 return True344 elif t is WikiToken.TABLE_DATA_SEP:345 # Next table data.346 self._pop_context()347 return False348 elif t in (349 WikiToken.TABLE_CLOSE,350 WikiToken.TABLE_CAPTION,351 WikiToken.TABLE_ROW,352 WikiToken.TABLE_HEADER,353 WikiToken.TABLE_HEADER_SEP,354 WikiToken.TABLE_DATA):355 # FAILSAFE: missing tokens.356 self._pop_context()357 return False358 else:359 # Anything else is table argument.360 self._push_context(WikiArgTree(), self._parse_table_arg)361 return False362 # _parse_table_arg:363 def _parse_table_arg(self, pos, t):364 assert isinstance(self._tree, WikiArgTree), self._tree365 if t is WikiToken.EOL:366 # End of table argument.367 self._pop_context()368 return True369 elif t is WikiToken.BAR:370 # Next table argument.371 self._pop_context()372 return True373 elif t in (374 WikiToken.TABLE_CLOSE,375 WikiToken.TABLE_CAPTION,376 WikiToken.TABLE_ROW,377 WikiToken.TABLE_HEADER,378 WikiToken.TABLE_HEADER_SEP,379 WikiToken.TABLE_DATA,380 WikiToken.TABLE_DATA_SEP):381 # FAILSAFE: missing tokens.382 self._pop_context()383 return False384 else:385 return self._parse_base(pos, t)386 # _parse_base: generic parse state.387 def _parse_base(self, pos, t):388 if self._is_xml_closing(t):389 self._pop_context()390 return False391 elif t is WikiToken.SPECIAL_OPEN:392 self._push_context(WikiSpecialTree(t), self._parse_special)393 return True394 elif t is WikiToken.KEYWORD_OPEN:395 self._push_context(WikiKeywordTree(t), self._parse_keyword)396 return True397 elif t is WikiToken.LINK_OPEN:398 self._push_context(WikiLinkTree(t), self._parse_link)399 return True400 elif t in (401 WikiToken.QUOTE2,402 WikiToken.QUOTE3,403 WikiToken.QUOTE5):404 self._push_context(WikiSpanTree(t), self._parse_span)405 return True406 elif t is WikiToken.COMMENT_OPEN:407 self._push_context(WikiCommentTree(t), self._parse_comment)408 return True409 elif isinstance(t, WikiToken):410 # any unhandled wiki token.411 self._tree.append(t)412 return True413 elif isinstance(t, XMLStartTagToken) and t.name in XMLTagToken.TABLE_TAG:414 self._push_context(WikiXMLTableTree(t), self._parse_xml_table,415 xmlcontext='table')416 return True417 elif isinstance(t, XMLStartTagToken) and t.name in XMLTagToken.PAR_TAG:418 self._push_context(WikiXMLParTree(t), self._parse_xml_par,419 xmlcontext='par')420 return True421 elif isinstance(t, XMLStartTagToken):422 self._push_context(WikiXMLTree(t), self._parse_xml)423 return True424 elif isinstance(t, XMLTagToken):425 # any unhandled XML token.426 self._tree.append(t)427 return True428 elif isinstance(t, str):429 # text string.430 self._tree.append(t)431 return True432 else:433 self.invalid_token(pos, t)434 return True435 # _parse_special: {{ ... }}436 def _parse_special(self, pos, t):437 assert isinstance(self._tree, WikiSpecialTree), self._tree438 if self._is_xml_closing(t):439 self._pop_context()440 return False441 elif t is WikiToken.SPECIAL_CLOSE:442 # End of special.443 self._pop_context()444 return True445 else:446 self._push_context(WikiArgTree(), self._parse_arg_barsep,447 stoptokens=(WikiToken.SPECIAL_CLOSE,))448 return False449 # _parse_keyword: [[ ... ]]450 def _parse_keyword(self, pos, t):451 assert isinstance(self._tree, WikiKeywordTree), self._tree452 if self._is_xml_closing(t):453 self._pop_context()454 return False455 elif t is WikiToken.KEYWORD_CLOSE:456 # End of keyword.457 self._pop_context()458 return True459 elif t is WikiToken.EOL:460 # FAILSAFE: missing token.461 self._pop_context()462 return False463 else:464 self._push_context(WikiArgTree(), self._parse_arg_barsep,465 stoptokens=(WikiToken.KEYWORD_CLOSE,))466 return False467 # _parse_link: [ ... ]468 def _parse_link(self, pos, t):469 assert isinstance(self._tree, WikiLinkTree), self._tree470 if self._is_xml_closing(t):471 self._pop_context()472 return False473 elif t is WikiToken.LINK_CLOSE:474 # End of link.475 self._pop_context()476 return True477 elif t is WikiToken.EOL:478 # FAILSAFE: missing token.479 self._pop_context()480 return False481 else:482 self._push_context(WikiArgTree(), self._parse_arg_blanksep,483 stoptokens=(WikiToken.LINK_CLOSE,))484 return False485 # _parse_span: ''...'', '''...''', etc.486 def _parse_span(self, pos, t):487 assert isinstance(self._tree, WikiSpanTree), self._tree488 if t is self._tree.token:489 # End of span.490 self._pop_context()491 return True492 elif t is WikiToken.EOL:493 # FAILSAFE: missing token.494 self._pop_context()495 return False496 else:497 return self._parse_base(pos, t)498 # _parse_arg_barsep: ...|...|...499 def _parse_arg_barsep(self, pos, t):500 assert isinstance(self._tree, WikiArgTree), self._tree501 assert self._stoptokens is not None502 if t in self._stoptokens:503 # End of argument.504 self._pop_context()505 return False506 elif t is WikiToken.BAR:507 # Next argument.508 self._pop_context()509 return True510 else:511 return self._parse_base(pos, t)512 # _parse_arg_blanksep: ... ... ...513 def _parse_arg_blanksep(self, pos, t):514 assert isinstance(self._tree, WikiArgTree), self._tree515 assert self._stoptokens is not None516 if t in self._stoptokens:517 # End of argument.518 self._pop_context()519 return False520 elif t is WikiToken.BLANK:521 # Next argument.522 self._pop_context()523 return True524 else:525 return self._parse_base(pos, t)526 # _parse_comment: <!-- ... -->527 def _parse_comment(self, pos, t):528 assert isinstance(self._tree, WikiCommentTree), self._tree529 if t is WikiToken.COMMENT_CLOSE:530 # End of comment.531 self._pop_context()532 return True533 else:534 self._tree.append(t)535 return True536 # _parse_xml_table: handle XML table tags.537 def _parse_xml_table(self, pos, t):538 assert isinstance(self._tree, WikiXMLTableTree), self._tree539 if (isinstance(t, XMLEndTagToken) and540 t.name in XMLTagToken.TABLE_TAG):541 # End of XML table.542 self._pop_context()543 return True544 elif (isinstance(t, XMLStartTagToken) and545 t.name in XMLTagToken.TABLE_ROW_TAG):546 self._push_context(WikiXMLTableRowTree(t),547 self._parse_xml_table_row,548 xmlcontext='tablerow')549 # Start <table>.550 return True551 else:552 return self._parse_par(pos, t)553 # _parse_xml_table_row: handle XML table row tags.554 def _parse_xml_table_row(self, pos, t):555 assert isinstance(self._tree, WikiXMLTableRowTree), self._tree556 if (isinstance(t, XMLEndTagToken) and557 t.name in XMLTagToken.TABLE_ROW_TAG):558 # End of <tr>.559 self._pop_context()560 return True...

Full Screen

Full Screen

symbol_common.py

Source:symbol_common.py Github

copy

Full Screen

...451 raise Exception('Parse ScaleLearningRate at {} failed'.format(q.begin))452 return inst453 q.backward()454 def compile(self, context, data):455 context = self._push_context(context)456 return self.operator.compile(context, data)457 def encode(self, context):458 return 'lr{}{}'.format(self.scale_text, self.operator.encode(context))459 def _push_context(self, context):460 context = context.copy()461 context['lr_mult'] = self.scale * context.get('lr_mult', 1)462 return context463class ScaleWeightDecay(Operator):464 @classmethod465 def parse(cls, context, q, **kargs):466 token, match = q.forward()467 if token == 'scale_weight_decay':468 inst = cls()469 inst.scale_text = match.group(1)470 inst.scale = float(inst.scale_text)471 inst.operator = Operator.parse(context, q, **kargs)472 if not inst.operator:473 raise Exception('Parse ScaleWeightDecay at {} failed'.format(q.begin))474 return inst475 q.backward()476 def compile(self, context, data):477 context = self._push_context(context)478 return self.operator.compile(context, data)479 def encode(self, context):480 return 'wd{}{}'.format(self.scale_text, self.operator.encode(context))481 def _push_context(self, context):482 context = context.copy()483 context['wd_mult'] = self.scale * context.get('wd_mult', 1)484 return context485class FixBN(Operator):486 @classmethod487 def parse(cls, context, q, **kargs):488 token, match = q.forward()489 if token == 'fixbn':490 inst = cls()491 inst.operator = Operator.parse(context, q, **kargs)492 if not inst.operator:493 raise Exception('Parse FixBN at {} failed'.format(q.begin))494 return inst495 q.backward()496 def compile(self, context, data):497 context = self._push_context(context)498 return self.operator.compile(context, data)499 def encode(self, context):500 return 'fixbn' + self.operator.encode(context)501 def _push_context(self, context):502 context = context.copy()503 context['fix_batch_norm'] = True504 return context505class Fix(Operator):506 @classmethod507 def parse(cls, context, q, **kargs):508 token, match = q.forward()509 if token == 'fix':510 inst = cls()511 inst.operator = Operator.parse(context, q, **kargs)512 if not inst.operator:513 raise Exception('Parse Fix at {} failed'.format(q.begin))514 return inst515 q.backward()516 def compile(self, context, data):517 context = self._push_context(context)518 return self.operator.compile(context, data)519 def encode(self, context):520 return 'fix' + self.operator.encode(context)521 def _push_context(self, context):522 context = context.copy()523 context['lr_mult'] = 0524 context['fix_batch_norm'] = True525 return context526class Bng(Operator):527 @classmethod528 def parse(cls, context, q, **kargs):529 token, match = q.forward()530 if token == 'bng':531 inst = cls()532 inst.operator = Operator.parse(context, q, **kargs)533 if not inst.operator:534 raise Exception('Parse Bng at {} failed'.format(q.begin))535 return inst536 q.backward()537 def compile(self, context, data):538 context = self._push_context(context)539 return self.operator.compile(context, data)540 def encode(self, context):541 return 'bng' + self.operator.encode(context)542 def _push_context(self, context):543 context = context.copy()544 context['batch_norm_use_global_stats'] = True545 return context546class Share(Operator):547 @classmethod548 def parse(cls, context, q, **kargs):549 token, match = q.forward()550 if token == 'share':551 inst = cls()552 inst.operator = Operator.parse(context, q, **kargs)553 if not inst.operator:554 raise Exception('Parse Share at {} failed'.format(q.begin))555 return inst556 q.backward()557 def compile(self, context, data):558 data, unpack = context['pack'](data)559 return unpack(self.operator.compile(context, data))560 def encode(self, context):561 return 'share' + self.operator.encode(context)562class Tee(Operator):563 @classmethod564 def parse(cls, context, q, **kargs):565 token, match = q.forward()566 if token == 'tee':567 inst = cls()568 inst.operator = Operator.parse(context, q, **kargs)569 if not inst.operator:570 raise Exception('Parse Tee at {} failed'.format(q.begin))571 return inst572 q.backward()573 def compile(self, context, data):574 return [self.operator.compile(context, branch) for branch in data]575 def encode(self, context):576 return 'tee' + self.operator.encode(context)577class Identity(Operator):578 class Op(mx.operator.CustomOp):579 def forward(self, is_train, req, in_data, out_data, aux):580 self.assign(out_data[0], req[0], 0 + in_data[0])581 def backward(self, req, out_grad, in_data, out_data, in_grad, aux):582 self.assign(in_grad[0], req[0], 0 + out_grad[0])583 @mx.operator.register('Identity')584 class Prop(mx.operator.CustomOpProp):585 def __init__(self):586 super(Identity.Prop, self).__init__(need_top_grad=True)587 def infer_shape(self, in_shape):588 data_shape = in_shape[0]589 output_shape = in_shape[0]590 return [data_shape], [output_shape], []591 def create_operator(self, ctx, shapes, dtypes):592 return Identity.Op()593 @classmethod594 def parse(cls, context, q, **kargs):595 token, match = q.forward()596 if token == 'identity':597 inst = cls()598 inst.name = match.group(1)599 return inst600 q.backward()601 def compile(self, context, data):602 return mx.symbol.Custom(data=data, name=self.name, op_type='Identity')603 def encode(self, context):604 return 'id' if self.name is None else 'id:' + self.name605class Sequence(Operator):606 '''This class must be defined at the end of this file'''607 @classmethod608 def parse(cls, context, q, **kargs):609 top = q.begin == 0610 token, match = q.forward()611 has_left = token == 'sequence_left'612 if top or has_left:613 if not has_left:614 q.backward()615 inst = cls()616 inst.operators = parse_operators(context, q, **kargs)617 has_right = False618 if has_left:619 token, match = q.forward()620 has_right = token == 'sequence_right'621 if not top and not has_right:622 raise Exception('Missing "]" at {}'.format(q.current))623 return inst624 q.backward()625 def compile(self, context, data):626 net = data627 context = self._push_context(context)628 for operator in self.operators:629 net = operator.compile(context, net)630 return net631 def encode(self, context):632 return '[' + ''.join(op.encode(context) for op in self.operators) + ']'633 def _push_context(self, context):634 context = context.copy()635 def gen_next_name(operator):636 index = context['counter'](type(operator))637 return add_prefix(operator.format_name(index=index))638 def gen_next_dropout_name():639 last_name = self.get_last_name(context)640 return last_name + '_drop' if last_name else None641 def add_prefix(name):642 return prefix + '_' + name if prefix else name643 def counter(operator):644 memo = getattr(counter, 'memo', None)645 if memo is None:646 memo = counter.memo = {}647 if operator in memo:...

Full Screen

Full Screen

test_util.py

Source:test_util.py Github

copy

Full Screen

...12 def _singleton_id():13 return id(GlobalContextTest.singleton_a)14 original_id = _singleton_id()15 new_object = object()16 TestContext._push_context(new_object)17 assert not _singleton_id() == original_id18 assert _singleton_id() == id(new_object)19 TestContext._pop_context()20 assert not _singleton_id() == id(new_object)21 assert _singleton_id() == original_id22 def test_nested_push_pop_of_two_singletons(self):23 class TestContext(util.GlobalContext):24 singleton_attr = (GlobalContextTest, 'singleton_a')25 def _singleton_id():26 return id(GlobalContextTest.singleton_a)27 original_id = _singleton_id()28 first_object = object()29 second_object = object()30 assert _singleton_id() == original_id31 TestContext._push_context(first_object)32 assert _singleton_id() == id(first_object)33 TestContext._push_context(second_object)34 assert _singleton_id() == id(second_object)35 TestContext._pop_context()36 assert _singleton_id() == id(first_object)37 TestContext._pop_context()38 assert _singleton_id() == original_id39 def test_multiple_global_contexts(self):40 class FirstContext(util.GlobalContext):41 singleton_attr = (GlobalContextTest, 'singleton_a')42 class SecondContext(util.GlobalContext):43 singleton_attr = (GlobalContextTest, 'singleton_b')44 def _first_singleton_id():45 return id(GlobalContextTest.singleton_a)46 def _second_singleton_id():47 return id(GlobalContextTest.singleton_b)48 first_original_id = _first_singleton_id()49 second_original_id = _second_singleton_id()50 assert not first_original_id == second_original_id51 first_object = object()52 second_object = object()53 FirstContext._push_context(first_object)54 assert _first_singleton_id() == id(first_object)55 assert not _second_singleton_id() == id(first_object)56 SecondContext._push_context(second_object)57 assert _second_singleton_id() == id(second_object)58 assert not _first_singleton_id() == id(second_object)59 assert _first_singleton_id() == id(first_object)60 FirstContext._pop_context()61 assert _first_singleton_id() == first_original_id62 SecondContext._pop_context()63 assert _second_singleton_id() == second_original_id64 def test_context_manager(self):65 class TestContext(util.GlobalContext): pass66 TestContext.singleton_attr = (GlobalContextTest, 'singleton_a')67 GlobalContextTest.singleton_a = TestContext()68 original_id = id(GlobalContextTest.singleton_a)69 new_context = TestContext()70 with new_context:...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run autotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful