How to use _write_file method in green

Best Python code snippet using green

test_yaml_target.py

Source:test_yaml_target.py Github

copy

Full Screen

...24 ds = YamlTargetSource({'root_dir': tmpdir})25 # We have to fill the configuration directory with files that the26 # data source can read.27 root_dir_path = pathlib.Path(tmpdir)28 _write_file(29 root_dir_path / 'top.yaml',30 """31 '*':32 - a33 """)34 _write_file(35 root_dir_path / 'a.yaml',36 """37 key: 138 """)39 (data, version1) = ds.get_data('dummy', {}, '')40 self.assertEqual({'key': 1}, data)41 # Now we update a.yaml.42 # We actually try several times with increasing sleep times. On43 # systems, where the time stamp is very precise, the test finishes44 # quickly, on other ones it takes a bit longer.45 sleep_time = 0.0146 while sleep_time < 3.0:47 _write_file(48 root_dir_path / 'a.yaml',49 """50 key: 251 """)52 (data, version2) = ds.get_data('dummy', {}, '')53 if version1 != version2:54 break55 time.sleep(sleep_time)56 sleep_time *= 257 self.assertEqual({'key': 2}, data)58 self.assertNotEqual(version1, version2)59 # Now we update top.yaml.60 # We actually try several times with increasing sleep times. On61 # systems, where the time stamp is very precise, the test finishes62 # quickly, on other ones it takes a bit longer.63 sleep_time = 0.0164 while sleep_time < 3.0:65 _write_file(66 root_dir_path / 'top.yaml',67 """68 '*':69 - b70 """)71 _write_file(72 root_dir_path / 'b.yaml',73 """74 key: 375 """)76 (data, version3) = ds.get_data('dummy', {}, '')77 if version2 != version3:78 break79 time.sleep(sleep_time)80 sleep_time *= 281 self.assertEqual({'key': 3}, data)82 self.assertNotEqual(version2, version3)83 def test_cache_invalidation_import(self):84 """85 Test that a template is rendered again when a template that is imported86 by that template changes. This specifically tests for a bug that we had87 in a pre-release version.88 """89 with TemporaryDirectory() as tmpdir:90 ds = YamlTargetSource({'root_dir': tmpdir})91 # We have to fill the configuration directory with files that the92 # data source can read.93 root_dir_path = pathlib.Path(tmpdir)94 _write_file(95 root_dir_path / 'top.yaml',96 """97 '*':98 - a99 """)100 _write_file(101 root_dir_path / 'a.yaml',102 """103 {% from 'b.yaml' import value %}104 key: {{ value }}105 """)106 _write_file(107 root_dir_path / 'b.yaml',108 """109 {% set value = 1 %}110 """)111 (data, version1) = ds.get_data('dummy', {}, '')112 self.assertEqual({'key': 1}, data)113 # Now we update b.yaml.114 # We actually try several times with increasing sleep times. On115 # systems, where the time stamp is very precise, the test finishes116 # quickly, on other ones it takes a bit longer.117 sleep_time = 0.01118 while sleep_time < 3.0:119 _write_file(120 root_dir_path / 'b.yaml',121 """122 {% set value = 2 %}123 """)124 (data, version2) = ds.get_data('dummy', {}, '')125 if version1 != version2:126 break127 time.sleep(sleep_time)128 sleep_time *= 2129 self.assertEqual({'key': 2}, data)130 self.assertNotEqual(version1, version2)131 def test_config_allow_empty_top(self):132 """133 Test the 'allow_empty_top' configuration option.134 """135 with TemporaryDirectory() as tmpdir:136 # We disable the cache for this test because it causes problems when137 # we rapidly make changes to the files. We also have to disable the138 # template cache, because that could cause problems, too.139 ds = YamlTargetSource(140 {141 'cache_size': 0,142 'root_dir': tmpdir,143 'template_config': {'cache_enabled': False}})144 # We have to fill the configuration directory with files that the145 # data source can read.146 root_dir_path = pathlib.Path(tmpdir)147 _write_file(148 root_dir_path / 'top.yaml',149 """150 """)151 # Without allow_empty_top set, an empty top file should result in a152 # type error.153 with self.assertRaises(TypeError):154 ds.get_data('dummy', {}, '')155 # Now we enable the option and test again.156 ds = YamlTargetSource(157 {158 'allow_empty_top': True,159 'cache_size': 0,160 'root_dir': tmpdir,161 'template_config': {'cache_enabled': False}})162 ds.get_data('dummy', {}, '')163 # A top file that is invalid (e.g. provides a list instead of a164 # dict) should still result in a type error.165 _write_file(166 root_dir_path / 'top.yaml',167 """168 - foo169 - bar170 """)171 with self.assertRaises(TypeError):172 ds.get_data('dummy', {}, '')173 def test_config_cache_size(self):174 """175 Test the 'cache_size' configuration option.176 In fact, there is no simple way of testing that changes in the size177 actually have the desired effect, but we can test that disabling the178 cache by setting the size to zero works.179 We do not test here that caching works for a non-zero this. This test180 is handled by `test_cache`.181 """182 with TemporaryDirectory() as tmpdir:183 ds = YamlTargetSource({'root_dir': tmpdir, 'cache_size': 0})184 # We have to fill the configuration directory with files that the185 # data source can read.186 root_dir_path = pathlib.Path(tmpdir)187 _write_file(188 root_dir_path / 'top.yaml',189 """190 '*':191 - a192 """)193 _write_file(194 root_dir_path / 'a.yaml',195 """196 key: {{ data['input'] }}197 """)198 (data, _) = ds.get_data('dummy', {'input': 1}, '1')199 self.assertEqual({'key': 1}, data)200 # Now we change the input, but do not update the corresponding201 # version number. If the cache was enabled, we would still get the202 # old data (as tested in test_cache).203 # Please note that we cannot test the version number here because204 # it might actually be the same (we did not change the input205 # version, so the code cannot know that a different version number206 # should be generated).207 (data, _) = ds.get_data('dummy', {'input': 2}, '1')208 self.assertEqual({'key': 2}, data)209 def test_config_merge_lists(self):210 """211 Test the 'merge_lists' configuration option.212 """213 with TemporaryDirectory() as tmpdir:214 ds = YamlTargetSource({'root_dir': tmpdir})215 # We have to fill the configuration directory with files that the216 # data source can read.217 root_dir_path = pathlib.Path(tmpdir)218 _write_file(219 root_dir_path / 'top.yaml',220 """221 '*':222 - a223 - b224 """)225 _write_file(226 root_dir_path / 'a.yaml',227 """228 key:229 - 3230 - 4231 - 5232 """)233 _write_file(234 root_dir_path / 'b.yaml',235 """236 key:237 - 1238 - 2239 - 3240 """)241 (data, _) = ds.get_data('dummy', {}, '')242 # We expect that the lists have not been merged and the second243 # definition has replaced the first definition instead.244 self.assertEqual([1, 2, 3], data['key'])245 # Now we repeat the test, but this time we set merge_lists to True.246 ds = YamlTargetSource({'root_dir': tmpdir, 'merge_lists': True})247 (data, _) = ds.get_data('dummy', {}, '')248 # Now the elements that are defined later should be appended, but249 # only those elements that were not already present.250 self.assertEqual([3, 4, 5, 1, 2], data['key'])251 def test_config_merge_sets(self):252 """253 Test the 'merge_sets' configuration option.254 """255 with TemporaryDirectory() as tmpdir:256 ds = YamlTargetSource({'root_dir': tmpdir})257 # We have to fill the configuration directory with files that the258 # data source can read.259 root_dir_path = pathlib.Path(tmpdir)260 _write_file(261 root_dir_path / 'top.yaml',262 """263 '*':264 - a265 - b266 """)267 _write_file(268 root_dir_path / 'a.yaml',269 """270 key: !!set271 1: null272 2: null273 3: null274 """)275 _write_file(276 root_dir_path / 'b.yaml',277 """278 key: !!set279 2: null280 4: null281 5: null282 """)283 (data, _) = ds.get_data('dummy', {}, '')284 # We expect that the lists have not been merged and the second285 # definition has replaced the first definition instead.286 self.assertEqual({1, 2, 3, 4, 5}, data['key'])287 # Now we repeat the test, but this time we set merge_sets to False.288 ds = YamlTargetSource({'root_dir': tmpdir, 'merge_sets': False})289 (data, _) = ds.get_data('dummy', {}, '')290 # Now the elements that are defined later should be appended, but291 # only those elements that were not already present.292 self.assertEqual({2, 4, 5}, data['key'])293 def test_config_template(self):294 """295 Test the 'template' configuration option.296 We cannot possibly test all template engines and the default Jinja297 engine is already covered by `test_jinja`, so we only test that setting298 ``template`` to ``None`` disables templating.299 """300 with TemporaryDirectory() as tmpdir:301 ds = YamlTargetSource({'root_dir': tmpdir, 'template': None})302 # We have to fill the configuration directory with files that the303 # data source can read.304 root_dir_path = pathlib.Path(tmpdir)305 _write_file(306 root_dir_path / 'top.yaml',307 """308 '*':309 - a310 """)311 _write_file(312 root_dir_path / 'a.yaml',313 """314 key: {{ data['input'] }}315 """)316 # As the file is not rendered by Jinja, we end up with invalid YAML,317 # so we expect an exception.318 with self.assertRaises(RuntimeError):319 ds.get_data('dummy', {'input': 1}, '1')320 # Now we fix the file so that it does not use Jinja and we expect321 # that we now get the data.322 _write_file(323 root_dir_path / 'a.yaml',324 """325 key: test326 """)327 self.assertEqual(328 {'key': 'test'}, ds.get_data('dummy', {'input': 1}, '1')[0])329 def test_config_template_config(self):330 """331 Test the 'template_config' configuration option.332 This test simply tests that the options are passed on to the template333 engine.334 """335 with TemporaryDirectory() as tmpdir:336 # The easiest thing that we can test is that replacing the variable337 # start and end strings (default '{{' and '}}') has the expected338 # effect.339 template_config = {340 'env': {341 'variable_start_string': '{!',342 'variable_end_string': '!}'}}343 ds = YamlTargetSource(344 {'root_dir': tmpdir, 'template_config': template_config})345 # We have to fill the configuration directory with files that the346 # data source can read.347 root_dir_path = pathlib.Path(tmpdir)348 _write_file(349 root_dir_path / 'top.yaml',350 """351 '*':352 - a353 """)354 _write_file(355 root_dir_path / 'a.yaml',356 """357 key: {! data['input'] !}358 """)359 self.assertEqual(360 {'key': 1}, ds.get_data('dummy', {'input': 1}, '1')[0])361 def test_deep_copy(self):362 """363 Test that modifying the data returned by ``get_data`` or modifying an364 object passed to the template context does not affect future calls or365 other templates.366 """367 with TemporaryDirectory() as tmpdir:368 ds = YamlTargetSource({'root_dir': tmpdir})369 # We have to fill the configuration directory with files that the370 # data source can read.371 root_dir_path = pathlib.Path(tmpdir)372 _write_file(373 root_dir_path / 'top.yaml',374 """375 '*':376 - a377 - b378 """)379 # We modify one of the context objects in the first template. This380 # change should not be visible in the second template.381 _write_file(382 root_dir_path / 'a.yaml',383 """384 {%- do data['key'].update({'abc': 'def'}) -%}385 a: {{ data['key']['abc'] }}386 """)387 _write_file(388 root_dir_path / 'b.yaml',389 """390 b: {{ data['key']['abc'] }}391 """)392 data, _ = ds.get_data('dummy', {'key': {'abc': 'abc'}}, '')393 self.assertEqual({'a': 'def', 'b': 'abc'}, data)394 # Now we modify the returned data and check that the (cached) data395 # returned by get_data does not change.396 data['other'] = 123397 data, _ = ds.get_data('dummy', {'key': {'abc': 'abc'}}, '')398 self.assertEqual({'a': 'def', 'b': 'abc'}, data)399 def test_get_instance(self):400 """401 Test that the data source can be instantiated via402 `vinegar.data_source.get_data_source`.403 """404 with TemporaryDirectory() as tmpdir:405 ds = vinegar.data_source.get_data_source(406 'yaml_target', {'root_dir': tmpdir})407 self.assertIsInstance(ds, YamlTargetSource)408 def test_include_merging(self):409 """410 Test that the precedence order is maintained when merging included411 files.412 """413 with TemporaryDirectory() as tmpdir:414 ds = YamlTargetSource({'root_dir': tmpdir})415 # We have to fill the configuration directory with files that the416 # data source can read.417 root_dir_path = pathlib.Path(tmpdir)418 _write_file(419 root_dir_path / 'top.yaml',420 """421 '*':422 - a423 'dum*':424 - c425 'dummy':426 - b427 """)428 _write_file(429 root_dir_path / 'a.yaml',430 """431 a_before_include: 1432 include:433 - a_inc434 a_after_include: 2435 """)436 _write_file(437 root_dir_path / 'a_inc.yaml',438 """439 a_before_include: 3440 a_after_include: 4441 a_from_include: 5442 """)443 _write_file(444 root_dir_path / 'b.yaml',445 """446 include:447 - b_inc448 b_after_include: 1449 """)450 _write_file(451 root_dir_path / 'b_inc.yaml',452 """453 b_after_include: 2454 b_from_include: 3455 """)456 _write_file(457 root_dir_path / 'c.yaml',458 """459 c_before_include: 1460 include:461 - c_inc462 """)463 _write_file(464 root_dir_path / 'c_inc.yaml',465 """466 c_before_include: 2467 c_from_include: 3468 """)469 verify_data = OrderedDict()470 verify_data['a_before_include'] = 3471 verify_data['a_after_include'] = 2472 verify_data['a_from_include'] = 5473 verify_data['c_before_include'] = 2474 verify_data['c_from_include'] = 3475 verify_data['b_after_include'] = 1476 verify_data['b_from_include'] = 3477 data = ds.get_data('dummy', {}, '')[0]478 self.assertEqual(verify_data, data)479 # We also want to check that the keys have the expected order.480 self.assertEqual(list(verify_data.keys()), list(data.keys()))481 def test_jinja(self):482 """483 Test that Jinja templates can be used in the top.yaml and in data files.484 """485 with TemporaryDirectory() as tmpdir:486 # We have to set the allow_empty_top option in order to avoid an487 # error message when the Jinja if statement does not match.488 ds = YamlTargetSource({'root_dir': tmpdir, 'allow_empty_top': True})489 # We have to fill the configuration directory with files that the490 # data source can read.491 root_dir_path = pathlib.Path(tmpdir)492 _write_file(493 root_dir_path / 'top.yaml',494 """495 # '*' would target all systems, but we only generate it when the496 # system ID matches497 {% if id == 'specific' %}498 '*':499 - a500 {% endif %}501 """)502 _write_file(503 root_dir_path / 'a.yaml',504 """505 key:506 {% for value in [1, 2, 3] %}507 - {{ value }}508 {% endfor %}509 """)510 self.assertEqual({}, ds.get_data('dummy', {}, '')[0])511 self.assertEqual(512 {'key': [1, 2, 3]}, ds.get_data('specific', {}, '')[0])513 def test_key_order(self):514 """515 Test that the key order is preserved (an ordered dict is used).516 This test is not extremely effective when running on Python >= 3.7 (or517 CPython 3.6) because all dicts are ordered in these versions, but we518 still include it for older versions of Python.519 """520 with TemporaryDirectory() as tmpdir:521 ds = YamlTargetSource({'root_dir': tmpdir})522 # We have to fill the configuration directory with files that the523 # data source can read.524 root_dir_path = pathlib.Path(tmpdir)525 _write_file(526 root_dir_path / 'top.yaml',527 """528 '*':529 - a530 """)531 _write_file(532 root_dir_path / 'a.yaml',533 """534 z: 1535 y: 2536 a: 3537 b: 4538 h: 5539 d: 6540 i: 7541 m: 8542 l: 9543 n: 10544 """)545 data = ds.get_data('dummy', {}, '')[0]546 keys = list(data.keys())547 values = list(data.values())548 self.assertEqual(549 ['z', 'y', 'a', 'b', 'h', 'd', 'i', 'm', 'l', 'n'], keys)550 self.assertEqual(list(range(1, 11)), values)551 def test_recursion_loop(self):552 """553 Test that recursive includes result in an exception.554 """555 with TemporaryDirectory() as tmpdir:556 ds = YamlTargetSource({'root_dir': tmpdir})557 # We have to fill the configuration directory with files that the558 # data source can read.559 root_dir_path = pathlib.Path(tmpdir)560 _write_file(561 root_dir_path / 'top.yaml',562 """563 '*':564 - a565 """)566 _write_file(567 root_dir_path / 'a.yaml',568 """569 include:570 - b571 some_key: abc572 """)573 _write_file(574 root_dir_path / 'b.yaml',575 """576 include:577 - a578 some_other_key: 123579 """)580 # We expect a RuntimeError because of the include loop.581 with self.assertRaises(RuntimeError) as assertion:582 ds.get_data('dummy', {}, '')583 self.assertTrue(584 str(assertion.exception).startswith('Recursion loop detected'))585 def test_template_context(self):586 """587 Test that the template gets the expected context objects.588 """589 with TemporaryDirectory() as tmpdir:590 ds = YamlTargetSource({'root_dir': tmpdir})591 # We have to fill the configuration directory with files that the592 # data source can read.593 root_dir_path = pathlib.Path(tmpdir)594 _write_file(595 root_dir_path / 'top.yaml',596 """597 '*':598 - a599 """)600 _write_file(601 root_dir_path / 'a.yaml',602 """603 id: {{ id }}604 data: {{ data.get('abc:def:ghi') }}605 """)606 # We use nested dicts for the input data so that we can test that607 # the data object is indeed a smart lookup dict.608 input_data = {'abc': {'def': {'ghi': 123}}}609 self.assertEqual(610 {'id': 'dummy', 'data': 123},611 ds.get_data('dummy', input_data, '1')[0])612 def test_top_targeting(self):613 """614 Tests that the targeting mechanism in ``top.yaml`` works.615 """616 with TemporaryDirectory() as tmpdir:617 ds = YamlTargetSource({'root_dir': tmpdir})618 # If there is no top file, we expect an exception when we try to get619 # data for a system.620 with self.assertRaises(FileNotFoundError):621 ds.get_data('dummy', {}, '')622 # We have to fill the configuration directory with files that the623 # data source can read.624 root_dir_path = pathlib.Path(tmpdir)625 app_dir_path = root_dir_path / 'app'626 app_dir_path.mkdir()627 common_dir_path = root_dir_path / 'common'628 common_dir_path.mkdir()629 domain_dir_path = root_dir_path / 'domain'630 domain_dir_path.mkdir()631 _write_file(632 root_dir_path / 'top.yaml',633 """634 '*':635 - common636 '*.example.com':637 - domain.com638 '*.example.net':639 - domain.net640 'db-* or database-*':641 - app.db642 'www.* or web.*':643 - app.web644 """)645 # We make a quick test before creating the state files, where we646 # expect a FileNotFoundError due to the data file missing.647 with self.assertRaises(FileNotFoundError):648 ds.get_data('dummy', {}, '')649 # We add the data file needed by all systems.650 _write_file(651 common_dir_path / 'init.yaml',652 """653 disks:654 root: 16G655 var: 100G656 """)657 # Now it should be possible to get data for a host that only matches658 # the '*' pattern.659 self.assertEqual(660 {661 'disks': {662 'root': '16G',663 'var': '100G'664 }665 },666 ds.get_data('dummy', {}, '')[0])667 # Getting data for one of the systems that needs additional files668 # should still fail.669 with self.assertRaises(FileNotFoundError):670 ds.get_data('myhost.example.com', {}, '')671 # We add the remaining data files.672 _write_file(673 domain_dir_path / 'com.yaml',674 """675 dnsdomain: example.com676 """)677 _write_file(678 domain_dir_path / 'net.yaml',679 """680 dnsdomain: example.net681 """)682 _write_file(683 app_dir_path / 'db.yaml',684 """685 disks:686 var: 1T687 """)688 _write_file(689 app_dir_path / 'web.yaml',690 """691 disks:692 home: 200G693 """)694 # Now we can test that the returned data is okay for other hosts.695 self.assertEqual(696 {697 'disks': {698 'root': '16G',699 'var': '100G'700 },701 'dnsdomain': 'example.com'702 },703 ds.get_data('foo.example.com', {}, '')[0])704 self.assertEqual(705 {706 'disks': {707 'root': '16G',708 'var': '1T'709 },710 'dnsdomain': 'example.com'711 },712 ds.get_data('db-1.example.com', {}, '')[0])713 self.assertEqual(714 {715 'disks': {716 'root': '16G',717 'var': '1T'718 },719 'dnsdomain': 'example.net'720 },721 ds.get_data('database-4.example.net', {}, '')[0])722 self.assertEqual(723 {724 'disks': {725 'home': '200G',726 'root': '16G',727 'var': '100G'728 },729 'dnsdomain': 'example.com'730 },731 ds.get_data('www.example.com', {}, '')[0])732def _write_file(path, text):733 """734 Write text to a file, cleaning the text with `inspect.cleandoc` first.735 We use this to generate configuration files for tests.736 """737 if isinstance(path, pathlib.PurePath):738 path = str(path)739 with open(path, mode='w') as file:...

Full Screen

Full Screen

CodeWriter.py

Source:CodeWriter.py Github

copy

Full Screen

1class CodeWriter:2 def __init__(self, file_name):3 self._file_name = file_name[:file_name.find('.')]4 self._write_file = open(self._file_name + '.asm', 'w')5 self._file_name = self._file_name.split('/').pop()6 self._true_counter = 17 self._end_counter = 18 self._return_counter = 19 def writeArithmetic(self, command):10 if command=='add':11 self._write_file.write('@SP\n')12 self._write_file.write('AM=M-1\n')13 self._write_file.write('D=M\n')14 self._write_file.write('@SP\n')15 self._write_file.write('AM=M-1\n')16 self._write_file.write('M=M+D\n')17 self._write_file.write('@SP\n')18 self._write_file.write('M=M+1\n')19 elif command=='sub':20 self._write_file.write('@SP\n')21 self._write_file.write('AM=M-1\n')22 self._write_file.write('D=M\n')23 self._write_file.write('@SP\n')24 self._write_file.write('AM=M-1\n')25 self._write_file.write('M=M-D\n')26 self._write_file.write('@SP\n')27 self._write_file.write('M=M+1\n')28 elif command=='neg':29 self._write_file.write('@SP\n')30 self._write_file.write('A=M-1\n')31 self._write_file.write('M=-M\n')32 elif command=='eq':33 self._write_file.write('@SP\n')34 self._write_file.write('AM=M-1\n')35 self._write_file.write('D=M\n')36 self._write_file.write('@TRUE_%d\n' % self._true_counter)37 self._write_file.write('D;JEQ\n')38 self._write_file.write('@SP\n')39 self._write_file.write('A=M\n')40 self._write_file.write('M=0\n')41 self._write_file.write('@END_%d\n' % self._end_counter)42 self._write_file.write('0;JMP\n')43 self._write_file.write('(TRUE_%d)\n' % self._true_counter)44 self._true_counter += 145 self._write_file.write('@SP\n')46 self._write_file.write('A=M\n')47 self._write_file.write('M=-1\n')48 self._write_file.write('(END_%d)\n' % self._end_counter)49 self._end_counter += 150 self._write_file.write('@SP\n')51 self._write_file.write('M=M+1\n')52 elif command=='gt':53 self._write_file.write('@SP\n')54 self._write_file.write('AM=M-1\n')55 self._write_file.write('D=M\n')56 self._write_file.write('@SP\n')57 self._write_file.write('AM=M-1\n')58 self._write_file.write('D=M-D\n')59 self._write_file.write('@TRUE_%d\n' % self._true_counter)60 self._write_file.write('D;JGT\n')61 self._write_file.write('@SP\n')62 self._write_file.write('A=M\n')63 self._write_file.write('M=0\n')64 self._write_file.write('@END_%d\n' % self._end_counter)65 self._write_file.write('0;JMP\n')66 self._write_file.write('(TRUE_%d)\n' % self._true_counter)67 self._true_counter += 168 self._write_file.write('@SP\n')69 self._write_file.write('A=M\n')70 self._write_file.write('M=-1\n')71 self._write_file.write('(END_%d)\n' % self._end_counter)72 self._end_counter += 173 self._write_file.write('@SP\n')74 self._write_file.write('M=M+1\n')75 elif command=='lt':76 self._write_file.write('@SP\n')77 self._write_file.write('AM=M-1\n')78 self._write_file.write('D=M\n')79 self._write_file.write('@SP\n')80 self._write_file.write('AM=M-1\n')81 self._write_file.write('D=M-D\n')82 self._write_file.write('@TRUE_%d\n' % self._true_counter)83 self._write_file.write('D;JLT\n')84 self._write_file.write('@SP\n')85 self._write_file.write('A=M\n')86 self._write_file.write('M=0\n')87 self._write_file.write('@END_%d\n' % self._end_counter)88 self._write_file.write('0;JMP\n')89 self._write_file.write('(TRUE_%d)\n' % self._true_counter)90 self._true_counter += 191 self._write_file.write('@SP\n')92 self._write_file.write('A=M\n')93 self._write_file.write('M=-1\n')94 self._write_file.write('(END_%d)\n' % self._end_counter)95 self._end_counter += 196 self._write_file.write('@SP\n')97 self._write_file.write('M=M+1\n')98 elif command=='and':99 self._write_file.write('@SP\n')100 self._write_file.write('AM=M-1\n')101 self._write_file.write('D=M\n')102 self._write_file.write('@SP\n')103 self._write_file.write('AM=M-1\n')104 self._write_file.write('M=M&D\n')105 self._write_file.write('@SP\n')106 self._write_file.write('M=M+1\n')107 elif command=='or':108 self._write_file.write('@SP\n')109 self._write_file.write('AM=M-1\n')110 self._write_file.write('D=M\n')111 self._write_file.write('@SP\n')112 self._write_file.write('AM=M-1\n')113 self._write_file.write('M=M|D\n')114 self._write_file.write('@SP\n')115 self._write_file.write('M=M+1\n')116 elif command=='not':117 self._write_file.write('@SP\n')118 self._write_file.write('A=M-1\n')119 self._write_file.write('M=!M\n')120 else:121 pass122 def writePushPop(self, command, segment, index):123 if command=='C_PUSH':124 if segment=='constant':125 self._write_file.write('@%s\n' % index)126 self._write_file.write('D=A\n')127 self._write_file.write('@SP\n')128 self._write_file.write('A=M\n')129 self._write_file.write('M=D\n')130 self._write_file.write('@SP\n')131 self._write_file.write('M=M+1\n')132 elif segment=='argument':133 self._write_file.write('@ARG\n')134 self._write_file.write('A=M\n')135 for i in range(int(index)):136 self._write_file.write('A=A+1\n')137 self._write_file.write('D=M\n')138 self._write_file.write('@SP\n')139 self._write_file.write('A=M\n')140 self._write_file.write('M=D\n')141 self._write_file.write('@SP\n')142 self._write_file.write('M=M+1\n')143 elif segment=='local':144 self._write_file.write('@LCL\n')145 self._write_file.write('A=M\n')146 for i in range(int(index)):147 self._write_file.write('A=A+1\n')148 self._write_file.write('D=M\n')149 self._write_file.write('@SP\n')150 self._write_file.write('A=M\n')151 self._write_file.write('M=D\n')152 self._write_file.write('@SP\n')153 self._write_file.write('M=M+1\n')154 elif segment=='static':155 self._write_file.write('@{}.{}\n'.format(self._file_name, index))156 self._write_file.write('D=M\n')157 self._write_file.write('@SP\n')158 self._write_file.write('A=M\n')159 self._write_file.write('M=D\n')160 self._write_file.write('@SP\n')161 self._write_file.write('M=M+1\n')162 elif segment=='pointer':163 if index=='0':164 self._write_file.write('@THIS\n')165 self._write_file.write('D=M\n')166 self._write_file.write('@SP\n')167 self._write_file.write('A=M\n')168 self._write_file.write('M=D\n')169 self._write_file.write('@SP\n')170 self._write_file.write('M=M+1\n')171 elif index=='1':172 self._write_file.write('@THAT\n')173 self._write_file.write('D=M\n')174 self._write_file.write('@SP\n')175 self._write_file.write('A=M\n')176 self._write_file.write('M=D\n')177 self._write_file.write('@SP\n')178 self._write_file.write('M=M+1\n')179 elif segment=='this':180 self._write_file.write('@THIS\n')181 self._write_file.write('A=M\n')182 for i in range(int(index)):183 self._write_file.write('A=A+1\n')184 self._write_file.write('D=M\n')185 self._write_file.write('@SP\n')186 self._write_file.write('A=M\n')187 self._write_file.write('M=D\n')188 self._write_file.write('@SP\n')189 self._write_file.write('M=M+1\n')190 elif segment=='that':191 self._write_file.write('@THAT\n')192 self._write_file.write('A=M\n')193 for i in range(int(index)):194 self._write_file.write('A=A+1\n')195 self._write_file.write('D=M\n')196 self._write_file.write('@SP\n')197 self._write_file.write('A=M\n')198 self._write_file.write('M=D\n')199 self._write_file.write('@SP\n')200 self._write_file.write('M=M+1\n')201 elif segment=='temp':202 self._write_file.write('@5\n')203 for i in range(int(index)):204 self._write_file.write('A=A+1\n')205 self._write_file.write('D=M\n')206 self._write_file.write('@SP\n')207 self._write_file.write('A=M\n')208 self._write_file.write('M=D\n')209 self._write_file.write('@SP\n')210 self._write_file.write('M=M+1\n')211 else:212 pass213 if command=='C_POP':214 if segment=='argument':215 self._write_file.write('@SP\n')216 self._write_file.write('M=M-1\n')217 self._write_file.write('A=M\n')218 self._write_file.write('D=M\n')219 self._write_file.write('@ARG\n')220 self._write_file.write('A=M\n')221 for i in range(int(index)):222 self._write_file.write('A=A+1\n')223 self._write_file.write('M=D\n')224 elif segment=='local':225 self._write_file.write('@SP\n')226 self._write_file.write('M=M-1\n')227 self._write_file.write('A=M\n')228 self._write_file.write('D=M\n')229 self._write_file.write('@LCL\n')230 self._write_file.write('A=M\n')231 for i in range(int(index)):232 self._write_file.write('A=A+1\n')233 self._write_file.write('M=D\n')234 elif segment=='static':235 self._write_file.write('@SP\n')236 self._write_file.write('M=M-1\n')237 self._write_file.write('A=M\n')238 self._write_file.write('D=M\n')239 self._write_file.write('@{}.{}\n'.format(self._file_name, index))240 self._write_file.write('M=D\n')241 elif segment=='pointer':242 if index=='0':243 self._write_file.write('@SP\n')244 self._write_file.write('M=M-1\n')245 self._write_file.write('A=M\n')246 self._write_file.write('D=M\n')247 self._write_file.write('@THIS\n')248 self._write_file.write('M=D\n')249 elif index=='1':250 self._write_file.write('@SP\n')251 self._write_file.write('M=M-1\n')252 self._write_file.write('A=M\n')253 self._write_file.write('D=M\n')254 self._write_file.write('@THAT\n')255 self._write_file.write('M=D\n')256 elif segment=='this':257 self._write_file.write('@SP\n')258 self._write_file.write('M=M-1\n')259 self._write_file.write('A=M\n')260 self._write_file.write('D=M\n')261 self._write_file.write('@THIS\n')262 self._write_file.write('A=M\n')263 for i in range(int(index)):264 self._write_file.write('A=A+1\n')265 self._write_file.write('M=D\n')266 elif segment=='that':267 self._write_file.write('@SP\n')268 self._write_file.write('M=M-1\n')269 self._write_file.write('A=M\n')270 self._write_file.write('D=M\n')271 self._write_file.write('@THAT\n')272 self._write_file.write('A=M\n')273 for i in range(int(index)):274 self._write_file.write('A=A+1\n')275 self._write_file.write('M=D\n')276 elif segment=='temp':277 self._write_file.write('@SP\n')278 self._write_file.write('M=M-1\n')279 self._write_file.write('A=M\n')280 self._write_file.write('D=M\n')281 self._write_file.write('@5\n')282 for i in range(int(index)):283 self._write_file.write('A=A+1\n')284 self._write_file.write('M=D\n')285 else:286 pass 287 288 def writeInit(self):289 self._write_file.write('@256\n')290 self._write_file.write('D=A\n')291 self._write_file.write('@SP\n')292 self._write_file.write('M=D\n')293 self.writeCall('Sys.init','0')294 def writeLabel(self, label):295 self._write_file.write('(%s)\n' % label)296 def writeGoto(self, label):297 self._write_file.write('@%s\n' % label)298 self._write_file.write('0;JMP\n')299 def writeIf(self, label):300 self._write_file.write('@SP\n')301 self._write_file.write('M=M-1\n')302 self._write_file.write('A=M\n')303 self._write_file.write('D=M\n')304 self._write_file.write('@%s\n' % label)305 self._write_file.write('D;JNE\n')306 def writeCall(self, functionName, numArgs):307 self._write_file.write('@RETURN_%d\n' % self._return_counter)308 self._write_file.write('D=A\n')309 self._write_file.write('@SP\n')310 self._write_file.write('A=M\n')311 self._write_file.write('M=D\n')312 self._write_file.write('@SP\n')313 self._write_file.write('M=M+1\n')314 self._write_file.write('@LCL\n')315 self._write_file.write('D=M\n')316 self._write_file.write('@SP\n')317 self._write_file.write('A=M\n')318 self._write_file.write('M=D\n')319 self._write_file.write('@SP\n')320 self._write_file.write('M=M+1\n')321 self._write_file.write('@ARG\n')322 self._write_file.write('D=M\n')323 self._write_file.write('@SP\n')324 self._write_file.write('A=M\n')325 self._write_file.write('M=D\n')326 self._write_file.write('@SP\n')327 self._write_file.write('M=M+1\n')328 self._write_file.write('@THIS\n')329 self._write_file.write('D=M\n')330 self._write_file.write('@SP\n')331 self._write_file.write('A=M\n')332 self._write_file.write('M=D\n')333 self._write_file.write('@SP\n')334 self._write_file.write('M=M+1\n')335 self._write_file.write('@THAT\n')336 self._write_file.write('D=M\n')337 self._write_file.write('@SP\n')338 self._write_file.write('A=M\n')339 self._write_file.write('M=D\n')340 self._write_file.write('@SP\n')341 self._write_file.write('M=M+1\n')342 self._write_file.write('@SP\n')343 self._write_file.write('D=M\n')344 for i in range(int(numArgs)+5):345 self._write_file.write('D=D-1\n')346 self._write_file.write('@ARG\n')347 self._write_file.write('M=D\n')348 self._write_file.write('@SP\n')349 self._write_file.write('D=M\n')350 self._write_file.write('@LCL\n')351 self._write_file.write('M=D\n')352 self.writeGoto(functionName)353 self._write_file.write('(RETURN_%d)\n' % self._return_counter)354 self._return_counter+=1355 def writeReturn(self):356 self._write_file.write('@LCL\n')357 self._write_file.write('D=M\n')358 self._write_file.write('@13\n')359 self._write_file.write('M=D\n')360 self._write_file.write('@5\n')361 self._write_file.write('D=D-A\n')362 self._write_file.write('A=D\n')363 self._write_file.write('D=M\n')364 self._write_file.write('@14\n')365 self._write_file.write('M=D\n')366 self._write_file.write('@SP\n')367 self._write_file.write('M=M-1\n')368 self._write_file.write('A=M\n')369 self._write_file.write('D=M\n')370 self._write_file.write('@ARG\n')371 self._write_file.write('A=M\n')372 self._write_file.write('M=D\n')373 self._write_file.write('@ARG\n')374 self._write_file.write('D=M+1\n')375 self._write_file.write('@SP\n')376 self._write_file.write('M=D\n')377 self._write_file.write('@13\n')378 self._write_file.write('M=M-1\n')379 self._write_file.write('D=M\n')380 self._write_file.write('A=D\n')381 self._write_file.write('D=M\n')382 self._write_file.write('@THAT\n')383 self._write_file.write('M=D\n')384 self._write_file.write('@13\n')385 self._write_file.write('M=M-1\n')386 self._write_file.write('D=M\n')387 self._write_file.write('A=D\n')388 self._write_file.write('D=M\n')389 self._write_file.write('@THIS\n')390 self._write_file.write('M=D\n')391 self._write_file.write('@13\n')392 self._write_file.write('M=M-1\n')393 self._write_file.write('D=M\n')394 self._write_file.write('A=D\n')395 self._write_file.write('D=M\n')396 self._write_file.write('@ARG\n')397 self._write_file.write('M=D\n')398 self._write_file.write('@13\n')399 self._write_file.write('M=M-1\n')400 self._write_file.write('D=M\n')401 self._write_file.write('A=D\n')402 self._write_file.write('D=M\n')403 self._write_file.write('@LCL\n')404 self._write_file.write('M=D\n')405 self._write_file.write('@14\n')406 self._write_file.write('A=M\n')407 self._write_file.write('0;JMP\n')408 def writeFunction(self, functionName, numLocals):409 self._write_file.write('(%s)\n' % functionName)410 for i in range(int(numLocals)):411 self._write_file.write('D=0\n')412 self._write_file.write('@SP\n')413 self._write_file.write('A=M\n')414 self._write_file.write('M=D\n')415 self._write_file.write('@SP\n')...

Full Screen

Full Screen

Tlatex.py

Source:Tlatex.py Github

copy

Full Screen

...80 ls_return.append(ls[i:i+j]) 81 #算上末尾的j+k 82 ls_return.append(ls[(n-1)*j:]) 83 return ls_return 84def _write_file(path,r):85 f=open(path,'a',encoding='utf8')86 f.write(r)87 f.flush()88 return89def _removef(outpath):90 lsd=['.aux','.log','.out','.xdv','.tex']91 base=os.path.split(outpath)92 basename=os.path.splitext(base[1])[0]93 for ex in lsd:94 try:95 mybsn=basename+ex96 path=os.path.join(base[0],mybsn)97 print(path)98 os.remove(path)99 except Exception as e:100 pass101 return102def sqlTolatex(text,oupf,mtype='kindle',pyin=True):103 title=set()104 #outpath='/home/chen/public/shiwen/'+oupf+'.tex'105 outpath=oupf+'.tex'106 if os.path.exists(outpath):107 os.remove(outpath)108 with open(outpath,'a') as f:109 f.writelines(latexs[mtype])110 f.flush()111 try:112 for li in text[0]:113 if li[1]+li[2] not in title:114 title.add(li[1]+li[2])115 sct=section%li[1]+'\n\n'116 _write_file(outpath,sct)117 118 conn=li[2]+'\n\n'119 _write_file(outpath,conn)120 content=li[3].strip().replace('\n','\n\n')+'\n\n'121 if pyin:122 #_write_file(outpath,'\begin{pinyinscope}'+'\n')123 _write_file(outpath,"\\begin{pinyinscope}"+"\n")124 #_write_file(outpath,'\saohao'+'\n')125 _write_file(outpath,content)126 #_write_file(outpath,'\xiaosaohao'+'\n')127 #_write_file(outpath,'\xiaosaohao'+'\n')128 _write_file(outpath,'\end{pinyinscope}'+'\n')129 else:130 _write_file(outpath,content)131 yw=li[4].strip()132 if len(yw)>0:133 yw=yw.replace('\n','\n\n')+'\n\n'134 _write_file(outpath,r'\subsection{译文}')135 _write_file(outpath,yw)136 zx=li[5].strip()137 if len(zx)>0:138 zx=zx.replace('\n','\n\n')+'\n\n'139 _write_file(outpath,r'\subsection{注释}')140 _write_file(outpath,zx)141 sx=li[6].strip()142 if len(sx) > 0:143 sx=sx.replace('、\n','、')144 sx=sx.replace('\n','\n\n')+'\n\n'145 _write_file(outpath,r'\subsection{赏析}')146 _write_file(outpath,sx)147 148 _write_file(outpath,end)149 os.system('xelatex -no-pdf -interaction=nonstopmode %s' %outpath)150 os.system('xelatex -interaction=nonstopmode %s' %outpath)151 _removef(outpath)152 except Exception as e:153 print(e)154 pass155 156def Gushi2Pdf_author(author,mtype='article',pyin=True):157 """158 Parameters:159 author:按作者160 mtype:分为article,kindle161 pyin: 主体部分是否要标拼音162 ywT:是否要翻译部分163 """ 164 165 sqll="select * from gushiwenI where author like '%%%s%%'"%author166 #sqll="select * from gushiwen"167 cur.execute(sqll)168 c=[]169 c.append(cur.fetchall())170 d=set(c)171 text=list(d)172 sqlTolatex(text,author,mtype,pyin)173 os.system('mv %s.pdf /home/chen/public/shiwen/' %author)174 return175def Gushi2Pdf_note(note,mtype='article',pyin=True,ywT=True):176 """177 Parameters:178 note:按分类179 mtype:分为article,kindle180 pyin: 主体部分是否要标拼音181 ywT:是否要翻译部分182 """ 183 184 sqll="select * from gushiwenI where note like '%%%s%%'"%note185 #sqll="select * from gushiwen"186 cur.execute(sqll)187 c=[]188 c.append(cur.fetchall())189 d=set(c)190 text=list(d)191 sqlTolatex(text,author,mtype,pyin)192 os.system('mv %s.pdf /home/chen/public/shiwen/' %note)193 return194def sqlTolatex_guwen(text,oupf,mtype='article',pyin=True,ywT=True,cnT=True):195 title=set()196 #outpath='/home/chen/public/shiwen/'+oupf+'.tex'197 outpath=oupf+'.tex'198 if os.path.exists(outpath):199 os.remove(outpath)200 with open(outpath,'a') as f:201 f.writelines(latexs[mtype])202 f.flush()203 204 try:205 for li in text[0]:206 if li[0] not in title:207 title.add(li[0])208 sct=section%li[0]+'\n\n'209 _write_file(outpath,sct)210 211 content=li[1].strip().replace('\n','\n\n')+'\n\n'212 if cnT:213 _write_file(outpath,r'\subsection{%s}'%li)214 if pyin:215 #_write_file(outpath,'\begin{pinyinscope}'+'\n')216 _write_file(outpath,"\\begin{pinyinscope}"+"\n")217 #_write_file(outpath,'\saohao'+'\n')218 _write_file(outpath,content)219 #_write_file(outpath,'\xiaosaohao'+'\n')220 #_write_file(outpath,'\xiaosaohao'+'\n')221 _write_file(outpath,'\end{pinyinscope}'+'\n')222 else:223 _write_file(outpath,content)224 225 yw=li[2].strip().replace('译文及注释','').replace('译文','').replace('全屏','')226 if len(yw)>0 and ywT:227 yw=yw.replace('\n','\n\n')+'\n\n'228 _write_file(outpath,r'\subsection{译文}')229 _write_file(outpath,yw)230 231 _write_file(outpath,end)232 os.system('xelatex -no-pdf -interaction=nonstopmode %s' %outpath)233 os.system('xelatex -interaction=nonstopmode %s' %outpath)234 _removef(outpath)235 except Exception as e:236 print(e)237 pass238 239def Guwen2Pdf_book(book,mtype='article',pyin=True,ywT=True,cnT=True):240 """241 Parameters:242 book:书名243 mtype:分为article,kindle244 pyin: 主体部分是否要标拼音245 cnT:是否要主体章节部分内容246 ywT:是否要翻译部分247 """248 249 sqll="select charpter,content,zhushi from Guwen where book like '%%%s%%'"%book250 #sqll="select * from gushiwen"251 cur.execute(sqll)252 c=[]253 c.append(cur.fetchall())254 d=set(c)255 text=list(d)256 sqlTolatex_guwen(text,book,mtype,pyin,ywT,cnT)257 os.system('mv %s.pdf /home/chen/public/shiwen/' %book)258 return259def sqlTolatex_split(text,oupf,mtype='kindle',pyin=True,ywT=True,zxT=True,sxT=True):260 outpath=oupf+'.tex'261 if os.path.exists(outpath):262 os.remove(outpath)263 with open(outpath,'a') as f:264 f.writelines(latexs[mtype])265 f.flush()266 try:267 for li in text:268 sct=section%li[0]+'\n\n'269 _write_file(outpath,sct)270 271 conn=li[1]+'\n\n'272 _write_file(outpath,conn)273 content=li[2].strip().replace('\n','\n\n')+'\n\n'274 if pyin:275 _write_file(outpath,"\\begin{pinyinscope}"+"\n")276 _write_file(outpath,content)277 _write_file(outpath,'\end{pinyinscope}'+'\n')278 else:279 _write_file(outpath,content)280 yw=li[3].strip()281 if (len(yw)>0)&ywT:282 yw=yw.replace('\n','\n\n')+'\n\n'283 _write_file(outpath,r'\subsection{译文}')284 _write_file(outpath,yw)285 zx=li[4].strip()286 if (len(zx)>0)&zxT:287 zx=zx.replace('\n','\n\n')+'\n\n'288 _write_file(outpath,r'\subsection{注释}')289 _write_file(outpath,zx)290 sx=li[5].strip()291 if (len(sx) > 0)&sxT:292 sx=sx.replace('、\n','、')293 sx=sx.replace('\n','\n\n')+'\n\n'294 _write_file(outpath,r'\subsection{赏析}')295 _write_file(outpath,sx)296 297 _write_file(outpath,end)298 os.system('xelatex -no-pdf -interaction=nonstopmode %s' %outpath)299 os.system('xelatex -interaction=nonstopmode %s' %outpath)300 _removef(outpath)301 except Exception as e:302 print(e)303 pass304def Gushi2Pdf_AuthorSplit(author,mtype='article',pyin=True,ywT=True,zxT=True,sxT=True,split=2):305 sqll="select title,author,content,yiwen,zhus,shangxi from gushiwenI where author like '%%%s%%'"%author306 cur.execute(sqll)307 df=cur.fetchall()308 df=set(df)309 text=list(df)310 title=set()311 allt=[]#最终的文本312 for li in text:313 if li[1]+li[2] not in title:314 title.add(li[1]+li[2])315 allt.append(li)316 allsplit=div_list(allt,split)317 for i,twx in enumerate(allsplit):318 out=author+str(i+1).zfill(2)319 sqlTolatex_split(twx,out,mtype,pyin,ywT,zxT,sxT)320 os.system('mv %s.pdf /home/chen/public/shiwen/' %out)321 return322def Gushi2Pdf_NoteSplit(note,mtype='article',pyin=True,ywT=True,zxT=True,sxT=True,split=2):323 #kk={'note':'','author':''}324 sqll="select title,author,content,yiwen,zhus,shangxi from gushiwenI where note like '%%%s%%'"%note325 cur.execute(sqll)326 df=cur.fetchall()327 df=set(df)328 text=list(df)329 title=set()330 allt=[]#最终的文本331 for li in text:332 if li[1]+li[2] not in title:333 title.add(li[1]+li[2])334 allt.append(li)335 allsplit=div_list(allt,split)336 for i,twx in enumerate(allsplit):337 out=note+str(i+1).zfill(2)338 sqlTolatex_split(twx,out,mtype,pyin,ywT,zxT,sxT)339 os.system('mv %s.pdf /home/chen/public/shiwen/' %out)340 return341def sqlTolatex_guwensplit(text,oupf,mtype='article',pyin=True,ywT=True,cnT=True):342 outpath=oupf+'.tex'343 if os.path.exists(outpath):344 os.remove(outpath)345 with open(outpath,'a') as f:346 f.writelines(latexs[mtype])347 f.flush()348 349 try:350 for li in text:351 sct=section%li[0]+'\n\n'352 _write_file(outpath,sct)353 354 content=li[1].strip().replace('\n','\n\n')+'\n\n'355 if cnT:356 _write_file(outpath,r'\subsection{%s}'%li)357 if pyin:358 _write_file(outpath,"\\begin{pinyinscope}"+"\n")359 _write_file(outpath,content)360 _write_file(outpath,'\end{pinyinscope}'+'\n')361 else:362 _write_file(outpath,content)363 364 yw=li[2].strip().replace('译文及注释','').replace('译文','').replace('全屏','')365 if len(yw)>0 and ywT:366 yw=yw.replace('\n','\n\n')+'\n\n'367 _write_file(outpath,r'\subsection{译文}')368 _write_file(outpath,yw)369 370 _write_file(outpath,end)371 os.system('xelatex -no-pdf -interaction=nonstopmode %s' %outpath)372 os.system('xelatex -interaction=nonstopmode %s' %outpath)373 _removef(outpath)374 except Exception as e:375 print(e)376 pass 377 378def Guwen2Pdf_bookSplit(book,mtype='article',pyin=True,ywT=True,cnT=True,split=1):379 #kk={'note':'','author':''}380 sqll="select charpter,content,zhushi from Guwen where book like '%%%s%%'"%book381 cur.execute(sqll)382 df=cur.fetchall()383 df=set(df)384 text=list(df)...

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 green 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