From f3734e2328c8a41992d0057291702e3b1cc2baa9 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Fri, 25 Aug 2023 11:52:33 +0100 Subject: [PATCH] Adjust supported PHP version --- .github/bin/composer.sh | 16 ------- .github/bin/hhvm.sh | 5 --- .github/workflows/tests.yml | 68 +++++------------------------ .gitignore | 1 + CHANGELOG.md | 5 +++ README.rst | 2 +- composer.json | 69 +++++++++++++++--------------- phpunit.xml.dist | 9 +++- src/SyntaxErrorException.php | 2 +- tests/ComplianceTest.php | 21 +++------ tests/EnvTest.php | 6 +-- tests/FnDispatcherTest.php | 8 ++-- tests/LexerTest.php | 10 ++--- tests/ParserTest.php | 61 +++++++------------------- tests/SyntaxErrorExceptionTest.php | 8 ++-- tests/TreeCompilerTest.php | 8 ++-- tests/TreeInterpreterTest.php | 10 ++--- tests/UtilsTest.php | 34 +++++++-------- 18 files changed, 122 insertions(+), 221 deletions(-) delete mode 100755 .github/bin/composer.sh delete mode 100755 .github/bin/hhvm.sh diff --git a/.github/bin/composer.sh b/.github/bin/composer.sh deleted file mode 100755 index a872006..0000000 --- a/.github/bin/composer.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)" -php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" -ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" -if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then - >&2 echo 'ERROR: Invalid installer checksum' - rm composer-setup.php - exit 1 -else - php composer-setup.php --install-dir="/usr/bin" --filename=composer - RESULT=$? - rm composer-setup.php - composer config platform.php 5.6.50 - exit $RESULT -fi diff --git a/.github/bin/hhvm.sh b/.github/bin/hhvm.sh deleted file mode 100755 index a0448d6..0000000 --- a/.github/bin/hhvm.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -echo "deb https://dl.hhvm.com/ubuntu $(lsb_release -sc)-lts-$1 main" >> /etc/apt/sources.list -apt-get update -apt-get --allow-downgrades --reinstall install hhvm/$(lsb_release -sc)-lts-$1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ed9aa0e..bf7024a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,15 +7,15 @@ on: jobs: tests_linux: name: PHP ${{ matrix.php }} Linux - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: matrix: - php: ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -27,32 +27,23 @@ jobs: - name: Setup Problem Matchers run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - name: Install PHP 5/7 Dependencies - uses: nick-invision/retry@v1 + - name: Install PHP Dependencies + uses: nick-invision/retry@v2 with: timeout_minutes: 5 max_attempts: 5 command: composer update --no-interaction --no-progress - if: "matrix.php < 8" - - - name: Install PHP 8 Dependencies - uses: nick-invision/retry@v1 - with: - timeout_minutes: 5 - max_attempts: 5 - command: composer update --no-interaction --no-progress --ignore-platform-req=php - if: "matrix.php >= 8" - name: Execute PHPUnit run: vendor/bin/phpunit tests_windows: name: PHP ${{ matrix.php }} Windows - runs-on: windows-2019 + runs-on: windows-2022 strategy: matrix: - php: ['5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] + php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3'] steps: - name: Configure Git @@ -61,7 +52,7 @@ jobs: git config --global core.eol lf - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -73,51 +64,12 @@ jobs: - name: Setup Problem Matchers run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - name: Install PHP 5/7 Dependencies - uses: nick-invision/retry@v1 + - name: Install PHP Dependencies + uses: nick-invision/retry@v2 with: timeout_minutes: 5 max_attempts: 5 command: composer update --no-interaction --no-progress - if: "matrix.php < 8" - - - name: Install PHP 8 Dependencies - uses: nick-invision/retry@v1 - with: - timeout_minutes: 5 - max_attempts: 5 - command: composer update --no-interaction --no-progress --ignore-platform-req=php - if: "matrix.php >= 8" - name: Execute PHPUnit run: vendor\bin\phpunit.bat - - test_hhvm: - name: HHVM ${{ matrix.hhvm }} - runs-on: ubuntu-16.04 - - strategy: - matrix: - hhvm: ["3.15", "3.18", "3.21", "3.24"] - - steps: - - name: Checkout Code - uses: actions/checkout@v2 - - - name: Install HHVM - shell: bash - run: sudo .github/bin/hhvm.sh ${{ matrix.hhvm }} - - - name: Install Composer - shell: bash - run: sudo .github/bin/composer.sh - - - name: Install Dependencies - uses: nick-invision/retry@v1 - with: - timeout_minutes: 5 - max_attempts: 5 - command: composer update --no-interaction --no-progress - - - name: Execute PHPUnit - run: hhvm vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 34a9206..3964314 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.phpunit.result.cache vendor composer.lock phpunit.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index d97dffb..ef7f380 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 2.7.0 - UPCOMING + +* Drop support for HHVM and PHP earlier than 7.2.5. +* Add support for PHP 8.1, 8.2, and 8.3. + ## 2.6.0 - 2020-07-31 * Support for PHP 8.0. diff --git a/README.rst b/README.rst index b65ee46..bef8db4 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ jmespath.php JMESPath (pronounced "jaymz path") allows you to declaratively specify how to extract elements from a JSON document. *jmespath.php* allows you to use -JMESPath in PHP applications with PHP data structures. It requires PHP 5.4 or +JMESPath in PHP applications with PHP data structures. It requires PHP 7.2.5 or greater and can be installed through `Composer `_ using the ``mtdowling/jmespath.php`` package. diff --git a/composer.json b/composer.json index 6b70068..b4c37c1 100644 --- a/composer.json +++ b/composer.json @@ -1,39 +1,38 @@ { - "name": "mtdowling/jmespath.php", - "description": "Declaratively specify how to extract elements from a JSON document", - "keywords": ["json", "jsonpath"], - "license": "MIT", - - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - - "require": { - "php": "^5.4 || ^7.0 || ^8.0", - "symfony/polyfill-mbstring": "^1.17" - }, - - "require-dev": { - "composer/xdebug-handler": "^1.4 || ^2.0", - "phpunit/phpunit": "^4.8.36 || ^7.5.15" - }, - - "autoload": { - "psr-4": { - "JmesPath\\": "src/" + "name": "mtdowling/jmespath.php", + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": ["json", "jsonpath"], + "license": "MIT", + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": ["src/JmesPath.php"] }, - "files": ["src/JmesPath.php"] - }, - - "bin": ["bin/jp.php"], - - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" + "bin": ["bin/jp.php"], + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } } - } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0e48023..ccaffa3 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,6 +1,11 @@ - + diff --git a/src/SyntaxErrorException.php b/src/SyntaxErrorException.php index 68683d0..b9e376e 100644 --- a/src/SyntaxErrorException.php +++ b/src/SyntaxErrorException.php @@ -16,7 +16,7 @@ public function __construct( array $token, $expression ) { - $message = "Syntax error at character {$token['pos']}\n" + $message = sprintf("Syntax error at character %d\n", max($token['pos'], 0)) . $expression . "\n" . str_repeat(' ', max($token['pos'], 0)) . "^\n"; $message .= !is_array($expectedTypesOrMessage) ? $expectedTypesOrMessage diff --git a/tests/ComplianceTest.php b/tests/ComplianceTest.php index 92e86ac..fe672e5 100644 --- a/tests/ComplianceTest.php +++ b/tests/ComplianceTest.php @@ -10,13 +10,13 @@ class ComplianceTest extends TestCase { private static $path; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { self::$path = __DIR__ . '/../../compiled'; array_map('unlink', glob(self::$path . '/jmespath_*.php')); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { array_map('unlink', glob(self::$path . '/jmespath_*.php')); } @@ -34,7 +34,7 @@ public function testPassesCompliance( $case, $compiled, $asAssoc - ) { + ): void { $evalResult = null; $failed = false; $failureMsg = ''; @@ -61,8 +61,8 @@ public function testPassesCompliance( $file = __DIR__ . '/compliance/' . $file . '.json'; $failure .= "\n{$compiledStr}php bin/jp.php --file {$file} --suite {$suite} --case {$case}\n\n" - . "Result: " . $this->prettyJson($evalResult) . "\n\n" - . "Expected: " . $this->prettyJson($result) . "\n\n"; + . "Result: " . json_encode($evalResult, JSON_PRETTY_PRINT) . "\n\n" + . "Expected: " . json_encode($result, JSON_PRETTY_PRINT) . "\n\n"; $failure .= 'Associative? ' . var_export($asAssoc, true) . "\n\n"; if (!$error && $failed) { @@ -78,7 +78,7 @@ public function testPassesCompliance( ); } - public function complianceProvider() + public static function complianceProvider(): array { $cases = []; @@ -126,13 +126,4 @@ private function convertAssoc($data) return $data; } } - - private function prettyJson($json) - { - if (defined('JSON_PRETTY_PRINT')) { - return json_encode($json, JSON_PRETTY_PRINT); - } - - return json_encode($json); - } } diff --git a/tests/EnvTest.php b/tests/EnvTest.php index 5b0d016..73631d2 100644 --- a/tests/EnvTest.php +++ b/tests/EnvTest.php @@ -7,20 +7,20 @@ class EnvTest extends TestCase { - public function testSearchesInput() + public function testSearchesInput(): void { $data = ['foo' => 123]; $this->assertEquals(123, Env::search('foo', $data)); $this->assertEquals(123, Env::search('foo', $data)); } - public function testSearchesWithFunction() + public function testSearchesWithFunction(): void { $data = ['foo' => 123]; $this->assertEquals(123, \JmesPath\search('foo', $data)); } - public function testCleansCompileDir() + public function testCleansCompileDir(): void { $dir = sys_get_temp_dir(); $runtime = new CompilerRuntime($dir); diff --git a/tests/FnDispatcherTest.php b/tests/FnDispatcherTest.php index 3ee48e7..dc22df6 100644 --- a/tests/FnDispatcherTest.php +++ b/tests/FnDispatcherTest.php @@ -6,7 +6,7 @@ class fnDispatcherTest extends TestCase { - public function testConvertsToString() + public function testConvertsToString(): void { $fn = new FnDispatcher(); $this->assertEquals('foo', $fn('to_string', ['foo'])); @@ -22,7 +22,7 @@ public function testConvertsToString() class _TestStringClass { - public function __toString() + public function __toString(): string { return 'foo'; } @@ -30,12 +30,12 @@ public function __toString() class _TestJsonStringClass implements \JsonSerializable { - public function __toString() + public function __toString(): string { return 'no!'; } - public function jsonSerialize() + public function jsonSerialize(): string { return 'foo'; } diff --git a/tests/LexerTest.php b/tests/LexerTest.php index 43094a9..3c0ed2b 100644 --- a/tests/LexerTest.php +++ b/tests/LexerTest.php @@ -10,7 +10,7 @@ */ class LexerTest extends TestCase { - public function inputProvider() + public static function inputProvider(): array { return [ ['0', 'number'], @@ -47,14 +47,14 @@ public function inputProvider() /** * @dataProvider inputProvider */ - public function testTokenizesInput($input, $type) + public function testTokenizesInput(string $input, string $type): void { $l = new Lexer(); $tokens = $l->tokenize($input); $this->assertEquals($tokens[0]['type'], $type); } - public function testTokenizesJsonLiterals() + public function testTokenizesJsonLiterals(): void { $l = new Lexer(); $tokens = $l->tokenize('`null`, `false`, `true`, `"abc"`, `"ab\\"c"`,' @@ -69,7 +69,7 @@ public function testTokenizesJsonLiterals() $this->assertSame(-0.5, $tokens[14]['value']); } - public function testTokenizesJsonNumbers() + public function testTokenizesJsonNumbers(): void { $l = new Lexer(); $tokens = $l->tokenize('`10`, `1.2`, `-10.20e-10`, `1.2E+2`'); @@ -79,7 +79,7 @@ public function testTokenizesJsonNumbers() $this->assertEquals(120, $tokens[6]['value']); } - public function testCanWorkWithElidedJsonLiterals() + public function testCanWorkWithElidedJsonLiterals(): void { $l = new Lexer(); $tokens = $l->tokenize('`foo`'); diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 82fd411..58c8301 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -3,6 +3,7 @@ use JmesPath\Lexer; use JmesPath\Parser; +use JmesPath\SyntaxErrorException; use PHPUnit\Framework\TestCase; /** @@ -11,61 +12,29 @@ class ParserTest extends TestCase { /** - * @expectedException \JmesPath\SyntaxErrorException - * @expectedExceptionMessage Syntax error at character 0 - */ - public function testMatchesFirstTokens() - { - $p = new Parser(new Lexer()); - $p->parse('.bar'); - } - - /** - * @expectedException \JmesPath\SyntaxErrorException - * @expectedExceptionMessage Syntax error at character 1 - */ - public function testThrowsSyntaxErrorForInvalidSequence() - { - $p = new Parser(new Lexer()); - $p->parse('a,'); - } - - /** - * @expectedException \JmesPath\SyntaxErrorException - * @expectedExceptionMessage Syntax error at character 2 + * @dataProvider invalidExpressionProvider */ - public function testMatchesAfterFirstToken() + public function testHandlesInvalidExpressions(string $expr, string $msg): void { $p = new Parser(new Lexer()); - $p->parse('a.,'); - } - /** - * @expectedException \JmesPath\SyntaxErrorException - * @expectedExceptionMessage Unexpected "eof" token - */ - public function testHandlesEmptyExpressions() - { - (new Parser(new Lexer()))->parse(''); - } + $this->expectException(SyntaxErrorException::class); + $this->expectExceptionMessage($msg); - /** - * @dataProvider invalidExpressionProvider - * @expectedException \JmesPath\SyntaxErrorException - * @expectedExceptionMessag Syntax error at character 0 - */ - public function testHandlesInvalidExpressions($expr) - { - (new Parser(new Lexer()))->parse($expr); + $p->parse($expr); } - public function invalidExpressionProvider() + public static function invalidExpressionProvider(): array { return [ - ['='], - ['<'], - ['>'], - ['|'] + ['', 'Unexpected "eof" token'], + ['.bar', 'Syntax error at character 0'], + ['a,', 'Syntax error at character 1'], + ['a.,', 'Syntax error at character 2'], + ['=', 'Syntax error at character 0'], + ['<', 'Syntax error at character 0'], + ['>', 'Syntax error at character 0'], + ['|', 'Syntax error at character 0'] ]; } } diff --git a/tests/SyntaxErrorExceptionTest.php b/tests/SyntaxErrorExceptionTest.php index 139fdfb..0580cc2 100644 --- a/tests/SyntaxErrorExceptionTest.php +++ b/tests/SyntaxErrorExceptionTest.php @@ -9,7 +9,7 @@ */ class SyntaxErrorExceptionTest extends TestCase { - public function testCreatesWithNoArray() + public function testCreatesWithNoArray(): void { $e = new SyntaxErrorException( 'Found comma', @@ -22,10 +22,10 @@ public function testCreatesWithNoArray() ^ Found comma EOT; - $this->assertContains($expected, $e->getMessage()); + $this->assertStringContainsString($expected, $e->getMessage()); } - public function testCreatesWithArray() + public function testCreatesWithArray(): void { $e = new SyntaxErrorException( ['dot' => true, 'eof' => true], @@ -38,6 +38,6 @@ public function testCreatesWithArray() ^ Expected one of the following: dot, eof; found comma "," EOT; - $this->assertContains($expected, $e->getMessage()); + $this->assertStringContainsString($expected, $e->getMessage()); } } diff --git a/tests/TreeCompilerTest.php b/tests/TreeCompilerTest.php index 99fdbb9..1ba82d8 100644 --- a/tests/TreeCompilerTest.php +++ b/tests/TreeCompilerTest.php @@ -9,7 +9,7 @@ */ class TreeCompilerTest extends TestCase { - public function testCreatesSourceCode() + public function testCreatesSourceCode(): void { $t = new TreeCompiler(); $source = $t->visit( @@ -17,8 +17,8 @@ public function testCreatesSourceCode() 'testing', 'foo' ); - $this->assertContains('assertContains('$value = isset($value->{\'foo\'}) ? $value->{\'foo\'} : null;', $source); - $this->assertContains('$value = isset($value[\'foo\']) ? $value[\'foo\'] : null;', $source); + $this->assertStringContainsString('assertStringContainsString('$value = isset($value->{\'foo\'}) ? $value->{\'foo\'} : null;', $source); + $this->assertStringContainsString('$value = isset($value[\'foo\']) ? $value[\'foo\'] : null;', $source); } } diff --git a/tests/TreeInterpreterTest.php b/tests/TreeInterpreterTest.php index f9eb92d..ee66a67 100644 --- a/tests/TreeInterpreterTest.php +++ b/tests/TreeInterpreterTest.php @@ -10,7 +10,7 @@ */ class TreeInterpreterTest extends TestCase { - public function testReturnsNullWhenMergingNonArray() + public function testReturnsNullWhenMergingNonArray(): void { $t = new TreeInterpreter(); $this->assertNull($t->visit([ @@ -24,7 +24,7 @@ public function testReturnsNullWhenMergingNonArray() ])); } - public function testWorksWithArrayObjectAsObject() + public function testWorksWithArrayObjectAsObject(): void { $runtime = new AstRuntime(); $this->assertEquals('baz', $runtime('foo.bar', new \ArrayObject([ @@ -32,7 +32,7 @@ public function testWorksWithArrayObjectAsObject() ]))); } - public function testWorksWithArrayObjectAsArray() + public function testWorksWithArrayObjectAsArray(): void { $runtime = new AstRuntime(); $this->assertEquals('baz', $runtime('foo[0].bar', new \ArrayObject([ @@ -40,7 +40,7 @@ public function testWorksWithArrayObjectAsArray() ]))); } - public function testWorksWithArrayProjections() + public function testWorksWithArrayProjections(): void { $runtime = new AstRuntime(); $this->assertEquals( @@ -55,7 +55,7 @@ public function testWorksWithArrayProjections() ); } - public function testWorksWithObjectProjections() + public function testWorksWithObjectProjections(): void { $runtime = new AstRuntime(); $this->assertEquals( diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index b09978d..0380b37 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -6,7 +6,7 @@ class UtilsTest extends TestCase { - public function typeProvider() + public static function typeProvider(): array { return [ ['a', 'string'], @@ -29,20 +29,19 @@ public function typeProvider() /** * @dataProvider typeProvider */ - public function testGetsTypes($given, $type) + public function testGetsTypes($given, string $type): void { $this->assertEquals($type, Utils::type($given)); } - /** - * @expectedException \InvalidArgumentException - */ - public function testThrowsForInvalidArg() + public function testThrowsForInvalidArg(): void { + $this->expectException(\InvalidArgumentException::class); + Utils::type(new _TestClass()); } - public function isArrayProvider() + public static function isArrayProvider(): array { return [ [[], true], @@ -58,12 +57,12 @@ public function isArrayProvider() /** * @dataProvider isArrayProvider */ - public function testChecksIfArray($given, $result) + public function testChecksIfArray($given, bool $result) { $this->assertSame($result, Utils::isArray($given)); } - public function isObjectProvider() + public static function isObjectProvider(): array { return [ [[], true], @@ -79,12 +78,12 @@ public function isObjectProvider() /** * @dataProvider isObjectProvider */ - public function testChecksIfObject($given, $result) + public function testChecksIfObject($given, $result): void { $this->assertSame($result, Utils::isObject($given)); } - public function testHasStableSort() + public function testHasStableSort(): void { $data = [new _TestStr(), new _TestStr(), 0, 10, 2]; $result = Utils::stableSort($data, function ($a, $b) { @@ -99,14 +98,14 @@ public function testHasStableSort() $this->assertEquals(0, $result[4]); } - public function testSlicesArrays() + public function testSlicesArrays(): void { $this->assertEquals([3, 2, 1], Utils::slice([1, 2, 3], null, null, -1)); $this->assertEquals([1, 3], Utils::slice([1, 2, 3], null, null, 2)); $this->assertEquals([2, 3], Utils::slice([1, 2, 3], 1)); } - public function testSlicesStrings() + public function testSlicesStrings(): void { $this->assertEquals('cba', Utils::slice('abc', null, null, -1)); $this->assertEquals('ac', Utils::slice('abc', null, null, 2)); @@ -116,15 +115,16 @@ public function testSlicesStrings() class _TestClass implements \ArrayAccess { - public function offsetExists($offset) {} + public function offsetExists($offset): bool {} + #[\ReturnTypeWillChange] public function offsetGet($offset) {} - public function offsetSet($offset, $value) {} - public function offsetUnset($offset) {} + public function offsetSet($offset, $value): void {} + public function offsetUnset($offset): void {} } class _TestStr { - public function __toString() + public function __toString(): string { return '100'; }