diff --git a/MANIFEST.in b/MANIFEST.in
index dad2e7d..ffa679b 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,3 +4,4 @@ recursive-include octoprint_netconnectd/translations *
include LICENSE
include requirements.txt
include README.md
+graft octoprint_netconnectd/scripts
\ No newline at end of file
diff --git a/octoprint_netconnectd/scripts/update_script.py b/octoprint_netconnectd/scripts/update_script.py
index bb10f66..d98cb9e 100644
--- a/octoprint_netconnectd/scripts/update_script.py
+++ b/octoprint_netconnectd/scripts/update_script.py
@@ -16,8 +16,8 @@
from octoprint.plugins.softwareupdate import exceptions
from octoprint.settings import _default_basedir
-from octoprint_mrbeam.util.pip_util import get_version_of_pip_module, \
- get_pip_caller # TODO check how to be independent of mrbeam plugin
+from octoprint_netconnectd.util.pip_util import get_version_of_pip_module, \
+ get_pip_caller
from requests.adapters import HTTPAdapter
from urllib3 import Retry
@@ -25,11 +25,12 @@
_logger = logging.getLogger("octoprint.plugins.netconnectd.softwareupdate.updatescript")
-UPDATE_CONFIG_NAME = "netconnectd_plugin"
+UPDATE_CONFIG_NAME = "netconnectd"
REPO_NAME = "OctoPrint-Netconnectd"
MAIN_SRC_FOLDER_NAME = "octoprint_netconnectd"
PLUGIN_NAME = "OctoPrint-Netconnectd"
DEFAULT_OPRINT_VENV = "/home/pi/oprint/bin/pip"
+PIP_WHEEL_TEMP_FOLDER = "/tmp/wheelhouse"
"""
copy pasta of mrbeam plugin update script
@@ -96,14 +97,6 @@ def _parse_arguments():
default=None,
help="Path of target zip file on local system",
)
- parser.add_argument(
- "--target_version",
- action="store",
- type=str,
- dest="target_version",
- default=None,
- help="Version number of the target",
- )
parser.add_argument(
"folder",
type=str,
@@ -175,13 +168,25 @@ def build_wheels(build_queue):
None
"""
+ try:
+ if not os.path.isdir(PIP_WHEEL_TEMP_FOLDER):
+ os.mkdir(PIP_WHEEL_TEMP_FOLDER)
+ except OSError as e:
+ raise RuntimeError("can't create wheel tmp folder {} - {}".format(PIP_WHEEL_TEMP_FOLDER, e))
+
for venv, packages in build_queue.items():
+ tmp_folder = os.path.join(PIP_WHEEL_TEMP_FOLDER, re.search(r"\w+((?=\/venv)|(?=\/bin))", venv).group(0))
+ if os.path.isdir(tmp_folder):
+ try:
+ os.system("sudo rm -r {}".format(tmp_folder))
+ except Exception as e:
+ raise RuntimeError("can't delete pip wheel temp folder {} - {}".format(tmp_folder, e))
pip_args = [
"wheel",
"--no-python-version-warning",
"--disable-pip-version-check",
- "--wheel-dir=/tmp/wheelhouse", # Build wheels into
, where the default is the current working directory.
+ "--wheel-dir={}".format(tmp_folder), # Build wheels into , where the default is the current working directory.
"--no-dependencies", # Don't install package dependencies.
]
for package in packages:
@@ -213,20 +218,20 @@ def install_wheels(install_queue):
raise RuntimeError("install queue is not a dict")
for venv, packages in install_queue.items():
-
+ tmp_folder = os.path.join(PIP_WHEEL_TEMP_FOLDER, re.search(r"\w+((?=\/venv)|(?=\/bin))", venv).group(0))
pip_args = [
"install",
"--no-python-version-warning",
"--disable-pip-version-check",
"--upgrade", # Upgrade all specified packages to the newest available version. The handling of dependencies depends on the upgrade-strategy used.
"--no-index", # Ignore package index (only looking at --find-links URLs instead).
- "--find-links=/tmp/wheelhouse", # If a URL or path to an html file, then parse for links to archives such as sdist (.tar.gz) or wheel (.whl) files. If a local path or file:// URL that's a directory, then look for archives in the directory listing. Links to VCS project URLs are not supported.
+ "--find-links={}".format(tmp_folder), # If a URL or path to an html file, then parse for links to archives such as sdist (.tar.gz) or wheel (.whl) files. If a local path or file:// URL that's a directory, then look for archives in the directory listing. Links to VCS project URLs are not supported.
"--no-dependencies", # Don't install package dependencies.
]
for package in packages:
pip_args.append(
- "{package}=={package_version}".format(
- package=package["name"], package_version=package["target"]
+ "{package}".format(
+ package=package["name"]
)
)
@@ -239,14 +244,14 @@ def install_wheels(install_queue):
)
-def build_queue(update_info, dependencies, target, plugin_archive):
+def build_queue(update_info, dependencies, plugin_archive):
"""
build the queue of packages to install
Args:
update_info: a dict of informations how to update the packages
dependencies: a list dicts of dependencies [{"name", "version"}]
- target: target of the Mr Beam Plugin to update to
+ plugin_archive: path to archive of the plugin
Returns:
install_queue: dict of venvs with a list of package dicts {"": [{"name", "archive", "target"}]
@@ -259,7 +264,7 @@ def build_queue(update_info, dependencies, target, plugin_archive):
{
"name": PLUGIN_NAME,
"archive": plugin_archive,
- "target": target,
+ "target": '',
}
)
print("dependencies - {}".format(dependencies))
@@ -322,7 +327,7 @@ def run_update():
update_info = get_update_info()
install_queue = build_queue(
- update_info, dependencies, args.target_version, args.archive
+ update_info, dependencies, args.archive
)
print("install_queue", install_queue)
@@ -367,7 +372,7 @@ def loadPluginTarget(archive, folder):
folder: working directory
Returns:
- (zip_file_path, target_version) - path of the downloaded zip file and target version string
+ zip_file_path - path of the downloaded zip file
"""
# download target repo zip
@@ -421,17 +426,7 @@ def loadPluginTarget(archive, folder):
except IOError:
raise RuntimeError("Could not copy update_script to working directory")
- # get target version
- exec(
- open(
- os.path.join(
- plugin_extracted_path_folder, MAIN_SRC_FOLDER_NAME, "__version.py"
- )
- ).read()
- )
- target_version = __version__
-
- return zip_file_path, target_version
+ return zip_file_path
def main():
@@ -445,9 +440,9 @@ def main():
args = _parse_arguments()
if args.call:
- if args.archive is None or args.target_version is None:
+ if args.archive is None:
raise RuntimeError(
- "Could not run update archive or target_version is missing"
+ "Could not run update archive is missing"
)
run_update()
else:
@@ -460,7 +455,7 @@ def main():
raise RuntimeError("Could not update, base folder is not writable")
update_info = get_update_info()
- archive, target_version = loadPluginTarget(
+ archive = loadPluginTarget(
update_info.get(UPDATE_CONFIG_NAME)
.get("pip")
.format(target_version=args.target),
@@ -470,8 +465,7 @@ def main():
# call new update script with args
sys.argv = [
"--call=true",
- "--archive={}".format(archive),
- "--target_version={}".format(target_version),
+ "--archive={}".format(archive)
] + sys.argv[1:]
try:
result = subprocess.call(
diff --git a/octoprint_netconnectd/util/__init__.py b/octoprint_netconnectd/util/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/octoprint_netconnectd/util/cmd_exec.py b/octoprint_netconnectd/util/cmd_exec.py
new file mode 100644
index 0000000..57c544f
--- /dev/null
+++ b/octoprint_netconnectd/util/cmd_exec.py
@@ -0,0 +1,78 @@
+"""
+copy pasta of octoprint_mrbeam/util/cmd_exec.py
+only changed the logging to be mrbeam plugin independend
+"""
+import logging
+import subprocess
+from logging import DEBUG
+
+
+def exec_cmd(cmd, log=True, shell=True, loglvl=DEBUG):
+ """
+ Executes a system command
+ :param cmd:
+ :return: True if system returncode was 0,
+ False if the command returned with an error,
+ None if there was an exception.
+ """
+ _logger = logging.getLogger(__name__ + ".exec_cmd")
+ code = None
+ if log:
+ _logger.log(loglvl, "cmd=%s", cmd)
+ try:
+ code = subprocess.call(cmd, shell=shell)
+ except Exception as e:
+ _logger.debug(
+ "Failed to execute command '%s', return code: %s, Exception: %s",
+ cmd,
+ code,
+ e,
+ )
+ return None
+ if code != 0 and log:
+ _logger.info("cmd= '%s', return code: '%s'", code)
+ return code == 0
+
+
+def exec_cmd_output(cmd, log=True, shell=False, loglvl=DEBUG):
+ """
+ Executes a system command and returns its output.
+ :param cmd:
+ :return: Tuple(String:output , int return_code)
+ """
+ _logger = logging.getLogger(__name__ + "exec_cmd_output")
+ output = None
+ code = 0
+ if log:
+ _logger.log(loglvl, "cmd='%s'", cmd)
+ try:
+ output = subprocess.check_output(cmd, shell=shell, stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ code = e.returncode
+
+ if not log:
+ cmd = cmd[:50] + "..." if len(cmd) > 30 else cmd
+ if e.output is not None:
+ output = e.output[:30] + "..." if len(e.output) > 30 else e.output
+ else:
+ output = e.output
+ _logger.log(
+ loglvl,
+ "Failed to execute command '%s', return code: %s, output: '%s'",
+ cmd,
+ e.returncode,
+ output,
+ )
+
+ except Exception as e:
+ code = 99
+ output = "{e}: {o}".format(e=e, o=output)
+ _logger.log(
+ loglvl,
+ "Failed to execute command '%s', return code: %s, output: '%s'",
+ cmd,
+ None,
+ output,
+ )
+
+ return output, code
diff --git a/octoprint_netconnectd/util/pip_util.py b/octoprint_netconnectd/util/pip_util.py
new file mode 100644
index 0000000..8991491
--- /dev/null
+++ b/octoprint_netconnectd/util/pip_util.py
@@ -0,0 +1,109 @@
+"""
+copy pasta of octoprint_mrbeam/util/pip_util.py
+only changed the logging to be mrbeam plugin independend
+"""
+import logging
+
+from octoprint.plugins.softwareupdate.updaters.pip import _get_pip_caller
+from octoprint.util.pip import PipCaller
+from cmd_exec import exec_cmd_output
+
+DISABLE_PIP_CHECK = "--disable-pip-version-check"
+DISABLE_PY_WARNING = "--no-python-version-warning"
+
+# Dictionary of package versions available at different locations
+# {
+# /home/pi/oprint/bin/pip : {
+# "OctoPrint x.x.x",
+# ...
+# },
+# /usr/share/iobeam/venv/bin/pip : {
+# "iobeam y.y.y",
+# ...
+# }
+# }
+_pip_package_version_lists = {}
+
+
+def get_version_of_pip_module(pip_name, pip_command=None, disable_pip_ver_check=True):
+ _logger = logging.getLogger(__name__ + ".get_version_of_pip_module")
+ global _pip_package_version_lists
+ version = None
+ returncode = -1
+ if pip_command is None:
+ pip_command = "pip"
+ elif isinstance(pip_command, list):
+ pip_command = " ".join(pip_command)
+ # Checking for pip version outdate takes extra time and text output.
+ # NOTE: Older versions of pip do not have the --no-python-version-warning flag
+ for disabled in [
+ DISABLE_PIP_CHECK,
+ ]: # DISABLE_PY_WARNING]:
+ if disable_pip_ver_check and not disabled in pip_command:
+ pip_command += " " + disabled
+ venv_packages = _pip_package_version_lists.get(pip_command, None)
+
+ if venv_packages is None:
+ # perform a pip discovery and remember it for next time
+ command = "{pip_command} list".format(pip_command=pip_command)
+ _logger.debug("refreshing list of installed packages (%s list)", pip_command)
+ output, returncode = exec_cmd_output(command, shell=True, log=False)
+ if returncode == 0:
+ venv_packages = output.splitlines()
+ _pip_package_version_lists[pip_command] = venv_packages
+ elif returncode == 127:
+ _logger.error(
+ "`%s` was not found in local $PATH (returncode %s)",
+ pip_command,
+ returncode,
+ )
+ return None
+ else:
+ _logger.warning("`%s list` returned code %s", pip_command, returncode)
+ return None
+ # Go through the package list available in our venv
+ for line in venv_packages:
+ token = line.split()
+ if len(token) >= 2 and token[0] == pip_name:
+ version = token[1]
+ break
+ _logger.debug("%s==%s", pip_name, version)
+ return version
+
+
+def get_pip_caller(venv, _logger=None):
+ """
+ gets the pip caller of the givenv venv
+
+ Args:
+ venv: path to venv
+ _logger: logger to log call, stdout and stderr of the pip caller
+
+ Returns:
+ PipCaller of the venv
+ """
+ pip_caller = _get_pip_caller(command=venv)
+ if not isinstance(pip_caller, PipCaller):
+ raise RuntimeError("Can't run pip", None)
+
+ def _log_call(*lines):
+ _log(lines, prefix=" ", stream="call")
+
+ def _log_stdout(*lines):
+ _log(lines, prefix=">", stream="stdout")
+
+ def _log_stderr(*lines):
+ _log(lines, prefix="!", stream="stderr")
+
+ def _log(lines, prefix=None, stream=None, strip=True):
+ if strip:
+ lines = map(lambda x: x.strip(), lines)
+ for line in lines:
+ print(u"{} {}".format(prefix, line))
+
+ if _logger is not None:
+ pip_caller.on_log_call = _log_call
+ pip_caller.on_log_stdout = _log_stdout
+ pip_caller.on_log_stderr = _log_stderr
+
+ return pip_caller