DEPRECATED -- Rewritten and moved to https://github.com/NiklasRosenstein/shut/. 🌊 Shore is a distribution and release management tool for pure Python packages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
4.6 KiB

11 months ago
11 months ago
  1. # -*- coding: utf8 -*-
  2. # Copyright (c) 2020 Niklas Rosenstein
  3. #
  4. # Permission is hereby granted, free of charge, to any person obtaining a copy
  5. # of this software and associated documentation files (the "Software"), to
  6. # deal in the Software without restriction, including without limitation the
  7. # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. # sell copies of the Software, and to permit persons to whom the Software is
  9. # furnished to do so, subject to the following conditions:
  10. #
  11. # The above copyright notice and this permission notice shall be included in
  12. # all copies or substantial portions of the Software.
  13. #
  14. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. # IN THE SOFTWARE.
  21. from shore.util.classifiers import get_classifiers
  22. from .core import CheckResult, CheckStatus, Checker, check, register_checker
  23. from shut.model import MonorepoModel, PackageModel, Project
  24. from typing import Iterable, Optional
  25. import os
  26. class PackageChecker(Checker[PackageModel]):
  27. @check('readme')
  28. def _check_readme(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  29. if package.get_readme():
  30. yield CheckResult(CheckStatus.PASSED, 'No README file found.')
  31. @check('license')
  32. def _check_license(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  33. if not package.data.license:
  34. yield CheckResult(CheckStatus.WARNING, 'not specified')
  35. elif package.data.license and not package.get_license():
  36. yield CheckResult(CheckStatus.WARNING, 'No LICENSE file found.')
  37. monorepo = project.monorepo
  38. if package.data.license and monorepo and monorepo.license \
  39. and monorepo.license != package.data.license:
  40. yield CheckResult(CheckStatus.ERROR,
  41. 'License is not consistent with parent mono repository (package: {}, monorepo: {}).'
  42. .format(package.license, monorepo.license))
  43. @check('classifiers')
  44. def _check_classifiers(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  45. classifiers = get_classifiers()
  46. unknown_classifiers = [x for x in package.data.classifiers if x not in classifiers]
  47. if unknown_classifiers:
  48. yield CheckResult(
  49. CheckStatus.WARNING,
  50. 'Unknown classifiers: ' + ', '.join(unknown_classifiers))
  51. @check('author')
  52. def _check_author(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  53. if not package.data.author:
  54. yield CheckResult(CheckStatus.WARNING, 'missing')
  55. @check('url')
  56. def _check_author(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  57. if not package.data.url:
  58. yield CheckResult(CheckStatus.WARNING, 'missing')
  59. @check('consistent-author')
  60. def _check_consistent_author(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  61. metadata = package.get_python_package_metadata()
  62. if package.data.author and metadata.author != str(package.data.author):
  63. yield CheckResult(
  64. CheckStatus.ERROR,
  65. 'Inconsistent package author (package.yaml: {!r} != {}: {!r})'.format(
  66. str(package.data.author), metadata.filename, metadata.author))
  67. @check('consistent-version')
  68. def _check_consistent_version(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  69. metadata = package.get_python_package_metadata()
  70. if package.data.version and metadata.version != str(package.data.version):
  71. yield CheckResult(
  72. CheckStatus.ERROR,
  73. '{!r} ({}) != {!r} ({})'.format(
  74. str(package.data.version),
  75. os.path.basename(package.filename),
  76. metadata.version,
  77. os.path.relpath(metadata.filename)))
  78. @check('typed')
  79. def _check_typed(self, project: Project, package: PackageModel) -> Iterable[CheckResult]:
  80. metadata = package.get_python_package_metadata()
  81. try:
  82. py_typed_file = os.path.join(metadata.package_directory, 'py.typed')
  83. except ValueError:
  84. if package.data.typed:
  85. yield CheckResult(
  86. CheckStatus.WARNING,
  87. '$.package.typed only works with packages, but this is a module')
  88. else:
  89. if os.path.isfile(py_typed_file) and not package.data.typed:
  90. yield CheckResult(
  91. CheckStatus.WARNING,
  92. 'file "py.typed" exists but $.typed is not set')
  93. register_checker(PackageChecker, PackageModel)