Merge pull request #161 from Neradoc/update-pylint
Update to pylint 2.15.5 to avoid an error in pip installing it
This commit is contained in:
commit
aa3c57ff22
4 changed files with 89 additions and 107 deletions
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
repos:
|
||||
- repo: https://github.com/pycqa/pylint
|
||||
rev: pylint-2.6.0
|
||||
rev: v2.15.5
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: lint (examples)
|
||||
|
|
|
|||
47
.pylintrc
47
.pylintrc
|
|
@ -8,11 +8,11 @@
|
|||
# run arbitrary code
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Add files or directories to the blacklist. They should be base names, not
|
||||
# Add files or directories to the ignore-list. They should be base names, not
|
||||
# paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the blacklist. The
|
||||
# Add files or directories matching the regex patterns to the ignore-list. The
|
||||
# regex matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
|
|
@ -54,8 +54,8 @@ confidence=
|
|||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
|
||||
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,attribute-defined-outside-init,bad-continuation,invalid-name, redefined-builtin, exec-used, global-statement, too-many-lines
|
||||
|
||||
disable=too-many-lines, consider-using-f-string, use-dict-literal, global-statement, invalid-name, fixme, import-error
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
|
@ -225,12 +225,6 @@ max-line-length=100
|
|||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=trailing-comma,dict-separator
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
|
@ -249,7 +243,7 @@ ignore-comments=yes
|
|||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
ignore-imports=yes
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
|
@ -257,38 +251,22 @@ min-similarity-lines=4
|
|||
|
||||
[BASIC]
|
||||
|
||||
# Naming hint for argument names
|
||||
argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct argument names
|
||||
argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Naming hint for attribute names
|
||||
attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct attribute names
|
||||
attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# Naming hint for class attribute names
|
||||
class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Regular expression matching correct class attribute names
|
||||
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
|
||||
|
||||
# Naming hint for class names
|
||||
# class-name-hint=[A-Z_][a-zA-Z0-9]+$
|
||||
class-name-hint=[A-Z_][a-zA-Z0-9_]+$
|
||||
|
||||
# Regular expression matching correct class names
|
||||
# class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
class-rgx=[A-Z_][a-zA-Z0-9_]+$
|
||||
|
||||
# Naming hint for constant names
|
||||
const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression matching correct constant names
|
||||
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
||||
|
||||
|
|
@ -296,9 +274,6 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
|
|||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming hint for function names
|
||||
function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct function names
|
||||
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
|
|
@ -309,21 +284,12 @@ good-names=r,g,b,w,i,j,k,n,x,y,z,ex,ok,Run,_
|
|||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming hint for inline iteration names
|
||||
inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct inline iteration names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Naming hint for method names
|
||||
method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct method names
|
||||
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Naming hint for module names
|
||||
module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression matching correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
|
|
@ -339,9 +305,6 @@ no-docstring-rgx=^_
|
|||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Naming hint for variable names
|
||||
variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct variable names
|
||||
variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ PLATFORMS = {"py": "py", "7mpy": "7.x-mpy", "8mpy": "7.x-mpy"}
|
|||
BOARDLESS_COMMANDS = ["show", "bundle-add", "bundle-remove", "bundle-show"]
|
||||
#: Version identifier for a bad MPY file format
|
||||
BAD_FILE_FORMAT = "Invalid"
|
||||
#: Timeout for requests calls like get()
|
||||
REQUESTS_TIMEOUT = 30
|
||||
|
||||
# Ensure DATA_DIR / LOG_DIR related directories and files exist.
|
||||
if not os.path.exists(DATA_DIR): # pragma: no cover
|
||||
|
|
@ -143,7 +145,7 @@ class Bundle:
|
|||
"requirements.txt",
|
||||
)
|
||||
if os.path.isfile(requirements_txt):
|
||||
with open(requirements_txt, "r") as read_this:
|
||||
with open(requirements_txt, "r", encoding="utf-8") as read_this:
|
||||
return read_this.read()
|
||||
return None
|
||||
|
||||
|
|
@ -190,7 +192,7 @@ class Bundle:
|
|||
return False
|
||||
for platform in PLATFORMS.values():
|
||||
url = self.url_format.format(platform=platform, tag=tag)
|
||||
r = requests.get(url, stream=True)
|
||||
r = requests.get(url, stream=True, timeout=REQUESTS_TIMEOUT)
|
||||
# pylint: disable=no-member
|
||||
if r.status_code != requests.codes.ok:
|
||||
if VERBOSE:
|
||||
|
|
@ -438,7 +440,7 @@ def clean_library_name(assumed_library_name):
|
|||
.replace("_circuitpython_", "_")
|
||||
.replace("-", "_")
|
||||
)
|
||||
if assumed_library_name in not_standard_names.keys():
|
||||
if assumed_library_name in not_standard_names:
|
||||
return not_standard_names[assumed_library_name]
|
||||
return assumed_library_name
|
||||
|
||||
|
|
@ -516,7 +518,7 @@ def extract_metadata(path):
|
|||
logger.info("%s", path)
|
||||
if path.endswith(".py"):
|
||||
result["mpy"] = False
|
||||
with open(path, encoding="utf-8") as source_file:
|
||||
with open(path, "r", encoding="utf-8") as source_file:
|
||||
content = source_file.read()
|
||||
#: The regex used to extract ``__version__`` and ``__repo__`` assignments.
|
||||
dunder_key_val = r"""(__\w+__)(?:\s*:\s*\w+)?\s*=\s*(?:['"]|\(\s)(.+)['"]"""
|
||||
|
|
@ -692,7 +694,7 @@ def get_bundle(bundle, tag):
|
|||
for platform, github_string in PLATFORMS.items():
|
||||
url = bundle.url_format.format(platform=github_string, tag=tag)
|
||||
logger.info("Downloading bundle: %s", url)
|
||||
r = requests.get(url, stream=True)
|
||||
r = requests.get(url, stream=True, timeout=REQUESTS_TIMEOUT)
|
||||
# pylint: disable=no-member
|
||||
if r.status_code != requests.codes.ok:
|
||||
logger.warning("Unable to connect to %s", url)
|
||||
|
|
@ -702,9 +704,9 @@ def get_bundle(bundle, tag):
|
|||
temp_zip = bundle.zip.format(platform=platform)
|
||||
with click.progressbar(r.iter_content(1024), length=total_size) as pbar, open(
|
||||
temp_zip, "wb"
|
||||
) as f:
|
||||
) as zip_fp:
|
||||
for chunk in pbar:
|
||||
f.write(chunk)
|
||||
zip_fp.write(chunk)
|
||||
pbar.update(len(chunk))
|
||||
logger.info("Saved to %s", temp_zip)
|
||||
temp_dir = bundle.dir.format(platform=platform)
|
||||
|
|
@ -750,10 +752,10 @@ def get_bundles_dict():
|
|||
"""
|
||||
bundle_dict = get_bundles_local_dict()
|
||||
try:
|
||||
with open(BUNDLE_CONFIG_OVERWRITE) as bundle_config_json:
|
||||
with open(BUNDLE_CONFIG_OVERWRITE, "rb") as bundle_config_json:
|
||||
bundle_config = json.load(bundle_config_json)
|
||||
except (FileNotFoundError, json.decoder.JSONDecodeError):
|
||||
with open(BUNDLE_CONFIG_FILE) as bundle_config_json:
|
||||
with open(BUNDLE_CONFIG_FILE, "rb") as bundle_config_json:
|
||||
bundle_config = json.load(bundle_config_json)
|
||||
for name, bundle in bundle_config.items():
|
||||
if bundle not in bundle_dict.values():
|
||||
|
|
@ -768,7 +770,7 @@ def get_bundles_local_dict():
|
|||
:return: Raw dictionary from the config file(s).
|
||||
"""
|
||||
try:
|
||||
with open(BUNDLE_CONFIG_LOCAL) as bundle_config_json:
|
||||
with open(BUNDLE_CONFIG_LOCAL, "rb") as bundle_config_json:
|
||||
bundle_config = json.load(bundle_config_json)
|
||||
if not isinstance(bundle_config, dict) or not bundle_config:
|
||||
logger.error("Local bundle list invalid. Skipped.")
|
||||
|
|
@ -807,7 +809,9 @@ def get_circuitpython_version(device_path):
|
|||
:return: A tuple with the version string for CircuitPython and the board ID string.
|
||||
"""
|
||||
try:
|
||||
with open(os.path.join(device_path, "boot_out.txt")) as boot:
|
||||
with open(
|
||||
os.path.join(device_path, "boot_out.txt"), "r", encoding="utf-8"
|
||||
) as boot:
|
||||
version_line = boot.readline()
|
||||
circuit_python = version_line.split(";")[0].split(" ")[-3]
|
||||
board_line = boot.readline()
|
||||
|
|
@ -885,7 +889,7 @@ def get_dependencies(*requested_libraries, mod_names, to_install=()):
|
|||
# If nothing is requested, we're done
|
||||
return _to_install
|
||||
|
||||
for library in _requested_libraries:
|
||||
for library in list(_requested_libraries):
|
||||
if library not in _to_install:
|
||||
_to_install = _to_install + (library,)
|
||||
# get the requirements.txt from bundle
|
||||
|
|
@ -923,7 +927,7 @@ def get_latest_release_from_url(url):
|
|||
"""
|
||||
|
||||
logger.info("Requesting redirect information: %s", url)
|
||||
response = requests.head(url)
|
||||
response = requests.head(url, timeout=REQUESTS_TIMEOUT)
|
||||
responseurl = response.url
|
||||
if response.is_redirect:
|
||||
responseurl = response.headers["Location"]
|
||||
|
|
@ -945,7 +949,7 @@ def get_modules(path):
|
|||
return result
|
||||
single_file_py_mods = glob.glob(os.path.join(path, "*.py"))
|
||||
single_file_mpy_mods = glob.glob(os.path.join(path, "*.mpy"))
|
||||
directory_mods = [
|
||||
package_dir_mods = [
|
||||
d
|
||||
for d in glob.glob(os.path.join(path, "*", ""))
|
||||
if not os.path.basename(os.path.normpath(d)).startswith(".")
|
||||
|
|
@ -955,18 +959,18 @@ def get_modules(path):
|
|||
metadata = extract_metadata(sfm)
|
||||
metadata["path"] = sfm
|
||||
result[os.path.basename(sfm).replace(".py", "").replace(".mpy", "")] = metadata
|
||||
for dm in directory_mods:
|
||||
name = os.path.basename(os.path.dirname(dm))
|
||||
py_files = glob.glob(os.path.join(dm, "*.py"))
|
||||
mpy_files = glob.glob(os.path.join(dm, "*.mpy"))
|
||||
for package_path in package_dir_mods:
|
||||
name = os.path.basename(os.path.dirname(package_path))
|
||||
py_files = glob.glob(os.path.join(package_path, "*.py"))
|
||||
mpy_files = glob.glob(os.path.join(package_path, "*.mpy"))
|
||||
all_files = py_files + mpy_files
|
||||
# default value
|
||||
result[name] = {"path": dm, "mpy": bool(mpy_files)}
|
||||
result[name] = {"path": package_path, "mpy": bool(mpy_files)}
|
||||
# explore all the submodules to detect bad ones
|
||||
for source in [f for f in all_files if not os.path.basename(f).startswith(".")]:
|
||||
metadata = extract_metadata(source)
|
||||
if "__version__" in metadata:
|
||||
metadata["path"] = dm
|
||||
metadata["path"] = package_path
|
||||
result[name] = metadata
|
||||
# break now if any of the submodules has a bad format
|
||||
if metadata["__version__"] == BAD_FILE_FORMAT:
|
||||
|
|
@ -976,7 +980,7 @@ def get_modules(path):
|
|||
|
||||
# pylint: disable=too-many-locals,too-many-branches
|
||||
def install_module(
|
||||
device_path, device_modules, name, py, mod_names
|
||||
device_path, device_modules, name, pyext, mod_names
|
||||
): # pragma: no cover
|
||||
"""
|
||||
Finds a connected device and installs a given module name if it
|
||||
|
|
@ -987,7 +991,7 @@ def install_module(
|
|||
:param str device_path: The path to the connected board.
|
||||
:param list(dict) device_modules: List of module metadata from the device.
|
||||
:param str name: Name of module to install
|
||||
:param bool py: Boolean to specify if the module should be installed from
|
||||
:param bool pyext: Boolean to specify if the module should be installed from
|
||||
source or from a pre-compiled module
|
||||
:param mod_names: Dictionary of metadata from modules that can be generated
|
||||
with get_bundle_versions()
|
||||
|
|
@ -1004,7 +1008,7 @@ def install_module(
|
|||
if name in device_modules:
|
||||
click.echo("'{}' is already installed.".format(name))
|
||||
return
|
||||
if py:
|
||||
if pyext:
|
||||
# Use Python source for module.
|
||||
source_path = metadata["path"] # Path to Python source version.
|
||||
if os.path.isdir(source_path):
|
||||
|
|
@ -1232,7 +1236,9 @@ def freeze(ctx, requirement): # pragma: no cover
|
|||
cwd = os.path.abspath(os.getcwd())
|
||||
for i, module in enumerate(output):
|
||||
output[i] += "\n"
|
||||
with open(cwd + "/" + "requirements.txt", "w", newline="\n") as file:
|
||||
with open(
|
||||
cwd + "/" + "requirements.txt", "w", newline="\n", encoding="utf-8"
|
||||
) as file:
|
||||
file.truncate(0)
|
||||
file.writelines(output)
|
||||
else:
|
||||
|
|
@ -1284,12 +1290,12 @@ def list_cli(ctx): # pragma: no cover
|
|||
@click.argument(
|
||||
"modules", required=False, nargs=-1, shell_complete=completion_for_install
|
||||
)
|
||||
@click.option("--py", is_flag=True)
|
||||
@click.option("pyext", "--py", is_flag=True)
|
||||
@click.option("-r", "--requirement", type=click.Path(exists=True, dir_okay=False))
|
||||
@click.option("--auto/--no-auto", "-a/-A")
|
||||
@click.option("--auto-file", default="code.py")
|
||||
@click.pass_context
|
||||
def install(ctx, modules, py, requirement, auto, auto_file): # pragma: no cover
|
||||
def install(ctx, modules, pyext, requirement, auto, auto_file): # pragma: no cover
|
||||
"""
|
||||
Install a named module(s) onto the device. Multiple modules
|
||||
can be installed at once by providing more than one module name, each
|
||||
|
|
@ -1308,8 +1314,8 @@ def install(ctx, modules, py, requirement, auto, auto_file): # pragma: no cover
|
|||
for module, metadata in available_modules.items():
|
||||
mod_names[module.replace(".py", "").lower()] = metadata
|
||||
if requirement:
|
||||
with open(requirement, "r") as fp:
|
||||
requirements_txt = fp.read()
|
||||
with open(requirement, "r", encoding="utf-8") as rfile:
|
||||
requirements_txt = rfile.read()
|
||||
requested_installs = libraries_from_requirements(requirements_txt)
|
||||
elif auto:
|
||||
auto_file = os.path.join(ctx.obj["DEVICE_PATH"], auto_file)
|
||||
|
|
@ -1325,7 +1331,7 @@ def install(ctx, modules, py, requirement, auto, auto_file): # pragma: no cover
|
|||
click.echo(f"Ready to install: {to_install}\n")
|
||||
for library in to_install:
|
||||
install_module(
|
||||
ctx.obj["DEVICE_PATH"], device_modules, library, py, mod_names
|
||||
ctx.obj["DEVICE_PATH"], device_modules, library, pyext, mod_names
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1397,10 +1403,13 @@ def uninstall(ctx, module): # pragma: no cover
|
|||
)
|
||||
)
|
||||
@click.option(
|
||||
"--all", is_flag=True, help="Update all modules without Major Version warnings."
|
||||
"update_all",
|
||||
"--all",
|
||||
is_flag=True,
|
||||
help="Update all modules without Major Version warnings.",
|
||||
)
|
||||
@click.pass_context
|
||||
def update(ctx, all): # pragma: no cover
|
||||
def update(ctx, update_all): # pragma: no cover
|
||||
"""
|
||||
Checks for out-of-date modules on the connected CIRCUITPYTHON device, and
|
||||
prompts the user to confirm updating such modules.
|
||||
|
|
@ -1414,10 +1423,10 @@ def update(ctx, all): # pragma: no cover
|
|||
]
|
||||
if modules:
|
||||
click.echo("Found {} module[s] needing update.".format(len(modules)))
|
||||
if not all:
|
||||
if not update_all:
|
||||
click.echo("Please indicate which modules you wish to update:\n")
|
||||
for module in modules:
|
||||
update_flag = all
|
||||
update_flag = update_all
|
||||
if VERBOSE:
|
||||
click.echo(
|
||||
"Device version: {}, Bundle version: {}".format(
|
||||
|
|
@ -1484,12 +1493,12 @@ def bundle_show(modules):
|
|||
Show the list of bundles, default and local, with URL, current version
|
||||
and latest version retrieved from the web.
|
||||
"""
|
||||
locals = get_bundles_local_dict().values()
|
||||
local_bundles = get_bundles_local_dict().values()
|
||||
bundles = get_bundles_list()
|
||||
available_modules = get_bundle_versions(bundles)
|
||||
|
||||
for bundle in bundles:
|
||||
if bundle.key in locals:
|
||||
if bundle.key in local_bundles:
|
||||
click.secho(bundle.key, fg="yellow")
|
||||
else:
|
||||
click.secho(bundle.key, fg="green")
|
||||
|
|
@ -1513,40 +1522,44 @@ def bundle_add(bundle):
|
|||
"""
|
||||
bundles_dict = get_bundles_local_dict()
|
||||
modified = False
|
||||
for bun in bundle:
|
||||
for bundle_repo in bundle:
|
||||
# cleanup in case seombody pastes the URL to the repo/releases
|
||||
bun = re.sub(r"https?://github.com/([^/]+/[^/]+)(/.*)?", r"\1", bun)
|
||||
if bun in bundles_dict.values():
|
||||
bundle_repo = re.sub(
|
||||
r"https?://github.com/([^/]+/[^/]+)(/.*)?", r"\1", bundle_repo
|
||||
)
|
||||
if bundle_repo in bundles_dict.values():
|
||||
click.secho("Bundle already in list.", fg="yellow")
|
||||
click.secho(" " + bun, fg="yellow")
|
||||
click.secho(" " + bundle_repo, fg="yellow")
|
||||
continue
|
||||
try:
|
||||
bb = Bundle(bun)
|
||||
bundle_added = Bundle(bundle_repo)
|
||||
except ValueError:
|
||||
click.secho(
|
||||
"Bundle string invalid, expecting github URL or `user/repository` string.",
|
||||
fg="red",
|
||||
)
|
||||
click.secho(" " + bun, fg="red")
|
||||
click.secho(" " + bundle_repo, fg="red")
|
||||
continue
|
||||
result = requests.get("https://github.com/" + bun)
|
||||
result = requests.get(
|
||||
"https://github.com/" + bundle_repo, timeout=REQUESTS_TIMEOUT
|
||||
)
|
||||
# pylint: disable=no-member
|
||||
if result.status_code == requests.codes.NOT_FOUND:
|
||||
click.secho("Bundle invalid, the repository doesn't exist (404).", fg="red")
|
||||
click.secho(" " + bun, fg="red")
|
||||
click.secho(" " + bundle_repo, fg="red")
|
||||
continue
|
||||
# pylint: enable=no-member
|
||||
if not bb.validate():
|
||||
if not bundle_added.validate():
|
||||
click.secho(
|
||||
"Bundle invalid, is the repository a valid circup bundle ?", fg="red"
|
||||
)
|
||||
click.secho(" " + bun, fg="red")
|
||||
click.secho(" " + bundle_repo, fg="red")
|
||||
continue
|
||||
# note: use bun as the dictionary key for uniqueness
|
||||
bundles_dict[bun] = bun
|
||||
bundles_dict[bundle_repo] = bundle_repo
|
||||
modified = True
|
||||
click.echo("Added " + bun)
|
||||
click.echo(" " + bb.url)
|
||||
click.echo("Added " + bundle_repo)
|
||||
click.echo(" " + bundle_added.url)
|
||||
if modified:
|
||||
# save the bundles list
|
||||
save_local_bundles(bundles_dict)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
# SPDX-FileCopyrightText: 2019 Nicholas Tollervey, written for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
# pylint: disable=too-many-lines,use-implicit-booleaness-not-comparison
|
||||
# pylint: disable=invalid-name,unnecessary-dunder-call
|
||||
"""
|
||||
Unit tests for the circup module.
|
||||
|
||||
|
|
@ -39,12 +41,12 @@ import circup
|
|||
|
||||
|
||||
TEST_BUNDLE_CONFIG_JSON = "tests/test_bundle_config.json"
|
||||
with open(TEST_BUNDLE_CONFIG_JSON) as tbc:
|
||||
with open(TEST_BUNDLE_CONFIG_JSON, "rb") as tbc:
|
||||
TEST_BUNDLE_DATA = json.load(tbc)
|
||||
TEST_BUNDLE_NAME = TEST_BUNDLE_DATA["test_bundle"]
|
||||
|
||||
TEST_BUNDLE_CONFIG_LOCAL_JSON = "tests/test_bundle_config_local.json"
|
||||
with open(TEST_BUNDLE_CONFIG_LOCAL_JSON) as tbc:
|
||||
with open(TEST_BUNDLE_CONFIG_LOCAL_JSON, "rb") as tbc:
|
||||
TEST_BUNDLE_LOCAL_DATA = json.load(tbc)
|
||||
|
||||
|
||||
|
|
@ -546,7 +548,7 @@ def test_get_latest_release_from_url():
|
|||
with mock.patch("circup.requests.head", return_value=response) as mock_get:
|
||||
result = circup.get_latest_release_from_url(expected_url)
|
||||
assert result == "20190903"
|
||||
mock_get.assert_called_once_with(expected_url)
|
||||
mock_get.assert_called_once_with(expected_url, timeout=mock.ANY)
|
||||
|
||||
|
||||
def test_extract_metadata_python():
|
||||
|
|
@ -563,7 +565,7 @@ def test_extract_metadata_python():
|
|||
path = "foo.py"
|
||||
with mock.patch("builtins.open", mock.mock_open(read_data=code)) as mock_open:
|
||||
result = circup.extract_metadata(path)
|
||||
mock_open.assert_called_once_with(path, encoding="utf-8")
|
||||
mock_open.assert_called_once_with(path, "r", encoding="utf-8")
|
||||
assert len(result) == 3
|
||||
assert result["__version__"] == "1.1.4"
|
||||
assert result["__repo__"] == "https://github.com/adafruit/SomeLibrary.git"
|
||||
|
|
@ -598,9 +600,9 @@ def test_find_modules():
|
|||
Ensure that the expected list of Module instances is returned given the
|
||||
metadata dictionary fixtures for device and bundle modules.
|
||||
"""
|
||||
with open("tests/device.json") as f:
|
||||
with open("tests/device.json", "rb") as f:
|
||||
device_modules = json.load(f)
|
||||
with open("tests/bundle.json") as f:
|
||||
with open("tests/bundle.json", "rb") as f:
|
||||
bundle_modules = json.load(f)
|
||||
with mock.patch(
|
||||
"circup.get_device_versions", return_value=device_modules
|
||||
|
|
@ -698,7 +700,9 @@ def test_get_circuitpython_version():
|
|||
)
|
||||
with mock.patch("builtins.open", mock.mock_open(read_data=data_no_id)) as mock_open:
|
||||
assert circup.get_circuitpython_version(device_path) == ("4.1.0", "")
|
||||
mock_open.assert_called_once_with(os.path.join(device_path, "boot_out.txt"))
|
||||
mock_open.assert_called_once_with(
|
||||
os.path.join(device_path, "boot_out.txt"), "r", encoding="utf-8"
|
||||
)
|
||||
data_with_id = data_no_id + "\r\n" "Board ID:this_is_a_board"
|
||||
with mock.patch(
|
||||
"builtins.open", mock.mock_open(read_data=data_with_id)
|
||||
|
|
@ -707,7 +711,9 @@ def test_get_circuitpython_version():
|
|||
"4.1.0",
|
||||
"this_is_a_board",
|
||||
)
|
||||
mock_open.assert_called_once_with(os.path.join(device_path, "boot_out.txt"))
|
||||
mock_open.assert_called_once_with(
|
||||
os.path.join(device_path, "boot_out.txt"), "r", encoding="utf-8"
|
||||
)
|
||||
|
||||
|
||||
def test_get_device_versions():
|
||||
|
|
@ -961,7 +967,7 @@ def test_get_bundle_network_error():
|
|||
"https://github.com/" + TEST_BUNDLE_NAME + "/releases/download"
|
||||
"/{tag}/adafruit-circuitpython-bundle-py-{tag}.zip".format(tag=tag)
|
||||
)
|
||||
mock_requests.get.assert_called_once_with(url, stream=True)
|
||||
mock_requests.get.assert_called_once_with(url, stream=True, timeout=mock.ANY)
|
||||
assert mock_logger.warning.call_count == 1
|
||||
mock_requests.get().raise_for_status.assert_called_once_with()
|
||||
|
||||
|
|
@ -971,11 +977,11 @@ def test_show_command():
|
|||
test_show_command
|
||||
"""
|
||||
runner = CliRunner()
|
||||
TEST_BUNDLE_MODULES = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=TEST_BUNDLE_MODULES):
|
||||
test_bundle_modules = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=test_bundle_modules):
|
||||
result = runner.invoke(circup.show)
|
||||
assert result.exit_code == 0
|
||||
assert all([m.replace(".py", "") in result.output for m in TEST_BUNDLE_MODULES])
|
||||
assert all(m.replace(".py", "") in result.output for m in test_bundle_modules)
|
||||
|
||||
|
||||
def test_show_match_command():
|
||||
|
|
@ -983,8 +989,8 @@ def test_show_match_command():
|
|||
test_show_match_command
|
||||
"""
|
||||
runner = CliRunner()
|
||||
TEST_BUNDLE_MODULES = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=TEST_BUNDLE_MODULES):
|
||||
test_bundle_modules = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=test_bundle_modules):
|
||||
result = runner.invoke(circup.show, ["t"])
|
||||
assert result.exit_code == 0
|
||||
assert "one" not in result.output
|
||||
|
|
@ -995,8 +1001,8 @@ def test_show_match_py_command():
|
|||
Check that py does not match the .py extention in the module names
|
||||
"""
|
||||
runner = CliRunner()
|
||||
TEST_BUNDLE_MODULES = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=TEST_BUNDLE_MODULES):
|
||||
test_bundle_modules = ["one.py", "two.py", "three.py"]
|
||||
with mock.patch("circup.get_bundle_versions", return_value=test_bundle_modules):
|
||||
result = runner.invoke(circup.show, ["py"])
|
||||
assert result.exit_code == 0
|
||||
assert "0 shown" in result.output
|
||||
|
|
|
|||
Loading…
Reference in a new issue