Compare commits

..

No commits in common. "main" and "1.5.0" have entirely different histories.
main ... 1.5.0

11 changed files with 130 additions and 443 deletions

View file

@ -1,13 +0,0 @@
# SPDX-FileCopyrightText: 2023 Melissa LeBlanc-Williams, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
change-template: "- $TITLE #$NUMBER by @$AUTHOR"
template: |
## What's Changed
$CHANGES
To use in CPython, `pip3 install Adafruit-Python-Shell`.
Read the [docs](https://circuitpython.readthedocs.io/projects/shell/en/latest/) for info on how to use it.

View file

@ -10,27 +10,31 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJson(github) }}
run: echo "$GITHUB_CONTEXT"
- name: Translate Repo Name For Build Tools filename_prefix - name: Translate Repo Name For Build Tools filename_prefix
id: repo-name id: repo-name
run: | run: |
echo repo-name=$( echo ::set-output name=repo-name::$(
echo ${{ github.repository }} | echo ${{ github.repository }} |
awk -F '\/' '{ print tolower($2) }' | awk -F '\/' '{ print tolower($2) }' |
tr '_' '-' tr '_' '-'
) >> $GITHUB_OUTPUT )
- name: Set up Python 3.11 - name: Set up Python 3.7
uses: actions/setup-python@v4 uses: actions/setup-python@v1
with: with:
python-version: '3.11' python-version: 3.7
- name: Versions - name: Versions
run: | run: |
python3 --version python3 --version
- name: Checkout Current Repo - name: Checkout Current Repo
uses: actions/checkout@v3 uses: actions/checkout@v1
with: with:
submodules: true submodules: true
- name: Checkout tools repo - name: Checkout tools repo
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
repository: adafruit/actions-ci-circuitpython-libs repository: adafruit/actions-ci-circuitpython-libs
path: actions-ci path: actions-ci
@ -40,23 +44,26 @@ jobs:
source actions-ci/install.sh source actions-ci/install.sh
- name: Pip install pylint, Sphinx, pre-commit - name: Pip install pylint, Sphinx, pre-commit
run: | run: |
pip install --force-reinstall Sphinx sphinx-rtd-theme pre-commit pip install --force-reinstall pylint Sphinx sphinx-rtd-theme pre-commit
- name: Library version - name: Library version
run: git describe --dirty --always --tags run: git describe --dirty --always --tags
- name: Pre-commit hooks - name: Pre-commit hooks
run: | run: |
pre-commit run --all-files pre-commit run --all-files
- name: PyLint
run: |
pylint $( find . -path './adafruit*.py' )
- name: Build docs - name: Build docs
working-directory: docs working-directory: docs
run: sphinx-build -E -W -b html . _build/html run: sphinx-build -E -W -b html . _build/html
- name: Check For pyproject.toml - name: Check For setup.py
id: need-pypi id: need-pypi
run: | run: |
echo pyproject-toml=$( find . -wholename './pyproject.toml' ) >> $GITHUB_OUTPUT echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Build Python package - name: Build Python package
if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: | run: |
pip install --upgrade build twine pip install --upgrade setuptools wheel twine readme_renderer testresources
find -type f -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) -exec sed -i -e "s/0.0.0+auto.0/1.2.3/" {} + python setup.py sdist
python -m build python setup.py bdist_wheel --universal
twine check dist/* twine check dist/*

View file

@ -1,25 +0,0 @@
# SPDX-FileCopyrightText: 2023 Melissa LeBlanc-Williams, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT
name: Release Drafter
on:
push:
branches:
- main
permissions:
contents: read
jobs:
update_release_draft:
permissions:
# write permission is required to create a github release
contents: write
pull-requests: read
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -12,27 +12,26 @@ jobs:
upload-pypi: upload-pypi:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v1
- name: Check For pyproject.toml - name: Check For setup.py
id: need-pypi id: need-pypi
run: | run: |
echo pyproject-toml=$( find . -wholename './pyproject.toml' ) >> $GITHUB_OUTPUT echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
- name: Set up Python - name: Set up Python
if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
uses: actions/setup-python@v4 uses: actions/setup-python@v1
with: with:
python-version: '3.11' python-version: '3.x'
- name: Install dependencies - name: Install dependencies
if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install --upgrade build twine pip install setuptools wheel twine
- name: Build and publish - name: Build and publish
if: contains(steps.need-pypi.outputs.pyproject-toml, 'pyproject.toml') if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
env: env:
TWINE_USERNAME: ${{ secrets.pypi_username }} TWINE_USERNAME: ${{ secrets.pypi_username }}
TWINE_PASSWORD: ${{ secrets.pypi_password }} TWINE_PASSWORD: ${{ secrets.pypi_password }}
run: | run: |
find -type f -not -path "./.*" -not -path "./docs*" \( -name "*.py" -o -name "*.toml" \) -exec sed -i -e "s/0.0.0+auto.0/${{github.event.release.tag_name}}/" {} + python setup.py sdist
python -m build
twine upload dist/* twine upload dist/*

View file

@ -3,40 +3,17 @@
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
repos: repos:
- repo: https://github.com/python/black - repo: https://github.com/python/black
rev: 23.3.0 rev: 22.3.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/fsfe/reuse-tool - repo: https://github.com/fsfe/reuse-tool
rev: v1.1.2 rev: v0.12.1
hooks: hooks:
- id: reuse - id: reuse
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0 rev: v4.0.1
hooks: hooks:
- id: check-yaml - id: check-yaml
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
- repo: https://github.com/pycqa/pylint
rev: v2.17.4
hooks:
- id: pylint
name: pylint (library code)
types: [python]
args:
- --disable=consider-using-f-string
exclude: "^(docs/|examples/|tests/|setup.py$)"
- id: pylint
name: pylint (example code)
description: Run pylint rules on "examples/*.py" files
types: [python]
files: "^examples/"
args:
- --disable=missing-docstring,invalid-name,consider-using-f-string,duplicate-code
- id: pylint
name: pylint (test code)
description: Run pylint rules on "tests/*.py" files
types: [python]
files: "^tests/"
args:
- --disable=missing-docstring,consider-using-f-string,duplicate-code

View file

@ -396,4 +396,4 @@ min-public-methods=1
# Exceptions that will emit a warning when being caught. Defaults to # Exceptions that will emit a warning when being caught. Defaults to
# "Exception" # "Exception"
overgeneral-exceptions=builtins.Exception overgeneral-exceptions=Exception

View file

@ -23,57 +23,19 @@ Implementation Notes
# imports # imports
import sys import sys
import os import os
import stat
import shutil import shutil
import subprocess import subprocess
import fcntl import fcntl
import platform import platform
import fileinput import fileinput
import re import re
import pwd
from datetime import datetime from datetime import datetime
from clint.textui import colored, prompt from clint.textui import colored, prompt
import adafruit_platformdetect import adafruit_platformdetect
__version__ = "0.0.0+auto.0" __version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_Python_Shell.git" __repo__ = "https://github.com/adafruit/Adafruit_Python_Shell.git"
# This must be by order of release
RASPI_VERSIONS = (
"wheezy",
"jessie",
"stretch",
"buster",
"bullseye",
"bookworm",
"trixie",
)
WINDOW_MANAGERS = {
"x11": "W1",
"wayfire": "W2",
"labwc": "W3",
}
FILE_MODES = {
"+x": stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH,
"+r": stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH,
"+w": stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH,
"a+x": stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH,
"a+r": stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH,
"a+w": stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH,
"u+x": stat.S_IXUSR,
"u+r": stat.S_IRUSR,
"u+w": stat.S_IWUSR,
"g+x": stat.S_IXGRP,
"g+r": stat.S_IRGRP,
"g+w": stat.S_IWGRP,
"o+x": stat.S_IXOTH,
"o+r": stat.S_IROTH,
"o+w": stat.S_IWOTH,
}
# pylint: disable=too-many-public-methods # pylint: disable=too-many-public-methods
class Shell: class Shell:
""" """
@ -102,9 +64,7 @@ class Shell:
) )
return prompt.options(message, options) return prompt.options(message, options)
def run_command( def run_command(self, cmd, suppress_message=False, return_output=False):
self, cmd, suppress_message=False, return_output=False, run_as_user=None
):
""" """
Run a shell command and show the output as it runs Run a shell command and show the output as it runs
""" """
@ -118,31 +78,13 @@ class Shell:
except TypeError: except TypeError:
return "" return ""
# Allow running as a different user if we are root
if self.is_root() and run_as_user is not None:
pw_record = pwd.getpwnam(run_as_user)
env = os.environ.copy()
env["HOME"] = pw_record.pw_dir
env["LOGNAME"] = run_as_user
env["USER"] = pw_record.pw_name
def preexec():
os.setgid(pw_record.pw_gid)
os.setuid(pw_record.pw_uid)
else:
env = None
preexec = None
full_output = "" full_output = ""
with subprocess.Popen( # pylint: disable=subprocess-popen-preexec-fn with subprocess.Popen(
cmd, cmd,
shell=True, shell=True,
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, stderr=subprocess.PIPE,
universal_newlines=True, universal_newlines=True,
env=env,
preexec_fn=preexec,
) as proc: ) as proc:
while proc.poll() is None: while proc.poll() is None:
err = read_stream(proc.stderr) err = read_stream(proc.stderr)
@ -161,50 +103,6 @@ class Shell:
return False return False
return True return True
def write_templated_file(self, output_path, template, **kwargs):
"""
Use a template file and render it with the given context and write it to the specified path.
The template file should contain placeholders in the format {key} which will be replaced
with the corresponding values from the kwargs dictionary.
"""
# if path is an existing directory, the template filename will be used
output_path = self.path(output_path)
if os.path.isdir(output_path):
output_path = os.path.join(output_path, os.path.basename(template))
# Render the template with the provided context
rendered_content = self.load_template(template, **kwargs)
if rendered_content is None:
self.error(
f"Failed to load template '{template}'. Unable to write file '{output_path}'."
)
return False
append = kwargs.get("append", False)
self.write_text_file(output_path, rendered_content, append=append)
return True
def load_template(self, template, **kwargs):
"""
Load a template file and return its content with the placeholders replaced by the provided
context. The template file should contain placeholders in the format {key} which will be
replaced with the corresponding values from the kwargs dictionary.
"""
if not os.path.exists(template):
self.error(f"Template file '{template}' does not exist")
return None
with open(template, "r") as template_file:
template_content = template_file.read()
# Render the template with the provided context
for key, value in kwargs.items():
template_content = template_content.replace(f"{{{key}}}", str(value))
return template_content
def info(self, message, **kwargs): def info(self, message, **kwargs):
""" """
Display a message with the group in green Display a message with the group in green
@ -304,9 +202,9 @@ class Shell:
# directory = self.getcwd() + "/" + directory # directory = self.getcwd() + "/" + directory
directory = self.path(directory) directory = self.path(directory)
if not self.exists(directory): if not self.exists(directory):
raise ValueError(f"Directory '{directory}' does not exist") raise ValueError("Directory does not exist")
if not self.isdir(directory): if not self.isdir(directory):
raise ValueError(f"The given location '{directory}' is not a directory") raise ValueError("Given location is not a directory")
os.chdir(directory) os.chdir(directory)
def pushd(self, directory): def pushd(self, directory):
@ -384,10 +282,7 @@ class Shell:
# Not found; append (silently) # Not found; append (silently)
self.write_text_file(file, replacement, append=True) self.write_text_file(file, replacement, append=True)
# pylint: disable=too-many-arguments def pattern_search(self, location, pattern, multi_line=False):
def pattern_search(
self, location, pattern, multi_line=False, return_match=False, find_all=False
):
""" """
Similar to grep, but uses pure python Similar to grep, but uses pure python
multi_line will search the entire file as a large text glob, multi_line will search the entire file as a large text glob,
@ -397,22 +292,17 @@ class Shell:
""" """
location = self.path(location) location = self.path(location)
found = False found = False
search_function = re.findall if find_all else re.search
if self.exists(location) and not self.isdir(location): if self.exists(location) and not self.isdir(location):
if multi_line: if multi_line:
with open(location, "r+", encoding="utf-8") as file: with open(location, "r+", encoding="utf-8") as file:
match = search_function(pattern, file.read(), flags=re.DOTALL) if re.search(pattern, file.read(), flags=re.DOTALL):
if match:
found = True found = True
else: else:
for line in fileinput.FileInput(location): for line in fileinput.FileInput(location):
match = search_function(pattern, line) if re.search(pattern, line):
if match:
found = True found = True
break
if return_match:
return match
return found return found
def pattern_replace(self, location, pattern, replace="", multi_line=False): def pattern_replace(self, location, pattern, replace="", multi_line=False):
@ -479,42 +369,6 @@ class Shell:
destination += os.sep + os.path.basename(source) destination += os.sep + os.path.basename(source)
shutil.copy(source, destination) shutil.copy(source, destination)
def chmod(self, location, mode):
"""
Change the permissions of a file or directory
"""
location = self.path(location)
# Convert a text mode to an integer mode
if isinstance(mode, str):
if mode not in FILE_MODES:
raise ValueError(f"Invalid mode string '{mode}'")
mode = FILE_MODES[mode]
if not 0 <= mode <= 0o777:
raise ValueError(f"Invalid mode value '{mode}'")
if os.path.exists(location):
os.chmod(location, mode)
def chown(self, location, user, group=None, recursive=False):
"""
Change the owner of a file or directory
"""
if group is None:
group = user
location = self.path(location)
if recursive and os.path.isdir(location):
for root, dirs, files in os.walk(location):
for directory in dirs:
shutil.chown(
os.path.join(root, directory),
user,
group,
)
for file in files:
shutil.chown(os.path.join(root, file), user, group)
else:
shutil.chown(location, user, group)
def remove(self, location): def remove(self, location):
""" """
Remove a file or directory if it exists Remove a file or directory if it exists
@ -547,16 +401,6 @@ class Shell:
with open(self.path(path), mode, encoding="utf-8") as service_file: with open(self.path(path), mode, encoding="utf-8") as service_file:
service_file.write(content) service_file.write(content)
def read_text_file(self, path):
"""
Read the contents of a file at the specified path
"""
path = self.path(path)
if not os.path.exists(path):
raise FileNotFoundError(f"File '{path}' does not exist")
with open(path, "r", encoding="utf-8") as file:
return file.read()
@staticmethod @staticmethod
def is_python3(): def is_python3():
"Check if we are running Python 3 or later" "Check if we are running Python 3 or later"
@ -628,10 +472,6 @@ class Shell:
with open("/etc/os-release", encoding="utf-8") as f: with open("/etc/os-release", encoding="utf-8") as f:
if "Raspbian" in f.read(): if "Raspbian" in f.read():
release = "Raspbian" release = "Raspbian"
if self.exists("/etc/rpi-issue"):
with open("/etc/rpi-issue", encoding="utf-8") as f:
if "Raspberry Pi" in f.read():
release = "Raspbian"
if self.run_command("command -v apt-get", suppress_message=True): if self.run_command("command -v apt-get", suppress_message=True):
with open("/etc/os-release", encoding="utf-8") as f: with open("/etc/os-release", encoding="utf-8") as f:
release_file = f.read() release_file = f.read()
@ -654,29 +494,17 @@ class Shell:
"""Return a string containing the raspbian version""" """Return a string containing the raspbian version"""
if self.get_os() != "Raspbian": if self.get_os() != "Raspbian":
return None return None
raspbian_releases = ("bullseye", "buster", "stretch", "jessie", "wheezy")
if os.path.exists("/etc/os-release"): if os.path.exists("/etc/os-release"):
with open("/etc/os-release", encoding="utf-8") as f: with open("/etc/os-release", encoding="utf-8") as f:
release_file = f.read() release_file = f.read()
if "/sid" in release_file: if "/sid" in release_file:
return "unstable" return "unstable"
for raspbian in RASPI_VERSIONS: for raspbian in raspbian_releases:
if raspbian in release_file: if raspbian in release_file:
return raspbian return raspbian
return None return None
def is_minumum_version(self, version):
"""Check if the version is at least the specified version"""
# Check that version is a string
if not isinstance(version, str):
raise ValueError("Version must be a string")
# Check that version is in the list of valid versions
if version.lower() not in RASPI_VERSIONS:
raise ValueError("Invalid version")
# Check that the current version is at least the specified version
return RASPI_VERSIONS.index(
self.get_raspbian_version()
) >= RASPI_VERSIONS.index(version.lower())
def prompt_reboot(self, default="y", **kwargs): def prompt_reboot(self, default="y", **kwargs):
"""Prompt the user for a reboot""" """Prompt the user for a reboot"""
if not self.prompt("REBOOT NOW?", default=default, **kwargs): if not self.prompt("REBOOT NOW?", default=default, **kwargs):
@ -696,96 +524,8 @@ class Shell:
) )
self.prompt_reboot() self.prompt_reboot()
def check_kernel_userspace_mismatch(self, attempt_fix=True, fix_with_x11=False):
"""
Check if the userspace is 64-bit and kernel is 32-bit
"""
if self.is_kernel_userspace_mismatched():
print(
"Unable to compile driver because kernel space is 64-bit, but user space is 32-bit."
)
config = self.get_boot_config()
if (
self.is_raspberry_pi_os()
and attempt_fix
and config
and self.prompt(f"Add parameter to {config} to use 32-bit kernel?")
):
# Set to use 32-bit kernel
self.reconfig(config, "^.*arm_64bit.*$", "arm_64bit=0")
if fix_with_x11:
self.set_window_manager("x11")
self.prompt_reboot()
else:
raise RuntimeError("Unable to continue while mismatch is present.")
def set_window_manager(self, manager):
"""
Call raspi-config to set a new window manager
"""
if not self.is_minumum_version("bullseye"):
return
if manager.lower() not in WINDOW_MANAGERS:
raise ValueError("Invalid window manager")
if manager.lower() == "labwc" and not self.exists("/usr/bin/labwc"):
raise RuntimeError("labwc is not installed")
print(f"Using {manager} as the window manager")
if not self.run_command(
"sudo raspi-config nonint do_wayland " + WINDOW_MANAGERS[manager.lower()]
):
raise RuntimeError("Unable to change window manager")
def get_window_manager(self):
"""
Get the current window manager
"""
sessions = {"wayfire": "LXDE-pi-wayfire"}
# Check for Raspbian Desktop sessions
if self.exists("/usr/share/xsessions/rpd-x.desktop") or self.exists(
"/usr/share/wayland-sessions/rpd-labwc.desktop"
):
sessions.update({"x11": "rpd-x", "labwc": "rpd-labwc"})
else:
sessions.update({"x11": "LXDE-pi-x", "labwc": "LXDE-pi-labwc"})
matches = self.pattern_search(
"/etc/lightdm/lightdm.conf", "^(?!#.*?)user-session=(.+)", False, True
)
if matches:
session_match = matches.group(1)
for key, session in sessions.items():
if session_match == session:
return key
return None
def get_boot_config(self):
"""
Get the location of the boot config file
"""
# check if /boot/firmware/config.txt exists
if self.exists("/boot/firmware/config.txt"):
return "/boot/firmware/config.txt"
if self.exists("/boot/config.txt"):
return "/boot/config.txt"
return None
def is_kernel_userspace_mismatched(self):
"""
If the userspace 64-bit and kernel is 32-bit?
"""
return self.is_arm64() and platform.architecture()[0] == "32bit"
# pylint: enable=invalid-name # pylint: enable=invalid-name
def is_raspberry_pi_os(self):
"""
Check if we are running Raspberry Pi OS or Raspbian
"""
return self.get_os() == "Raspbian"
@staticmethod @staticmethod
def is_raspberry_pi(): def is_raspberry_pi():
""" """
@ -802,14 +542,6 @@ class Shell:
detector = adafruit_platformdetect.Detector() detector = adafruit_platformdetect.Detector()
return detector.board.id return detector.board.id
@staticmethod
def is_pi5_or_newer():
"""
Use PlatformDetect to check if this is a Raspberry Pi 5 or newer
"""
detector = adafruit_platformdetect.Detector()
return detector.board.any_raspberry_pi_5_board
@staticmethod @staticmethod
def get_architecture(): def get_architecture():
""" """

View file

@ -6,7 +6,6 @@
import os import os
import sys import sys
import datetime
sys.path.insert(0, os.path.abspath("..")) sys.path.insert(0, os.path.abspath(".."))
@ -17,14 +16,13 @@ sys.path.insert(0, os.path.abspath(".."))
# ones. # ones.
extensions = [ extensions = [
"sphinx.ext.autodoc", "sphinx.ext.autodoc",
"sphinxcontrib.jquery",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx.ext.napoleon", "sphinx.ext.napoleon",
"sphinx.ext.todo", "sphinx.ext.todo",
] ]
intersphinx_mapping = { intersphinx_mapping = {
"python": ("https://docs.python.org/3", None), "python": ("https://docs.python.org/3.4", None),
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None), "CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
} }
@ -38,14 +36,7 @@ master_doc = "index"
# General information about the project. # General information about the project.
project = "Adafruit Shell Library" project = "Adafruit Shell Library"
creation_year = "2020" copyright = "2020 Melissa LeBlanc-Williams"
current_year = str(datetime.datetime.now().year)
year_duration = (
current_year
if current_year == creation_year
else creation_year + " - " + current_year
)
copyright = year_duration + " Melissa LeBlanc-Williams"
author = "Melissa LeBlanc-Williams" author = "Melissa LeBlanc-Williams"
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
@ -100,9 +91,19 @@ napoleon_numpy_docstring = False
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes. # a list of builtin themes.
# #
import sphinx_rtd_theme on_rtd = os.environ.get("READTHEDOCS", None) == "True"
html_theme = "sphinx_rtd_theme" if not on_rtd: # only import and set the theme if we're building docs locally
try:
import sphinx_rtd_theme
html_theme = "sphinx_rtd_theme"
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
except:
html_theme = "default"
html_theme_path = ["."]
else:
html_theme_path = ["."]
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,

View file

@ -1,3 +0,0 @@
# SPDX-FileCopyrightText: 2023 Alec Delaney, written for Adafruit Industries
#
# SPDX-License-Identifier: MIT

View file

@ -1,54 +1,6 @@
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò # SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
# SPDX-FileCopyrightText: 2023 Alec Delaney for Adafruit Industries
# #
# SPDX-License-Identifier: Unlicense # SPDX-License-Identifier: Unlicense
[build-system] [tool.black]
requires = [ target-version = ['py35']
"setuptools",
"wheel",
"setuptools-scm",
]
[project]
name = "adafruit-python-shell"
description = "Python helper for running Shell scripts in Python"
version = "0.0.0+auto.0"
readme = "README.rst"
authors = [
{name = "Adafruit Industries", email = "circuitpython@adafruit.com"}
]
urls = {Homepage = "https://github.com/adafruit/Adafruit_Python_Shell"}
keywords = [
"adafruit",
"blinka",
"circuitpython",
"micropython",
"python",
"shell",
"installation",
"raspberry",
"pi",
"console",
"terminal",
"installer",
]
license = {text = "MIT"}
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
]
dynamic = ["dependencies", "optional-dependencies"]
[tool.setuptools]
py-modules = ["adafruit_shell"]
[tool.setuptools.dynamic]
dependencies = {file = ["requirements.txt"]}
optional-dependencies = {optional = {file = ["optional_requirements.txt"]}}

60
setup.py Normal file
View file

@ -0,0 +1,60 @@
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2020 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""A setuptools based setup module.
See:
https://packaging.python.org/en/latest/distributing.html
https://github.com/pypa/sampleproject
"""
from setuptools import setup, find_packages
# To use a consistent encoding
from codecs import open
from os import path
here = path.abspath(path.dirname(__file__))
# Get the long description from the README file
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
long_description = f.read()
setup(
name="adafruit-python-shell",
use_scm_version=True,
setup_requires=["setuptools_scm"],
description="Python helper for running Shell scripts in Python",
long_description=long_description,
long_description_content_type="text/x-rst",
# The project's main homepage.
url="https://github.com/adafruit/Adafruit_Python_Shell",
# Author details
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
install_requires=[
"clint",
"Adafruit-PlatformDetect",
],
# Choose your license
license="MIT",
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"Topic :: System :: Hardware",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
],
# What does your project relate to?
keywords="adafruit blinka circuitpython micropython python shell installation raspberry pi "
"console terminal installer",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
py_modules=["adafruit_shell"],
)