Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
classifiers = data.get("classifiers", [])
for classifier in classifiers:
parts = [p.strip() for p in classifier.split("::")]
if parts[0] == "Development Status":
# license classifier exist
return True
return False
def message(self):
return (
"Specifying a development status in the classifiers gives "
"users a hint of how stable your software is."
)
class SDist(BaseTest):
weight = 100
def test(self, data):
if "_has_sdist" not in data:
# We aren't checking on PyPI
self.weight = 0
return None
return data["_has_sdist"]
def message(self):
return (
"You have no source distribution on the Cheeseshop. "
"Uploading the source distribution to the Cheeseshop ensures "
"maximum availability of your package."
)
u"Gorgonzola",
u"Stilton",
u"Brie",
u"Comté",
u"Jarlsberg",
u"Philadelphia",
u"Cottage Cheese",
u"Your cheese is so fresh most people think it's a cream: Mascarpone",
]
class BaseTest(object):
fatal = False
class FieldTest(BaseTest):
"""Tests that a specific field is in the data and is not empty or False"""
def test(self, data):
return bool(data.get(self.field))
def message(self):
return ("Your package does not have %s data" % self.field) + (
self.fatal and "!" or "."
)
class Name(FieldTest):
fatal = True
field = "name"
def test(self, data):
if "_has_sdist" not in data:
# We aren't checking on PyPI
self.weight = 0
return None
return data["_has_sdist"]
def message(self):
return (
"You have no source distribution on the Cheeseshop. "
"Uploading the source distribution to the Cheeseshop ensures "
"maximum availability of your package."
)
class ValidREST(BaseTest):
weight = 50
def test(self, data):
content_type = data.get("long_description_content_type", None)
if content_type in ("text/plain", "text/markdown"):
# These can't fail. Markdown will just assume everything
# it doesn't understand is plain text.
return True
# This should be ReStructuredText
source = data.get("long_description", "")
stream = io.StringIO()
settings = {"warning_stream": stream}
try:
if license in CODE_LICENSES:
if not CODE_LICENSES[license].intersection(licenses):
self._message = (
"The license '%s' specified is not listed in "
"your classifiers." % license
)
return False
return True
def message(self):
return self._message
class DevStatusClassifier(BaseTest):
weight = 20
def test(self, data):
classifiers = data.get("classifiers", [])
for classifier in classifiers:
parts = [p.strip() for p in classifier.split("::")]
if parts[0] == "Development Status":
# license classifier exist
return True
return False
def message(self):
return (
"Specifying a development status in the classifiers gives "
"users a hint of how stable your software is."
)
version = data.get("version")
self.pep386 = False
if PEP386_RE.search(str(version)) is not None:
# Matches the old PEP386
self.weight = 10
self.pep386 = True
match = PEP440_RE.search(str(version))
return match is not None
def message(self):
if self.pep386:
return "The package's version number complies only with PEP-386 and not PEP-440."
return "The package's version number does not comply with PEP-386 or PEP-440."
class Description(BaseTest):
weight = 100
def test(self, data):
description = data.get("description")
if not description:
# No description at all. That's fatal.
self.fatal = True
return False
self.fatal = False
return len(description) > 10
def message(self):
if self.fatal:
return "The package had no description!"
else:
return "The package's description should be longer than " "10 characters."
def test(self, data):
long_description = data.get("long_description", "")
if not isinstance(long_description, stringtypes):
long_description = ""
return len(long_description) > 100
def message(self):
return "The package's long_description is quite short."
class Classifiers(FieldTest):
weight = 100
field = "classifiers"
class ClassifierVerification(BaseTest):
weight = 20
def test(self, data):
self._incorrect = []
classifiers = data.get("classifiers", [])
for classifier in classifiers:
if classifier not in CLASSIFIERS:
self._incorrect.append(classifier)
if self._incorrect:
return False
return True
def message(self):
err = "\n".join(self._incorrect)
return "Some of your classifiers are not standard classifiers:\n" + err
class Url(BaseTest):
weight = 20
def test(self, data):
return bool(data.get("url")) or bool(data.get("project_urls"))
def message(self):
return (
"Your package should have a 'url' field with a link to the "
"project home page, or a 'project_urls' field, with a "
"dictionary of links, or both."
)
class Licensing(BaseTest):
weight = 50
def test(self, data):
license = data.get("license")
classifiers = data.get("classifiers", [])
licenses = set()
for classifier in classifiers:
parts = [p.strip() for p in classifier.split("::")]
if parts[0] == "License":
# license classifier exist
licenses.add(classifier)
if not license and not licenses:
self._message = (
"Your package does neither have a license field "
"nor any license classifiers."
source=source, writer_name="html4css1", settings_overrides=settings
)
except SystemMessage as e:
self._message = e.args[0]
errors = stream.getvalue().strip()
if not errors:
return True
self._message = "\n" + errors
return False
def message(self):
return "Your long_description is not valid ReST: " + self._message
class BusFactor(BaseTest):
def test(self, data):
if "_owners" not in data:
self.weight = 0
return None
if len(data.get("_owners", [])) == 1:
self.weight = 100
return False
if len(data.get("_owners", [])) == 2:
self.weight = 50
return False
# Three or more, that's good.
self.weight = 100
return True
class Keywords(FieldTest):
weight = 20
field = "keywords"
class Author(FieldTest):
weight = 100
field = "author"
class AuthorEmail(FieldTest):
weight = 100
field = "author_email"
class Url(BaseTest):
weight = 20
def test(self, data):
return bool(data.get("url")) or bool(data.get("project_urls"))
def message(self):
return (
"Your package should have a 'url' field with a link to the "
"project home page, or a 'project_urls' field, with a "
"dictionary of links, or both."
)
class Licensing(BaseTest):
weight = 50
return ("Your package does not have %s data" % self.field) + (
self.fatal and "!" or "."
)
class Name(FieldTest):
fatal = True
field = "name"
class Version(FieldTest):
fatal = True
field = "version"
class VersionIsString(BaseTest):
weight = 50
def test(self, data):
# Check that the version is a string
version = data.get("version")
return isinstance(version, stringtypes)
def message(self):
return "The version number should be a string."
PEP386_RE = re.compile(
r"""
^
(?P\d+\.\d+) # minimum 'N.N'
(?P(?:\.\d+)*) # any number of extra '.N' segments