Generate requirements_* from manifests (#22718)
## Description: Generate requirements_* from manifests (if present). If not, fallback to the current approach of reading `REQUIREMENTS` from the module attribute. I disabled exploring the children of the `homeassistant.components.*` packages since that will just add a dependency (from the manifest) due to each of the python files in the package. Just having one for the top level package should be sufficient. **Related issue (if applicable):** relates to #22700 ## Checklist: - [x] The code change is tested and works locally. - [x] Local tests pass with `tox`. **Your PR cannot be merged unless tests pass** - [x] There is no commented out code in this PR. [ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L14 [ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L23 Co-authored-by: Jason Hu <awaregit@gmail.com>
This commit is contained in:
parent
6c5f0b7434
commit
d15eedc0fb
4 changed files with 515 additions and 524 deletions
|
@ -7,6 +7,8 @@ import pkgutil
|
|||
import re
|
||||
import sys
|
||||
|
||||
from script.manifest.requirements import gather_requirements_from_manifests
|
||||
|
||||
COMMENT_REQUIREMENTS = (
|
||||
'Adafruit-DHT',
|
||||
'Adafruit_BBIO',
|
||||
|
@ -213,36 +215,8 @@ def gather_modules():
|
|||
|
||||
errors = []
|
||||
|
||||
for package in sorted(
|
||||
explore_module('homeassistant.components', True) +
|
||||
explore_module('homeassistant.scripts', True) +
|
||||
explore_module('homeassistant.auth', True)):
|
||||
try:
|
||||
module = importlib.import_module(package)
|
||||
except ImportError as err:
|
||||
for pattern in IGNORE_PACKAGES:
|
||||
if fnmatch.fnmatch(package, pattern):
|
||||
break
|
||||
else:
|
||||
print("{}: {}".format(package.replace('.', '/') + '.py', err))
|
||||
errors.append(package)
|
||||
continue
|
||||
|
||||
if not getattr(module, 'REQUIREMENTS', None):
|
||||
continue
|
||||
|
||||
for req in module.REQUIREMENTS:
|
||||
if req in IGNORE_REQ:
|
||||
continue
|
||||
if '://' in req and 'pyharmony' not in req:
|
||||
errors.append(
|
||||
"{}[Only pypi dependencies are allowed: {}]".format(
|
||||
package, req))
|
||||
if req.partition('==')[1] == '' and req not in IGNORE_PIN:
|
||||
errors.append(
|
||||
"{}[Please pin requirement {}, see {}]".format(
|
||||
package, req, URL_PIN))
|
||||
reqs.setdefault(req, []).append(package)
|
||||
gather_requirements_from_manifests(process_requirements, errors, reqs)
|
||||
gather_requirements_from_modules(errors, reqs)
|
||||
|
||||
for key in reqs:
|
||||
reqs[key] = sorted(reqs[key],
|
||||
|
@ -257,12 +231,47 @@ def gather_modules():
|
|||
return reqs
|
||||
|
||||
|
||||
def gather_requirements_from_modules(errors, reqs):
|
||||
"""Collect the requirements from the modules directly."""
|
||||
for package in sorted(
|
||||
explore_module('homeassistant.scripts', True) +
|
||||
explore_module('homeassistant.auth', True)):
|
||||
try:
|
||||
module = importlib.import_module(package)
|
||||
except ImportError as err:
|
||||
for pattern in IGNORE_PACKAGES:
|
||||
if fnmatch.fnmatch(package, pattern):
|
||||
break
|
||||
else:
|
||||
print("{}: {}".format(package.replace('.', '/') + '.py', err))
|
||||
errors.append(package)
|
||||
continue
|
||||
|
||||
if getattr(module, 'REQUIREMENTS', None):
|
||||
process_requirements(errors, module.REQUIREMENTS, package, reqs)
|
||||
|
||||
|
||||
def process_requirements(errors, module_requirements, package, reqs):
|
||||
"""Process all of the requirements."""
|
||||
for req in module_requirements:
|
||||
if req in IGNORE_REQ:
|
||||
continue
|
||||
if '://' in req:
|
||||
errors.append(
|
||||
"{}[Only pypi dependencies are allowed: {}]".format(
|
||||
package, req))
|
||||
if req.partition('==')[1] == '' and req not in IGNORE_PIN:
|
||||
errors.append(
|
||||
"{}[Please pin requirement {}, see {}]".format(
|
||||
package, req, URL_PIN))
|
||||
reqs.setdefault(req, []).append(package)
|
||||
|
||||
|
||||
def generate_requirements_list(reqs):
|
||||
"""Generate a pip file based on requirements."""
|
||||
output = []
|
||||
for pkg, requirements in sorted(reqs.items(), key=lambda item: item[0]):
|
||||
for req in sorted(requirements,
|
||||
key=lambda name: (len(name.split('.')), name)):
|
||||
for req in sorted(requirements):
|
||||
output.append('\n# {}'.format(req))
|
||||
|
||||
if comment_requirement(pkg):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue