167 lines
5.1 KiB
Python
167 lines
5.1 KiB
Python
# SPDX-FileCopyrightText: 2021 foamyguy
|
|
# SPDX-FileCopyrightText: 2019 Nicholas Tollervey, written for Adafruit Industries
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
"""
|
|
Get the list of required libraries based on a file's imports
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import findimports
|
|
import requests
|
|
|
|
BUNDLE_DATA = "latest_bundle_data.json"
|
|
BUNDLE_TAG = "latest_bundle_tag.json"
|
|
|
|
LEARN_GUIDE_REPO = os.environ.get(
|
|
"LEARN_GUIDE_REPO", "../../Adafruit_Learning_System_Guides/"
|
|
)
|
|
|
|
SHOWN_FILETYPES = ["py", "mpy", "bmp", "pcf", "bdf", "wav", "mp3", "json", "txt"]
|
|
|
|
|
|
def get_bundle(tag):
|
|
"""Download the given bundle's data to BUNDLE_DATA"""
|
|
url = f"https://adafruit-circuit-python.s3.amazonaws.com/bundles/adafruit/adafruit-circuitpython-bundle-{tag}.json" # pylint: disable=line-too-long
|
|
print(f"get bundle metadata from {url}")
|
|
r = requests.get(url)
|
|
with open(BUNDLE_DATA, "wb") as bundle_file:
|
|
bundle_file.write(r.content)
|
|
|
|
|
|
LATEST_BUNDLE_VERSION = ""
|
|
|
|
|
|
def get_latest_release_from_url(url):
|
|
"""
|
|
Find the tag name of the latest release by using HTTP HEAD and decoding the redirect.
|
|
|
|
:return: The most recent tag value for the release.
|
|
"""
|
|
|
|
print(f"Requesting redirect information: {url}")
|
|
response = requests.head(url)
|
|
responseurl = response.url
|
|
if response.is_redirect:
|
|
responseurl = response.headers["Location"]
|
|
tag = responseurl.rsplit("/", 1)[-1]
|
|
print(f"Tag: {tag!r}")
|
|
return tag
|
|
|
|
|
|
def get_latest_tag():
|
|
"""
|
|
Find the value of the latest tag for the Adafruit CircuitPython library
|
|
bundle.
|
|
:return: The most recent tag value for the project.
|
|
"""
|
|
global LATEST_BUNDLE_VERSION # pylint: disable=global-statement
|
|
if LATEST_BUNDLE_VERSION == "":
|
|
LATEST_BUNDLE_VERSION = get_latest_release_from_url(
|
|
"https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/latest"
|
|
)
|
|
return LATEST_BUNDLE_VERSION
|
|
|
|
|
|
def ensure_latest_bundle():
|
|
"""
|
|
Ensure that there's a copy of the latest library bundle available so circup
|
|
can check the metadata contained therein.
|
|
"""
|
|
print("Checking for library updates.")
|
|
tag = get_latest_tag()
|
|
old_tag = "0"
|
|
if os.path.isfile(BUNDLE_TAG):
|
|
with open(BUNDLE_TAG, encoding="utf-8") as data:
|
|
try:
|
|
old_tag = json.load(data)["tag"]
|
|
except json.decoder.JSONDecodeError as _:
|
|
# Sometimes (why?) the JSON file becomes corrupt. In which case
|
|
# log it and carry on as if setting up for first time.
|
|
print(f"Could not parse {BUNDLE_TAG:r}")
|
|
if tag > old_tag:
|
|
print(f"New version available {tag}.")
|
|
try:
|
|
get_bundle(tag)
|
|
with open(BUNDLE_TAG, "w", encoding="utf-8") as data:
|
|
json.dump({"tag": tag}, data)
|
|
except requests.exceptions.HTTPError as _:
|
|
# See #20 for reason this this
|
|
print(
|
|
(
|
|
"There was a problem downloading the bundle. "
|
|
"Please try again in a moment."
|
|
),
|
|
)
|
|
raise
|
|
else:
|
|
print(f"Current library bundle up to date {tag}")
|
|
|
|
|
|
ensure_latest_bundle()
|
|
|
|
with open("latest_bundle_data.json", "r") as f:
|
|
bundle_data = json.load(f)
|
|
|
|
|
|
def get_files_for_project(project_name):
|
|
"""Get the set of files for a learn project"""
|
|
found_files = set()
|
|
project_dir = "{}/{}/".format(LEARN_GUIDE_REPO, project_name)
|
|
for file in os.listdir(project_dir):
|
|
if "." in file:
|
|
cur_extension = file.split(".")[-1]
|
|
if cur_extension in SHOWN_FILETYPES:
|
|
# print(file)
|
|
found_files.add(file)
|
|
else:
|
|
# add dir
|
|
found_files.add(file)
|
|
return found_files
|
|
|
|
|
|
def get_libs_for_project(project_name):
|
|
"""Get the set of libraries for a learn project"""
|
|
found_libs = set()
|
|
found_imports = []
|
|
project_dir = "{}{}/".format(LEARN_GUIDE_REPO, project_name)
|
|
for file in os.listdir(project_dir):
|
|
if file.endswith(".py"):
|
|
|
|
found_imports = findimports.find_imports("{}{}".format(project_dir, file))
|
|
|
|
for cur_import in found_imports:
|
|
cur_lib = cur_import.name.split(".")[0]
|
|
if cur_lib in bundle_data:
|
|
found_libs.add(cur_lib)
|
|
|
|
return found_libs
|
|
|
|
|
|
def get_learn_guide_projects():
|
|
"""Get the list of all folders in the learn guide"""
|
|
return os.listdir(LEARN_GUIDE_REPO)
|
|
|
|
|
|
def get_learn_guide_cp_projects():
|
|
"""Get the list of all circuitpython projects, according to some heuristics"""
|
|
cp_projects = []
|
|
|
|
def has_py_file(location):
|
|
dir_files = os.listdir(location)
|
|
for file in dir_files:
|
|
if file.endswith(".py"):
|
|
return ".circuitpython.skip" not in dir_files
|
|
return False
|
|
|
|
all_projects = get_learn_guide_projects()
|
|
for project in all_projects:
|
|
project_dir = "{}/{}/".format(LEARN_GUIDE_REPO, project)
|
|
try:
|
|
if has_py_file(project_dir):
|
|
cp_projects.append(project)
|
|
except NotADirectoryError:
|
|
pass
|
|
return cp_projects
|