From 43a171b221b462bdca9851d84d765a029064e714 Mon Sep 17 00:00:00 2001 From: jNullj <15849761+jNullj@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:37:44 +0300 Subject: [PATCH 1/5] Add PythonVersionFromToml Added new shield per issue #9410 The shield display required python versions for packages based on pyproject.toml --- .../python-version-from-toml.service.js | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 services/python/python-version-from-toml.service.js diff --git a/services/python/python-version-from-toml.service.js b/services/python/python-version-from-toml.service.js new file mode 100644 index 0000000000000..0dfd23be0bc42 --- /dev/null +++ b/services/python/python-version-from-toml.service.js @@ -0,0 +1,65 @@ +import Joi from 'joi' +import BaseTomlService from '../../core/base-service/base-toml.js' +import { optionalUrl } from '../validators.js' + +const queryParamSchema = Joi.object({ + tomlFilePath: optionalUrl.required(), +}).required() + +const schema = Joi.object({ + project: Joi.object({ + 'requires-python': Joi.string().required(), + }).required(), +}).required() + +const documentation = `Shows the required python version for a package based on the values in the requires-python field in the pyproject.toml \n +a URL of the toml is required, please note that when linking to files in github or similar sites, provide URL to raw file, for example: + +Use https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml \n +And not https://github.com/numpy/numpy/blob/main/pyproject.toml +` + +class PythonVersionFromToml extends BaseTomlService { + static category = 'platform-support' + + static route = { + base: '', + pattern: 'python/required-version-toml', + queryParamSchema, + } + + static examples = [ + { + title: 'Python Required Version TOML', + namedParams: {}, + queryParams: { + tomlFilePath: + 'https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml', + }, + staticPreview: this.render({ requiresPythonString: '>=3.9' }), + documentation, + }, + ] + + static defaultBadgeData = { label: 'python' } + + static render({ requiresPythonString }) { + // we only show requries-python as is + // for more info read the following issues: + // https://github.com/badges/shields/issues/9410 + // https://github.com/badges/shields/issues/5551 + return { + message: requiresPythonString, + color: 'blue', + } + } + + async handle(namedParams, { tomlFilePath }) { + const tomlData = await this._requestToml({ url: tomlFilePath, schema }) + const requiresPythonString = tomlData.project['requires-python'] + + return this.constructor.render({ requiresPythonString }) + } +} + +export { PythonVersionFromToml } From 97b418d958955c53a86d7d20fa641c577a87d01c Mon Sep 17 00:00:00 2001 From: jNullj <15849761+jNullj@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:38:13 +0300 Subject: [PATCH 2/5] Add tests for PythonVersionFromToml --- .../python/python-version-from-toml.tester.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 services/python/python-version-from-toml.tester.js diff --git a/services/python/python-version-from-toml.tester.js b/services/python/python-version-from-toml.tester.js new file mode 100644 index 0000000000000..24ac9594558ca --- /dev/null +++ b/services/python/python-version-from-toml.tester.js @@ -0,0 +1,21 @@ +import Joi from 'joi' +import { createServiceTester } from '../tester.js' +export const t = await createServiceTester() + +const isCommaSeparatedPythonVersions = Joi.string().regex( + /^\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?)(?:\s*,\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?))*\s*$/, +) + +t.create('python versions (valid)') + .get( + '/python/required-version-toml.json?tomlFilePath=https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml', + ) + .expectBadge({ label: 'python', message: isCommaSeparatedPythonVersions }) + +t.create( + 'python versions - valid toml with missing python-requires field (invalid)', +) + .get( + '/python/required-version-toml.json?tomlFilePath=https://raw.githubusercontent.com/django/django/main/pyproject.toml', + ) + .expectBadge({ label: 'python', message: 'invalid response data' }) From 05702d5162c3fba16c74462ed39240e1ecbb1980 Mon Sep 17 00:00:00 2001 From: jNullj <15849761+jNullj@users.noreply.github.com> Date: Fri, 25 Aug 2023 20:17:40 +0300 Subject: [PATCH 3/5] Improve docs for tests regex --- services/python/python-version-from-toml.tester.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/python/python-version-from-toml.tester.js b/services/python/python-version-from-toml.tester.js index 24ac9594558ca..cdb6fb43e15ef 100644 --- a/services/python/python-version-from-toml.tester.js +++ b/services/python/python-version-from-toml.tester.js @@ -3,6 +3,11 @@ import { createServiceTester } from '../tester.js' export const t = await createServiceTester() const isCommaSeparatedPythonVersions = Joi.string().regex( + // This should test for PEP440 + // Accepted values are one or more Version specifiers as defined at https://peps.python.org/pep-0440/#version-specifiers + // Some strings might include spaces, those are valid, values are comma seperated + // Versions should fit the version scheme https://peps.python.org/pep-0440/#version-scheme + // This is based on the example in PEP440 at https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions /^\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?)(?:\s*,\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?))*\s*$/, ) From e2ecbf5ff2a83f419307f752c453460be345b027 Mon Sep 17 00:00:00 2001 From: jNullj <15849761+jNullj@users.noreply.github.com> Date: Tue, 5 Sep 2023 00:10:17 +0300 Subject: [PATCH 4/5] Improve title and description Rename and updated description to bring into focus that only PEP 621 complaint pyproject.toml files are supported. Solves review https://github.com/badges/shields/pull/9516#discussion_r1310648023 --- services/python/python-version-from-toml.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/python/python-version-from-toml.service.js b/services/python/python-version-from-toml.service.js index 0dfd23be0bc42..f05fe0d2968dd 100644 --- a/services/python/python-version-from-toml.service.js +++ b/services/python/python-version-from-toml.service.js @@ -12,7 +12,7 @@ const schema = Joi.object({ }).required(), }).required() -const documentation = `Shows the required python version for a package based on the values in the requires-python field in the pyproject.toml \n +const documentation = `Shows the required python version for a package based on the values in the requires-python field in PEP 621 compliant pyproject.toml \n a URL of the toml is required, please note that when linking to files in github or similar sites, provide URL to raw file, for example: Use https://raw.githubusercontent.com/numpy/numpy/main/pyproject.toml \n @@ -30,7 +30,7 @@ class PythonVersionFromToml extends BaseTomlService { static examples = [ { - title: 'Python Required Version TOML', + title: 'Python Version from PEP 621 TOML', namedParams: {}, queryParams: { tomlFilePath: From b3de30f1859274749dc0e513be77ecd2b63ddfcd Mon Sep 17 00:00:00 2001 From: jNullj <15849761+jNullj@users.noreply.github.com> Date: Wed, 6 Sep 2023 00:34:52 +0300 Subject: [PATCH 5/5] replace complex regex with @renovate/pep440 solves review https://github.com/badges/shields/pull/9516#discussion_r1310648881 --- .../python/python-version-from-toml.tester.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/services/python/python-version-from-toml.tester.js b/services/python/python-version-from-toml.tester.js index cdb6fb43e15ef..b1a0cdeaf16e8 100644 --- a/services/python/python-version-from-toml.tester.js +++ b/services/python/python-version-from-toml.tester.js @@ -1,15 +1,16 @@ import Joi from 'joi' +import pep440 from '@renovate/pep440' import { createServiceTester } from '../tester.js' export const t = await createServiceTester() -const isCommaSeparatedPythonVersions = Joi.string().regex( - // This should test for PEP440 - // Accepted values are one or more Version specifiers as defined at https://peps.python.org/pep-0440/#version-specifiers - // Some strings might include spaces, those are valid, values are comma seperated - // Versions should fit the version scheme https://peps.python.org/pep-0440/#version-scheme - // This is based on the example in PEP440 at https://peps.python.org/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions - /^\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?)(?:\s*,\s*(?:(?:===|!=|<=|>=|<|>)\s*)?((?:(?:\d+!)?(?:\d+(?:\.\d+)*))(?:(?:[abc]|rc)\d+)?(?:\.post\d+)?(?:\.dev\d+)?))*\s*$/, -) +const validatePep440 = (value, helpers) => { + if (!pep440.validRange(value)) { + return helpers.error('any.invalid') + } + return value +} + +const isCommaSeparatedPythonVersions = Joi.string().custom(validatePep440) t.create('python versions (valid)') .get(