|
19 | 19 | Tests for `jsonpath_ng_ext` module.
|
20 | 20 | """
|
21 | 21 |
|
22 |
| -import unittest |
23 |
| - |
24 | 22 | from jsonpath_ng import jsonpath # For setting the global auto_id_field flag
|
25 | 23 |
|
26 | 24 | from jsonpath_ng.ext import parser
|
| 25 | +from jsonpath_ng.exceptions import JsonPathParserError |
| 26 | + |
| 27 | +import pytest |
27 | 28 |
|
28 | 29 |
|
29 | 30 | # Example from https://docs.pytest.org/en/7.1.x/example/parametrize.html#a-quick-port-of-testscenarios
|
30 | 31 | def pytest_generate_tests(metafunc):
|
| 32 | + if metafunc.cls is None: |
| 33 | + return |
31 | 34 | idlist = []
|
32 | 35 | argvalues = []
|
33 | 36 | for scenario in metafunc.cls.scenarios:
|
@@ -373,243 +376,10 @@ def test_fields_value(self, string, data, target):
|
373 | 376 | else:
|
374 | 377 | assert target == result[0].value
|
375 | 378 |
|
376 |
| -# NOTE(sileht): copy of tests/test_jsonpath.py |
377 |
| -# to ensure we didn't break jsonpath_ng |
378 |
| - |
379 |
| - |
380 |
| -class TestJsonPath(unittest.TestCase): |
381 |
| - """Tests of the actual jsonpath functionality """ |
382 |
| - |
383 |
| - # |
384 |
| - # Check that the data value returned is good |
385 |
| - # |
386 |
| - def check_cases(self, test_cases): |
387 |
| - # Note that just manually building an AST would avoid this dep and |
388 |
| - # isolate the tests, but that would suck a bit |
389 |
| - # Also, we coerce iterables, etc, into the desired target type |
390 |
| - |
391 |
| - for string, data, target in test_cases: |
392 |
| - print('parse("%s").find(%s) =?= %s' % (string, data, target)) |
393 |
| - result = parser.parse(string).find(data) |
394 |
| - if isinstance(target, list): |
395 |
| - assert [r.value for r in result] == target |
396 |
| - elif isinstance(target, set): |
397 |
| - assert set([r.value for r in result]) == target |
398 |
| - else: |
399 |
| - assert result.value == target |
400 |
| - |
401 |
| - def test_fields_value(self): |
402 |
| - jsonpath.auto_id_field = None |
403 |
| - self.check_cases([('foo', {'foo': 'baz'}, ['baz']), |
404 |
| - ('foo,baz', {'foo': 1, 'baz': 2}, [1, 2]), |
405 |
| - ('@foo', {'@foo': 1}, [1]), |
406 |
| - ('*', {'foo': 1, 'baz': 2}, set([1, 2]))]) |
407 |
| - |
408 |
| - jsonpath.auto_id_field = 'id' |
409 |
| - self.check_cases([('*', {'foo': 1, 'baz': 2}, set([1, 2, '`this`']))]) |
410 | 379 |
|
411 |
| - def test_root_value(self): |
412 |
| - jsonpath.auto_id_field = None |
413 |
| - self.check_cases([ |
414 |
| - ('$', {'foo': 'baz'}, [{'foo': 'baz'}]), |
415 |
| - ('foo.$', {'foo': 'baz'}, [{'foo': 'baz'}]), |
416 |
| - ('foo.$.foo', {'foo': 'baz'}, ['baz']), |
417 |
| - ]) |
418 |
| - |
419 |
| - def test_this_value(self): |
420 |
| - jsonpath.auto_id_field = None |
421 |
| - self.check_cases([ |
422 |
| - ('`this`', {'foo': 'baz'}, [{'foo': 'baz'}]), |
423 |
| - ('foo.`this`', {'foo': 'baz'}, ['baz']), |
424 |
| - ('foo.`this`.baz', {'foo': {'baz': 3}}, [3]), |
425 |
| - ]) |
426 |
| - |
427 |
| - def test_index_value(self): |
428 |
| - self.check_cases([ |
429 |
| - ('[0]', [42], [42]), |
430 |
| - ('[5]', [42], []), |
431 |
| - ('[2]', [34, 65, 29, 59], [29]) |
432 |
| - ]) |
433 |
| - |
434 |
| - def test_slice_value(self): |
435 |
| - self.check_cases([('[*]', [1, 2, 3], [1, 2, 3]), |
436 |
| - ('[*]', range(1, 4), [1, 2, 3]), |
437 |
| - ('[1:]', [1, 2, 3, 4], [2, 3, 4]), |
438 |
| - ('[:2]', [1, 2, 3, 4], [1, 2])]) |
439 |
| - |
440 |
| - # Funky slice hacks |
441 |
| - self.check_cases([ |
442 |
| - ('[*]', 1, [1]), # This is a funky hack |
443 |
| - ('[0:]', 1, [1]), # This is a funky hack |
444 |
| - ('[*]', {'foo': 1}, [{'foo': 1}]), # This is a funky hack |
445 |
| - ('[*].foo', {'foo': 1}, [1]), # This is a funky hack |
446 |
| - ]) |
447 |
| - |
448 |
| - def test_child_value(self): |
449 |
| - self.check_cases([('foo.baz', {'foo': {'baz': 3}}, [3]), |
450 |
| - ('foo.baz', {'foo': {'baz': [3]}}, [[3]]), |
451 |
| - ('foo.baz.bizzle', {'foo': {'baz': {'bizzle': 5}}}, |
452 |
| - [5])]) |
453 |
| - |
454 |
| - def test_descendants_value(self): |
455 |
| - self.check_cases([ |
456 |
| - ('foo..baz', {'foo': {'baz': 1, 'bing': {'baz': 2}}}, [1, 2]), |
457 |
| - ('foo..baz', {'foo': [{'baz': 1}, {'baz': 2}]}, [1, 2]), |
458 |
| - ]) |
459 |
| - |
460 |
| - def test_parent_value(self): |
461 |
| - self.check_cases([('foo.baz.`parent`', {'foo': {'baz': 3}}, |
462 |
| - [{'baz': 3}]), |
463 |
| - ('foo.`parent`.foo.baz.`parent`.baz.bizzle', |
464 |
| - {'foo': {'baz': {'bizzle': 5}}}, [5])]) |
465 |
| - |
466 |
| - def test_hyphen_key(self): |
467 |
| - # NOTE(sileht): hyphen is now a operator |
468 |
| - # so to use it has key we must escape it with quote |
469 |
| - # self.check_cases([('foo.bar-baz', {'foo': {'bar-baz': 3}}, [3]), |
470 |
| - # ('foo.[bar-baz,blah-blah]', |
471 |
| - # {'foo': {'bar-baz': 3, 'blah-blah': 5}}, |
472 |
| - # [3, 5])]) |
473 |
| - self.check_cases([('foo."bar-baz"', {'foo': {'bar-baz': 3}}, [3]), |
474 |
| - ('foo.["bar-baz","blah-blah"]', |
475 |
| - {'foo': {'bar-baz': 3, 'blah-blah': 5}}, |
476 |
| - [3, 5])]) |
477 |
| - # self.assertRaises(lexer.JsonPathLexerError, self.check_cases, |
478 |
| - # [('foo.-baz', {'foo': {'-baz': 8}}, [8])]) |
479 |
| - |
480 |
| - # |
481 |
| - # Check that the paths for the data are correct. |
482 |
| - # FIXME: merge these tests with the above, since the inputs are the same |
483 |
| - # anyhow |
484 |
| - # |
485 |
| - def check_paths(self, test_cases): |
486 |
| - # Note that just manually building an AST would avoid this dep and |
487 |
| - # isolate the tests, but that would suck a bit |
488 |
| - # Also, we coerce iterables, etc, into the desired target type |
489 |
| - |
490 |
| - for string, data, target in test_cases: |
491 |
| - print('parse("%s").find(%s).paths =?= %s' % (string, data, target)) |
492 |
| - result = parser.parse(string).find(data) |
493 |
| - if isinstance(target, list): |
494 |
| - assert [str(r.full_path) for r in result] == target |
495 |
| - elif isinstance(target, set): |
496 |
| - assert set([str(r.full_path) for r in result]) == target |
497 |
| - else: |
498 |
| - assert str(result.path) == target |
499 |
| - |
500 |
| - def test_filter_with_filtering(self): |
501 |
| - data = {"foos": [{"id": 1, "name": "first"}, {"id": 2, "name": "second"}]} |
502 |
| - result = parser.parse('$.foos[?(@.name=="second")]').filter( |
503 |
| - lambda _: True, data |
504 |
| - ) |
505 |
| - names = [item["name"] for item in result["foos"]] |
506 |
| - assert "second" not in names |
507 |
| - |
508 |
| - def test_fields_paths(self): |
509 |
| - jsonpath.auto_id_field = None |
510 |
| - self.check_paths([('foo', {'foo': 'baz'}, ['foo']), |
511 |
| - ('foo,baz', {'foo': 1, 'baz': 2}, ['foo', 'baz']), |
512 |
| - ('*', {'foo': 1, 'baz': 2}, set(['foo', 'baz']))]) |
513 |
| - |
514 |
| - jsonpath.auto_id_field = 'id' |
515 |
| - self.check_paths([('*', {'foo': 1, 'baz': 2}, |
516 |
| - set(['foo', 'baz', 'id']))]) |
517 |
| - |
518 |
| - def test_root_paths(self): |
519 |
| - jsonpath.auto_id_field = None |
520 |
| - self.check_paths([ |
521 |
| - ('$', {'foo': 'baz'}, ['$']), |
522 |
| - ('foo.$', {'foo': 'baz'}, ['$']), |
523 |
| - ('foo.$.foo', {'foo': 'baz'}, ['foo']), |
524 |
| - ]) |
525 |
| - |
526 |
| - def test_this_paths(self): |
527 |
| - jsonpath.auto_id_field = None |
528 |
| - self.check_paths([ |
529 |
| - ('`this`', {'foo': 'baz'}, ['`this`']), |
530 |
| - ('foo.`this`', {'foo': 'baz'}, ['foo']), |
531 |
| - ('foo.`this`.baz', {'foo': {'baz': 3}}, ['foo.baz']), |
532 |
| - ]) |
533 |
| - |
534 |
| - def test_index_paths(self): |
535 |
| - self.check_paths([('[0]', [42], ['[0]']), |
536 |
| - ('[2]', [34, 65, 29, 59], ['[2]'])]) |
537 |
| - |
538 |
| - def test_slice_paths(self): |
539 |
| - self.check_paths([('[*]', [1, 2, 3], ['[0]', '[1]', '[2]']), |
540 |
| - ('[1:]', [1, 2, 3, 4], ['[1]', '[2]', '[3]'])]) |
541 |
| - |
542 |
| - def test_child_paths(self): |
543 |
| - self.check_paths([('foo.baz', {'foo': {'baz': 3}}, ['foo.baz']), |
544 |
| - ('foo.baz', {'foo': {'baz': [3]}}, ['foo.baz']), |
545 |
| - ('foo.baz.bizzle', {'foo': {'baz': {'bizzle': 5}}}, |
546 |
| - ['foo.baz.bizzle'])]) |
547 |
| - |
548 |
| - def test_descendants_paths(self): |
549 |
| - self.check_paths([('foo..baz', {'foo': {'baz': 1, 'bing': {'baz': 2}}}, |
550 |
| - ['foo.baz', 'foo.bing.baz'])]) |
551 |
| - |
552 |
| - # |
553 |
| - # Check the "auto_id_field" feature |
554 |
| - # |
555 |
| - def test_fields_auto_id(self): |
556 |
| - jsonpath.auto_id_field = "id" |
557 |
| - self.check_cases([('foo.id', {'foo': 'baz'}, ['foo']), |
558 |
| - ('foo.id', {'foo': {'id': 'baz'}}, ['baz']), |
559 |
| - ('foo,baz.id', {'foo': 1, 'baz': 2}, ['foo', 'baz']), |
560 |
| - ('*.id', |
561 |
| - {'foo': {'id': 1}, |
562 |
| - 'baz': 2}, |
563 |
| - set(['1', 'baz']))]) |
564 |
| - |
565 |
| - def test_root_auto_id(self): |
566 |
| - jsonpath.auto_id_field = 'id' |
567 |
| - self.check_cases([ |
568 |
| - ('$.id', {'foo': 'baz'}, ['$']), # This is a wonky case that is |
569 |
| - # not that interesting |
570 |
| - ('foo.$.id', {'foo': 'baz', 'id': 'bizzle'}, ['bizzle']), |
571 |
| - ('foo.$.baz.id', {'foo': 4, 'baz': 3}, ['baz']), |
572 |
| - ]) |
573 |
| - |
574 |
| - def test_this_auto_id(self): |
575 |
| - jsonpath.auto_id_field = 'id' |
576 |
| - self.check_cases([ |
577 |
| - ('id', {'foo': 'baz'}, ['`this`']), # This is, again, a wonky case |
578 |
| - # that is not that interesting |
579 |
| - ('foo.`this`.id', {'foo': 'baz'}, ['foo']), |
580 |
| - ('foo.`this`.baz.id', {'foo': {'baz': 3}}, ['foo.baz']), |
581 |
| - ]) |
582 |
| - |
583 |
| - def test_index_auto_id(self): |
584 |
| - jsonpath.auto_id_field = "id" |
585 |
| - self.check_cases([('[0].id', [42], ['[0]']), |
586 |
| - ('[2].id', [34, 65, 29, 59], ['[2]'])]) |
587 |
| - |
588 |
| - def test_slice_auto_id(self): |
589 |
| - jsonpath.auto_id_field = "id" |
590 |
| - self.check_cases([('[*].id', [1, 2, 3], ['[0]', '[1]', '[2]']), |
591 |
| - ('[1:].id', [1, 2, 3, 4], ['[1]', '[2]', '[3]'])]) |
592 |
| - |
593 |
| - def test_child_auto_id(self): |
594 |
| - jsonpath.auto_id_field = "id" |
595 |
| - self.check_cases([('foo.baz.id', {'foo': {'baz': 3}}, ['foo.baz']), |
596 |
| - ('foo.baz.id', {'foo': {'baz': [3]}}, ['foo.baz']), |
597 |
| - ('foo.baz.id', {'foo': {'id': 'bizzle', 'baz': 3}}, |
598 |
| - ['bizzle.baz']), |
599 |
| - ('foo.baz.id', {'foo': {'baz': {'id': 'hi'}}}, |
600 |
| - ['foo.hi']), |
601 |
| - ('foo.baz.bizzle.id', |
602 |
| - {'foo': {'baz': {'bizzle': 5}}}, |
603 |
| - ['foo.baz.bizzle'])]) |
604 |
| - |
605 |
| - def test_descendants_auto_id(self): |
606 |
| - jsonpath.auto_id_field = "id" |
607 |
| - self.check_cases([('foo..baz.id', |
608 |
| - {'foo': { |
609 |
| - 'baz': 1, |
610 |
| - 'bing': { |
611 |
| - 'baz': 2 |
612 |
| - } |
613 |
| - }}, |
614 |
| - ['foo.baz', |
615 |
| - 'foo.bing.baz'])]) |
| 380 | +def test_invalid_hyphenation_in_key(): |
| 381 | + # This test is almost copied-and-pasted directly from `test_jsonpath.py`. |
| 382 | + # However, the parsers generate different exceptions for this syntax error. |
| 383 | + # This discrepancy needs to be resolved. |
| 384 | + with pytest.raises(JsonPathParserError): |
| 385 | + parser.parse("foo.-baz") |
0 commit comments