Compare commits
2 Commits
master
...
requires-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
332a496e84 | ||
|
|
5f28ac34cc |
15
package-lock.json
generated
15
package-lock.json
generated
@@ -6460,6 +6460,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@renovate/pep440": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@renovate/pep440/-/pep440-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-UJR4qqM5l1b84iXd9SS8nPOFfxCWDgL3uOhhYwb15DgC1j8wf5ZLoyTcVUhnCLXG770c999PNLJEUl4wRscvhQ==",
|
||||||
|
"requires": {
|
||||||
|
"xregexp": "4.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"xregexp": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-IyMa7SVe9FyT4WbQVW3b95mTLVceHhLEezQ02+QMvmIqDnKTxk0MLWIQPSW2MXAr1zQb+9yvwYhcyQULneh3wA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@samverschueren/stream-to-observable": {
|
"@samverschueren/stream-to-observable": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz",
|
||||||
|
|||||||
@@ -23,10 +23,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hapi/joi": "^17.1.1",
|
"@hapi/joi": "^17.1.1",
|
||||||
|
"@renovate/pep440": "^0.4.1",
|
||||||
"@sentry/node": "^5.24.2",
|
"@sentry/node": "^5.24.2",
|
||||||
|
"@shields_io/camp": "^18.0.0",
|
||||||
|
"badge-maker": "file:badge-maker",
|
||||||
"bytes": "^3.1.0",
|
"bytes": "^3.1.0",
|
||||||
"camelcase": "^5.3.1",
|
"camelcase": "^5.3.1",
|
||||||
"@shields_io/camp": "^18.0.0",
|
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"check-node-version": "^4.0.3",
|
"check-node-version": "^4.0.3",
|
||||||
@@ -39,7 +41,6 @@
|
|||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"fast-xml-parser": "^3.17.4",
|
"fast-xml-parser": "^3.17.4",
|
||||||
"fsos": "^1.1.6",
|
"fsos": "^1.1.6",
|
||||||
"badge-maker": "file:badge-maker",
|
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"graphql": "^14.7.0",
|
"graphql": "^14.7.0",
|
||||||
"graphql-tag": "^2.11.0",
|
"graphql-tag": "^2.11.0",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ const schema = Joi.object({
|
|||||||
// https://github.com/badges/shields/issues/2022
|
// https://github.com/badges/shields/issues/2022
|
||||||
license: Joi.string().allow(''),
|
license: Joi.string().allow(''),
|
||||||
classifiers: Joi.array().items(Joi.string()).required(),
|
classifiers: Joi.array().items(Joi.string()).required(),
|
||||||
|
requires_python: Joi.alternatives().try(Joi.string(), Joi.allow(null)),
|
||||||
}).required(),
|
}).required(),
|
||||||
releases: Joi.object()
|
releases: Joi.object()
|
||||||
.pattern(
|
.pattern(
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const { satisfies } = require('@renovate/pep440')
|
||||||
|
|
||||||
|
// This list tracks "Active Python Releases" at
|
||||||
|
// https://www.python.org/downloads/ which means it needs to be manually updated
|
||||||
|
// every two years or so. It would be good to find a machine-readable version of
|
||||||
|
// this listing (like we do with PHP) so it does not need to be updated manually.
|
||||||
|
const ACTIVE_PYTHON_VERSIONS = ['2.7', '3.5', '3.6', '3.7', '3.8']
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Django versions will be specified in the form major.minor
|
Django versions will be specified in the form major.minor
|
||||||
trying to sort with `semver.compare` will throw e.g:
|
trying to sort with `semver.compare` will throw e.g:
|
||||||
@@ -93,10 +101,52 @@ function getPackageFormats(packageData) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getPythonVersionsFromClassifiers(packageData) {
|
||||||
|
let versions = parseClassifiers(
|
||||||
|
packageData,
|
||||||
|
/^Programming Language :: Python :: ([\d.]+)$/
|
||||||
|
)
|
||||||
|
|
||||||
|
// If no versions are found yet, check "X :: Only" as a fallback.
|
||||||
|
if (versions.length === 0) {
|
||||||
|
versions.push(
|
||||||
|
...parseClassifiers(
|
||||||
|
packageData,
|
||||||
|
/^Programming Language :: Python :: (\d+) :: Only$/
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only show v2 if eg. v2.4 does not appear.
|
||||||
|
// See https://github.com/badges/shields/pull/489 for more.
|
||||||
|
;['2', '3'].forEach(majorVersion => {
|
||||||
|
if (versions.some(v => v.startsWith(`${majorVersion}.`))) {
|
||||||
|
versions = versions.filter(v => v !== majorVersion)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return versions.sort()
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPythonVersionsFromPythonRequires(packageData) {
|
||||||
|
const {
|
||||||
|
info: { requires_python: pythonRequires },
|
||||||
|
} = packageData
|
||||||
|
if (pythonRequires) {
|
||||||
|
return ACTIVE_PYTHON_VERSIONS.filter(activeVersion =>
|
||||||
|
satisfies(activeVersion, pythonRequires)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
parseClassifiers,
|
parseClassifiers,
|
||||||
parseDjangoVersionString,
|
parseDjangoVersionString,
|
||||||
sortDjangoVersions,
|
sortDjangoVersions,
|
||||||
getLicenses,
|
getLicenses,
|
||||||
getPackageFormats,
|
getPackageFormats,
|
||||||
|
getPythonVersionsFromClassifiers,
|
||||||
|
getPythonVersionsFromPythonRequires,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ const {
|
|||||||
sortDjangoVersions,
|
sortDjangoVersions,
|
||||||
getLicenses,
|
getLicenses,
|
||||||
getPackageFormats,
|
getPackageFormats,
|
||||||
|
getPythonVersionsFromPythonRequires,
|
||||||
} = require('./pypi-helpers')
|
} = require('./pypi-helpers')
|
||||||
|
|
||||||
const classifiersFixture = {
|
const classifiersFixture = {
|
||||||
@@ -168,4 +169,13 @@ describe('PyPI helpers', function () {
|
|||||||
},
|
},
|
||||||
}).expect({ hasWheel: false, hasEgg: true })
|
}).expect({ hasWheel: false, hasEgg: true })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test(getPythonVersionsFromPythonRequires, () => {
|
||||||
|
given({ info: { requires_python: null } }).expect(undefined)
|
||||||
|
given({
|
||||||
|
info: {
|
||||||
|
requires_python: '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*',
|
||||||
|
},
|
||||||
|
}).expect(['2.7', '3.5', '3.6', '3.7', '3.8'])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const PypiBase = require('./pypi-base')
|
const PypiBase = require('./pypi-base')
|
||||||
const { parseClassifiers } = require('./pypi-helpers')
|
const {
|
||||||
|
getPythonVersionsFromClassifiers,
|
||||||
|
getPythonVersionsFromPythonRequires,
|
||||||
|
} = require('./pypi-helpers')
|
||||||
|
|
||||||
module.exports = class PypiPythonVersions extends PypiBase {
|
module.exports = class PypiPythonVersions extends PypiBase {
|
||||||
static get category() {
|
static get category() {
|
||||||
@@ -18,7 +21,7 @@ module.exports = class PypiPythonVersions extends PypiBase {
|
|||||||
title: 'PyPI - Python Version',
|
title: 'PyPI - Python Version',
|
||||||
pattern: ':packageName',
|
pattern: ':packageName',
|
||||||
namedParams: { packageName: 'Django' },
|
namedParams: { packageName: 'Django' },
|
||||||
staticPreview: this.render({ versions: ['3.5', '3.6', '3.7'] }),
|
staticPreview: this.render({ versions: ['3.5', '3.6', '3.7', '3.8'] }),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -28,17 +31,9 @@ module.exports = class PypiPythonVersions extends PypiBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static render({ versions }) {
|
static render({ versions }) {
|
||||||
const versionSet = new Set(versions)
|
if (versions.length) {
|
||||||
// We only show v2 if eg. v2.4 does not appear.
|
|
||||||
// See https://github.com/badges/shields/pull/489 for more.
|
|
||||||
;['2', '3'].forEach(majorVersion => {
|
|
||||||
if (Array.from(versions).some(v => v.startsWith(`${majorVersion}.`))) {
|
|
||||||
versionSet.delete(majorVersion)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (versionSet.size) {
|
|
||||||
return {
|
return {
|
||||||
message: Array.from(versionSet).sort().join(' | '),
|
message: versions.join(' | '),
|
||||||
color: 'blue',
|
color: 'blue',
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -52,19 +47,10 @@ module.exports = class PypiPythonVersions extends PypiBase {
|
|||||||
async handle({ egg }) {
|
async handle({ egg }) {
|
||||||
const packageData = await this.fetch({ egg })
|
const packageData = await this.fetch({ egg })
|
||||||
|
|
||||||
const versions = parseClassifiers(
|
const versions =
|
||||||
packageData,
|
getPythonVersionsFromClassifiers(packageData) ||
|
||||||
/^Programming Language :: Python :: ([\d.]+)$/
|
getPythonVersionsFromPythonRequires(packageData) ||
|
||||||
)
|
[]
|
||||||
// If no versions are found yet, check "X :: Only" as a fallback.
|
|
||||||
if (versions.length === 0) {
|
|
||||||
versions.push(
|
|
||||||
...parseClassifiers(
|
|
||||||
packageData,
|
|
||||||
/^Programming Language :: Python :: (\d+) :: Only$/
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.constructor.render({ versions })
|
return this.constructor.render({ versions })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,29 @@ t.create('python versions (valid, no package version specified)')
|
|||||||
message: isPipeSeparatedPythonVersions,
|
message: isPipeSeparatedPythonVersions,
|
||||||
})
|
})
|
||||||
|
|
||||||
t.create('python versions ("Only" and others)')
|
t.create(
|
||||||
|
'python versions (valid, package version in request, experimental flag)'
|
||||||
|
)
|
||||||
|
.get('/requests/2.18.4.json?experimental')
|
||||||
|
.expectBadge({
|
||||||
|
label: 'python',
|
||||||
|
message: isPipeSeparatedPythonVersions,
|
||||||
|
})
|
||||||
|
|
||||||
|
t.create(
|
||||||
|
'python versions (valid, no package version specified, experimental flag)'
|
||||||
|
)
|
||||||
|
.get('/requests.json?experimental')
|
||||||
|
.expectBadge({
|
||||||
|
label: 'python',
|
||||||
|
message: isPipeSeparatedPythonVersions,
|
||||||
|
})
|
||||||
|
|
||||||
|
t.create('python versions ("Only" classifier and others)')
|
||||||
.get('/uvloop/0.12.1.json')
|
.get('/uvloop/0.12.1.json')
|
||||||
.expectBadge({ label: 'python', message: '3.5 | 3.6 | 3.7' })
|
.expectBadge({ label: 'python', message: '3.5 | 3.6 | 3.7' })
|
||||||
|
|
||||||
t.create('python versions ("Only" only)')
|
t.create('python versions ("Only" classifier only)')
|
||||||
.get('/hashpipe/0.9.1.json')
|
.get('/hashpipe/0.9.1.json')
|
||||||
.expectBadge({ label: 'python', message: '3' })
|
.expectBadge({ label: 'python', message: '3' })
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user