forked from platformio/platformio-core
Refactor HTTP related operations
This commit is contained in:
@ -15,4 +15,8 @@ disable=
|
|||||||
useless-object-inheritance,
|
useless-object-inheritance,
|
||||||
useless-import-alias,
|
useless-import-alias,
|
||||||
fixme,
|
fixme,
|
||||||
bad-option-value
|
bad-option-value,
|
||||||
|
|
||||||
|
; PY2 Compat
|
||||||
|
super-with-arguments,
|
||||||
|
raise-missing-from
|
||||||
|
@ -26,7 +26,7 @@ from os import environ, getenv, listdir, remove
|
|||||||
from os.path import dirname, isdir, isfile, join, realpath
|
from os.path import dirname, isdir, isfile, join, realpath
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from platformio import __version__, exception, fs, proc, util
|
from platformio import __version__, exception, fs, proc
|
||||||
from platformio.compat import WINDOWS, dump_json_to_unicode, hashlib_encode_data
|
from platformio.compat import WINDOWS, dump_json_to_unicode, hashlib_encode_data
|
||||||
from platformio.package.lockfile import LockFile
|
from platformio.package.lockfile import LockFile
|
||||||
from platformio.project.helpers import (
|
from platformio.project.helpers import (
|
||||||
@ -394,6 +394,9 @@ def is_disabled_progressbar():
|
|||||||
|
|
||||||
|
|
||||||
def get_cid():
|
def get_cid():
|
||||||
|
# pylint: disable=import-outside-toplevel
|
||||||
|
from platformio.clients.http import fetch_remote_content
|
||||||
|
|
||||||
cid = get_state_item("cid")
|
cid = get_state_item("cid")
|
||||||
if cid:
|
if cid:
|
||||||
return cid
|
return cid
|
||||||
@ -403,7 +406,7 @@ def get_cid():
|
|||||||
elif getenv("CHE_API", getenv("CHE_API_ENDPOINT")):
|
elif getenv("CHE_API", getenv("CHE_API_ENDPOINT")):
|
||||||
try:
|
try:
|
||||||
uid = json.loads(
|
uid = json.loads(
|
||||||
util.fetch_remote_content(
|
fetch_remote_content(
|
||||||
"{api}/user?token={token}".format(
|
"{api}/user?token={token}".format(
|
||||||
api=getenv("CHE_API", getenv("CHE_API_ENDPOINT")),
|
api=getenv("CHE_API", getenv("CHE_API_ENDPOINT")),
|
||||||
token=getenv("USER_TOKEN"),
|
token=getenv("USER_TOKEN"),
|
||||||
|
@ -67,7 +67,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
token = self.fetch_authentication_token()
|
token = self.fetch_authentication_token()
|
||||||
headers["Authorization"] = "Bearer %s" % token
|
headers["Authorization"] = "Bearer %s" % token
|
||||||
kwargs["headers"] = headers
|
kwargs["headers"] = headers
|
||||||
return self.request_json_data(*args, **kwargs)
|
return self.fetch_json_data(*args, **kwargs)
|
||||||
|
|
||||||
def login(self, username, password):
|
def login(self, username, password):
|
||||||
try:
|
try:
|
||||||
@ -79,7 +79,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
app.get_state_item("account", {}).get("email", "")
|
app.get_state_item("account", {}).get("email", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
data = self.request_json_data(
|
data = self.fetch_json_data(
|
||||||
"post", "/v1/login", data={"username": username, "password": password},
|
"post", "/v1/login", data={"username": username, "password": password},
|
||||||
)
|
)
|
||||||
app.set_state_item("account", data)
|
app.set_state_item("account", data)
|
||||||
@ -95,7 +95,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
app.get_state_item("account", {}).get("email", "")
|
app.get_state_item("account", {}).get("email", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
result = self.request_json_data(
|
result = self.fetch_json_data(
|
||||||
"post",
|
"post",
|
||||||
"/v1/login/code",
|
"/v1/login/code",
|
||||||
data={"client_id": client_id, "code": code, "redirect_uri": redirect_uri},
|
data={"client_id": client_id, "code": code, "redirect_uri": redirect_uri},
|
||||||
@ -107,7 +107,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
refresh_token = self.get_refresh_token()
|
refresh_token = self.get_refresh_token()
|
||||||
self.delete_local_session()
|
self.delete_local_session()
|
||||||
try:
|
try:
|
||||||
self.request_json_data(
|
self.fetch_json_data(
|
||||||
"post", "/v1/logout", data={"refresh_token": refresh_token},
|
"post", "/v1/logout", data={"refresh_token": refresh_token},
|
||||||
)
|
)
|
||||||
except AccountError:
|
except AccountError:
|
||||||
@ -133,7 +133,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
app.get_state_item("account", {}).get("email", "")
|
app.get_state_item("account", {}).get("email", "")
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.request_json_data(
|
return self.fetch_json_data(
|
||||||
"post",
|
"post",
|
||||||
"/v1/registration",
|
"/v1/registration",
|
||||||
data={
|
data={
|
||||||
@ -153,7 +153,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
).get("auth_token")
|
).get("auth_token")
|
||||||
|
|
||||||
def forgot_password(self, username):
|
def forgot_password(self, username):
|
||||||
return self.request_json_data(
|
return self.fetch_json_data(
|
||||||
"post", "/v1/forgot", data={"username": username},
|
"post", "/v1/forgot", data={"username": username},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ class AccountClient(HTTPClient): # pylint:disable=too-many-public-methods
|
|||||||
return auth.get("access_token")
|
return auth.get("access_token")
|
||||||
if auth.get("refresh_token"):
|
if auth.get("refresh_token"):
|
||||||
try:
|
try:
|
||||||
data = self.request_json_data(
|
data = self.fetch_json_data(
|
||||||
"post",
|
"post",
|
||||||
"/v1/login",
|
"/v1/login",
|
||||||
headers={
|
headers={
|
||||||
|
@ -12,11 +12,24 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
|
||||||
import requests.adapters
|
import requests.adapters
|
||||||
from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error
|
from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error
|
||||||
|
|
||||||
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, util
|
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, util
|
||||||
from platformio.exception import PlatformioException
|
from platformio.exception import PlatformioException, UserSideException
|
||||||
|
|
||||||
|
|
||||||
|
PING_REMOTE_HOSTS = [
|
||||||
|
"140.82.118.3", # Github.com
|
||||||
|
"35.231.145.151", # Gitlab.com
|
||||||
|
"88.198.170.159", # platformio.org
|
||||||
|
"github.com",
|
||||||
|
"platformio.org",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class HTTPClientError(PlatformioException):
|
class HTTPClientError(PlatformioException):
|
||||||
@ -29,6 +42,15 @@ class HTTPClientError(PlatformioException):
|
|||||||
return self.message
|
return self.message
|
||||||
|
|
||||||
|
|
||||||
|
class InternetIsOffline(UserSideException):
|
||||||
|
|
||||||
|
MESSAGE = (
|
||||||
|
"You are not connected to the Internet.\n"
|
||||||
|
"PlatformIO needs the Internet connection to"
|
||||||
|
" download dependent packages or to work with PIO Account."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HTTPClient(object):
|
class HTTPClient(object):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, base_url,
|
self, base_url,
|
||||||
@ -57,7 +79,7 @@ class HTTPClient(object):
|
|||||||
def send_request(self, method, path, **kwargs):
|
def send_request(self, method, path, **kwargs):
|
||||||
# check Internet before and resolve issue with 60 seconds timeout
|
# check Internet before and resolve issue with 60 seconds timeout
|
||||||
# print(self, method, path, kwargs)
|
# print(self, method, path, kwargs)
|
||||||
util.internet_on(raise_exception=True)
|
ensure_internet_on(raise_exception=True)
|
||||||
|
|
||||||
# set default timeout
|
# set default timeout
|
||||||
if "timeout" not in kwargs:
|
if "timeout" not in kwargs:
|
||||||
@ -68,9 +90,18 @@ class HTTPClient(object):
|
|||||||
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
|
except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e:
|
||||||
raise HTTPClientError(str(e))
|
raise HTTPClientError(str(e))
|
||||||
|
|
||||||
def request_json_data(self, *args, **kwargs):
|
def fetch_json_data(self, *args, **kwargs):
|
||||||
response = self.send_request(*args, **kwargs)
|
cache_valid = kwargs.pop("cache_valid") if "cache_valid" in kwargs else None
|
||||||
return self.raise_error_from_response(response)
|
if not cache_valid:
|
||||||
|
return self.raise_error_from_response(self.send_request(*args, **kwargs))
|
||||||
|
cache_key = app.ContentCache.key_from_args(*args, kwargs)
|
||||||
|
with app.ContentCache() as cc:
|
||||||
|
result = cc.get(cache_key)
|
||||||
|
if result is not None:
|
||||||
|
return json.loads(result)
|
||||||
|
response = self.send_request(*args, **kwargs)
|
||||||
|
cc.set(cache_key, response.text, cache_valid)
|
||||||
|
return self.raise_error_from_response(response)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def raise_error_from_response(response, expected_codes=(200, 201, 202)):
|
def raise_error_from_response(response, expected_codes=(200, 201, 202)):
|
||||||
@ -84,3 +115,48 @@ class HTTPClient(object):
|
|||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
message = response.text
|
message = response.text
|
||||||
raise HTTPClientError(message, response)
|
raise HTTPClientError(message, response)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Helpers
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
@util.memoized(expire="10s")
|
||||||
|
def _internet_on():
|
||||||
|
timeout = 2
|
||||||
|
socket.setdefaulttimeout(timeout)
|
||||||
|
for host in PING_REMOTE_HOSTS:
|
||||||
|
try:
|
||||||
|
for var in ("HTTP_PROXY", "HTTPS_PROXY"):
|
||||||
|
if not os.getenv(var) and not os.getenv(var.lower()):
|
||||||
|
continue
|
||||||
|
requests.get("http://%s" % host, allow_redirects=False, timeout=timeout)
|
||||||
|
return True
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
s.connect((host, 80))
|
||||||
|
s.close()
|
||||||
|
return True
|
||||||
|
except: # pylint: disable=bare-except
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_internet_on(raise_exception=False):
|
||||||
|
result = _internet_on()
|
||||||
|
if raise_exception and not result:
|
||||||
|
raise InternetIsOffline()
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_remote_content(*args, **kwargs):
|
||||||
|
kwargs["headers"] = kwargs.get("headers", {})
|
||||||
|
if "User-Agent" not in kwargs["headers"]:
|
||||||
|
kwargs["headers"]["User-Agent"] = app.get_user_agent()
|
||||||
|
|
||||||
|
if "timeout" not in kwargs:
|
||||||
|
kwargs["timeout"] = DEFAULT_REQUESTS_TIMEOUT
|
||||||
|
|
||||||
|
r = requests.get(*args, **kwargs)
|
||||||
|
r.raise_for_status()
|
||||||
|
return r.text
|
||||||
|
@ -21,7 +21,7 @@ from os.path import isfile
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import app, exception, fs, proc, util
|
from platformio import app, exception, fs, proc
|
||||||
from platformio.commands.debug import helpers
|
from platformio.commands.debug import helpers
|
||||||
from platformio.commands.debug.exception import DebugInvalidOptionsError
|
from platformio.commands.debug.exception import DebugInvalidOptionsError
|
||||||
from platformio.package.manager.core import inject_contrib_pysite
|
from platformio.package.manager.core import inject_contrib_pysite
|
||||||
@ -130,7 +130,7 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro
|
|||||||
nl=False,
|
nl=False,
|
||||||
)
|
)
|
||||||
stream = helpers.GDBMIConsoleStream()
|
stream = helpers.GDBMIConsoleStream()
|
||||||
with util.capture_std_streams(stream):
|
with proc.capture_std_streams(stream):
|
||||||
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
helpers.predebug_project(ctx, project_dir, env_name, preload, verbose)
|
||||||
stream.close()
|
stream.close()
|
||||||
else:
|
else:
|
||||||
|
@ -23,6 +23,7 @@ import click
|
|||||||
from twisted.internet import defer # pylint: disable=import-error
|
from twisted.internet import defer # pylint: disable=import-error
|
||||||
|
|
||||||
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, fs, util
|
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, fs, util
|
||||||
|
from platformio.clients.http import ensure_internet_on
|
||||||
from platformio.commands.home import helpers
|
from platformio.commands.home import helpers
|
||||||
from platformio.compat import PY2, get_filesystem_encoding, glob_recursive
|
from platformio.compat import PY2, get_filesystem_encoding, glob_recursive
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ class OSRPC(object):
|
|||||||
defer.returnValue(result)
|
defer.returnValue(result)
|
||||||
|
|
||||||
# check internet before and resolve issue with 60 seconds timeout
|
# check internet before and resolve issue with 60 seconds timeout
|
||||||
util.internet_on(raise_exception=True)
|
ensure_internet_on(raise_exception=True)
|
||||||
|
|
||||||
session = helpers.requests_session()
|
session = helpers.requests_session()
|
||||||
if data:
|
if data:
|
||||||
|
@ -28,7 +28,7 @@ from platformio.commands.lib.helpers import (
|
|||||||
save_project_libdeps,
|
save_project_libdeps,
|
||||||
)
|
)
|
||||||
from platformio.compat import dump_json_to_unicode
|
from platformio.compat import dump_json_to_unicode
|
||||||
from platformio.package.exception import UnknownPackageError
|
from platformio.package.exception import NotGlobalLibDir, UnknownPackageError
|
||||||
from platformio.package.manager.library import LibraryPackageManager
|
from platformio.package.manager.library import LibraryPackageManager
|
||||||
from platformio.package.meta import PackageItem, PackageSpec
|
from platformio.package.meta import PackageItem, PackageSpec
|
||||||
from platformio.proc import is_ci
|
from platformio.proc import is_ci
|
||||||
@ -97,7 +97,7 @@ def cli(ctx, **options):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not storage_dirs:
|
if not storage_dirs:
|
||||||
raise exception.NotGlobalLibDir(
|
raise NotGlobalLibDir(
|
||||||
get_project_dir(), get_project_global_lib_dir(), ctx.invoked_subcommand
|
get_project_dir(), get_project_global_lib_dir(), ctx.invoked_subcommand
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ from io import BytesIO
|
|||||||
|
|
||||||
from twisted.spread import pb # pylint: disable=import-error
|
from twisted.spread import pb # pylint: disable=import-error
|
||||||
|
|
||||||
from platformio import util
|
from platformio import fs
|
||||||
from platformio.commands.remote.client.async_base import AsyncClientBase
|
from platformio.commands.remote.client.async_base import AsyncClientBase
|
||||||
from platformio.commands.remote.projectsync import PROJECT_SYNC_STAGE, ProjectSync
|
from platformio.commands.remote.projectsync import PROJECT_SYNC_STAGE, ProjectSync
|
||||||
from platformio.compat import hashlib_encode_data
|
from platformio.compat import hashlib_encode_data
|
||||||
@ -64,7 +64,7 @@ class RunOrTestClient(AsyncClientBase):
|
|||||||
return "%s-%s" % (os.path.basename(path), h.hexdigest())
|
return "%s-%s" % (os.path.basename(path), h.hexdigest())
|
||||||
|
|
||||||
def add_project_items(self, psync):
|
def add_project_items(self, psync):
|
||||||
with util.cd(self.options["project_dir"]):
|
with fs.cd(self.options["project_dir"]):
|
||||||
cfg = ProjectConfig.get_instance(
|
cfg = ProjectConfig.get_instance(
|
||||||
os.path.join(self.options["project_dir"], "platformio.ini")
|
os.path.join(self.options["project_dir"], "platformio.ini")
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,8 @@ from zipfile import ZipFile
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import VERSION, __version__, app, exception, util
|
from platformio import VERSION, __version__, app, exception
|
||||||
|
from platformio.clients.http import fetch_remote_content
|
||||||
from platformio.compat import WINDOWS
|
from platformio.compat import WINDOWS
|
||||||
from platformio.proc import exec_command, get_pythonexe_path
|
from platformio.proc import exec_command, get_pythonexe_path
|
||||||
from platformio.project.helpers import get_project_cache_dir
|
from platformio.project.helpers import get_project_cache_dir
|
||||||
@ -130,7 +131,7 @@ def get_latest_version():
|
|||||||
|
|
||||||
def get_develop_latest_version():
|
def get_develop_latest_version():
|
||||||
version = None
|
version = None
|
||||||
content = util.fetch_remote_content(
|
content = fetch_remote_content(
|
||||||
"https://raw.githubusercontent.com/platformio/platformio"
|
"https://raw.githubusercontent.com/platformio/platformio"
|
||||||
"/develop/platformio/__init__.py"
|
"/develop/platformio/__init__.py"
|
||||||
)
|
)
|
||||||
@ -150,5 +151,5 @@ def get_develop_latest_version():
|
|||||||
|
|
||||||
|
|
||||||
def get_pypi_latest_version():
|
def get_pypi_latest_version():
|
||||||
content = util.fetch_remote_content("https://pypi.org/pypi/platformio/json")
|
content = fetch_remote_content("https://pypi.org/pypi/platformio/json")
|
||||||
return json.loads(content)["info"]["version"]
|
return json.loads(content)["info"]["version"]
|
||||||
|
@ -30,10 +30,6 @@ class ReturnErrorCode(PlatformioException):
|
|||||||
MESSAGE = "{0}"
|
MESSAGE = "{0}"
|
||||||
|
|
||||||
|
|
||||||
class LockFileTimeoutError(PlatformioException):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class MinitermException(PlatformioException):
|
class MinitermException(PlatformioException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -47,61 +43,6 @@ class AbortedByUser(UserSideException):
|
|||||||
MESSAGE = "Aborted by user"
|
MESSAGE = "Aborted by user"
|
||||||
|
|
||||||
|
|
||||||
# Package Manager
|
|
||||||
|
|
||||||
|
|
||||||
class PlatformIOPackageException(PlatformioException):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class UnknownPackage(UserSideException):
|
|
||||||
|
|
||||||
MESSAGE = "Detected unknown package '{0}'"
|
|
||||||
|
|
||||||
|
|
||||||
class MissingPackageManifest(PlatformIOPackageException):
|
|
||||||
|
|
||||||
MESSAGE = "Could not find one of '{0}' manifest files in the package"
|
|
||||||
|
|
||||||
|
|
||||||
class UndefinedPackageVersion(PlatformIOPackageException):
|
|
||||||
|
|
||||||
MESSAGE = (
|
|
||||||
"Could not find a version that satisfies the requirement '{0}'"
|
|
||||||
" for your system '{1}'"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PackageInstallError(PlatformIOPackageException):
|
|
||||||
|
|
||||||
MESSAGE = (
|
|
||||||
"Could not install '{0}' with version requirements '{1}' "
|
|
||||||
"for your system '{2}'.\n\n"
|
|
||||||
"Please try this solution -> http://bit.ly/faq-package-manager"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Library
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
class NotGlobalLibDir(UserSideException):
|
|
||||||
|
|
||||||
MESSAGE = (
|
|
||||||
"The `{0}` is not a PlatformIO project.\n\n"
|
|
||||||
"To manage libraries in global storage `{1}`,\n"
|
|
||||||
"please use `platformio lib --global {2}` or specify custom storage "
|
|
||||||
"`platformio lib --storage-dir /path/to/storage/ {2}`.\n"
|
|
||||||
"Check `platformio lib --help` for details."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidLibConfURL(UserSideException):
|
|
||||||
|
|
||||||
MESSAGE = "Invalid library config URL '{0}'"
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# UDEV Rules
|
# UDEV Rules
|
||||||
#
|
#
|
||||||
@ -143,20 +84,6 @@ class GetLatestVersionError(PlatformioException):
|
|||||||
MESSAGE = "Can not retrieve the latest PlatformIO version"
|
MESSAGE = "Can not retrieve the latest PlatformIO version"
|
||||||
|
|
||||||
|
|
||||||
class APIRequestError(PlatformioException):
|
|
||||||
|
|
||||||
MESSAGE = "[API] {0}"
|
|
||||||
|
|
||||||
|
|
||||||
class InternetIsOffline(UserSideException):
|
|
||||||
|
|
||||||
MESSAGE = (
|
|
||||||
"You are not connected to the Internet.\n"
|
|
||||||
"PlatformIO needs the Internet connection to"
|
|
||||||
" download dependent packages or to work with PIO Account."
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidSettingName(UserSideException):
|
class InvalidSettingName(UserSideException):
|
||||||
|
|
||||||
MESSAGE = "Invalid setting with the name '{0}'"
|
MESSAGE = "Invalid setting with the name '{0}'"
|
||||||
|
@ -176,6 +176,10 @@ def expanduser(path):
|
|||||||
return os.environ["USERPROFILE"] + path[1:]
|
return os.environ["USERPROFILE"] + path[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def change_filemtime(path, mtime):
|
||||||
|
os.utime(path, (mtime, mtime))
|
||||||
|
|
||||||
|
|
||||||
def rmtree(path):
|
def rmtree(path):
|
||||||
def _onerror(func, path, __):
|
def _onerror(func, path, __):
|
||||||
try:
|
try:
|
||||||
|
@ -20,6 +20,7 @@ import click
|
|||||||
import semantic_version
|
import semantic_version
|
||||||
|
|
||||||
from platformio import __version__, app, exception, fs, telemetry, util
|
from platformio import __version__, app, exception, fs, telemetry, util
|
||||||
|
from platformio.clients import http
|
||||||
from platformio.commands import PlatformioCLI
|
from platformio.commands import PlatformioCLI
|
||||||
from platformio.commands.lib.command import CTX_META_STORAGE_DIRS_KEY
|
from platformio.commands.lib.command import CTX_META_STORAGE_DIRS_KEY
|
||||||
from platformio.commands.lib.command import lib_update as cmd_lib_update
|
from platformio.commands.lib.command import lib_update as cmd_lib_update
|
||||||
@ -53,9 +54,9 @@ def on_platformio_end(ctx, result): # pylint: disable=unused-argument
|
|||||||
check_internal_updates(ctx, "platforms")
|
check_internal_updates(ctx, "platforms")
|
||||||
check_internal_updates(ctx, "libraries")
|
check_internal_updates(ctx, "libraries")
|
||||||
except (
|
except (
|
||||||
exception.InternetIsOffline,
|
http.HTTPClientError,
|
||||||
|
http.InternetIsOffline,
|
||||||
exception.GetLatestVersionError,
|
exception.GetLatestVersionError,
|
||||||
exception.APIRequestError,
|
|
||||||
):
|
):
|
||||||
click.secho(
|
click.secho(
|
||||||
"Failed to check for PlatformIO upgrades. "
|
"Failed to check for PlatformIO upgrades. "
|
||||||
@ -221,7 +222,7 @@ def check_platformio_upgrade():
|
|||||||
last_check["platformio_upgrade"] = int(time())
|
last_check["platformio_upgrade"] = int(time())
|
||||||
app.set_state_item("last_check", last_check)
|
app.set_state_item("last_check", last_check)
|
||||||
|
|
||||||
util.internet_on(raise_exception=True)
|
http.ensure_internet_on(raise_exception=True)
|
||||||
|
|
||||||
# Update PlatformIO's Core packages
|
# Update PlatformIO's Core packages
|
||||||
update_core_packages(silent=True)
|
update_core_packages(silent=True)
|
||||||
@ -268,7 +269,7 @@ def check_internal_updates(ctx, what): # pylint: disable=too-many-branches
|
|||||||
last_check[what + "_update"] = int(time())
|
last_check[what + "_update"] = int(time())
|
||||||
app.set_state_item("last_check", last_check)
|
app.set_state_item("last_check", last_check)
|
||||||
|
|
||||||
util.internet_on(raise_exception=True)
|
http.ensure_internet_on(raise_exception=True)
|
||||||
|
|
||||||
outdated_items = []
|
outdated_items = []
|
||||||
pm = PlatformPackageManager() if what == "platforms" else LibraryPackageManager()
|
pm = PlatformPackageManager() if what == "platforms" else LibraryPackageManager()
|
||||||
|
@ -21,7 +21,7 @@ from time import mktime
|
|||||||
import click
|
import click
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, fs, util
|
from platformio import DEFAULT_REQUESTS_TIMEOUT, app, fs
|
||||||
from platformio.package.exception import PackageException
|
from platformio.package.exception import PackageException
|
||||||
|
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ class FileDownloader(object):
|
|||||||
def _preserve_filemtime(self, lmdate):
|
def _preserve_filemtime(self, lmdate):
|
||||||
timedata = parsedate_tz(lmdate)
|
timedata = parsedate_tz(lmdate)
|
||||||
lmtime = mktime(timedata[:9])
|
lmtime = mktime(timedata[:9])
|
||||||
util.change_filemtime(self._destination, lmtime)
|
fs.change_filemtime(self._destination, lmtime)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if self._request:
|
if self._request:
|
||||||
|
@ -58,3 +58,14 @@ class UnknownPackageError(UserSideException):
|
|||||||
"Could not find a package with '{0}' requirements for your system '%s'"
|
"Could not find a package with '{0}' requirements for your system '%s'"
|
||||||
% util.get_systype()
|
% util.get_systype()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NotGlobalLibDir(UserSideException):
|
||||||
|
|
||||||
|
MESSAGE = (
|
||||||
|
"The `{0}` is not a PlatformIO project.\n\n"
|
||||||
|
"To manage libraries in global storage `{1}`,\n"
|
||||||
|
"please use `platformio lib --global {2}` or specify custom storage "
|
||||||
|
"`platformio lib --storage-dir /path/to/storage/ {2}`.\n"
|
||||||
|
"Check `platformio lib --help` for details."
|
||||||
|
)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import os
|
import os
|
||||||
from time import sleep, time
|
from time import sleep, time
|
||||||
|
|
||||||
from platformio import exception
|
from platformio.exception import PlatformioException
|
||||||
|
|
||||||
LOCKFILE_TIMEOUT = 3600 # in seconds, 1 hour
|
LOCKFILE_TIMEOUT = 3600 # in seconds, 1 hour
|
||||||
LOCKFILE_DELAY = 0.2
|
LOCKFILE_DELAY = 0.2
|
||||||
@ -36,7 +36,11 @@ except ImportError:
|
|||||||
LOCKFILE_CURRENT_INTERFACE = None
|
LOCKFILE_CURRENT_INTERFACE = None
|
||||||
|
|
||||||
|
|
||||||
class LockFileExists(Exception):
|
class LockFileExists(PlatformioException):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LockFileTimeoutError(PlatformioException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ class LockFile(object):
|
|||||||
sleep(self.delay)
|
sleep(self.delay)
|
||||||
elapsed += self.delay
|
elapsed += self.delay
|
||||||
|
|
||||||
raise exception.LockFileTimeoutError()
|
raise LockFileTimeoutError()
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
self._unlock()
|
self._unlock()
|
||||||
|
@ -16,10 +16,10 @@ import os
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import util
|
|
||||||
from platformio.package.exception import UnknownPackageError
|
from platformio.package.exception import UnknownPackageError
|
||||||
from platformio.package.meta import PackageItem, PackageOutdatedResult, PackageSpec
|
from platformio.package.meta import PackageItem, PackageOutdatedResult, PackageSpec
|
||||||
from platformio.package.vcsclient import VCSBaseException, VCSClientFactory
|
from platformio.package.vcsclient import VCSBaseException, VCSClientFactory
|
||||||
|
from platformio.clients.http import ensure_internet_on
|
||||||
|
|
||||||
|
|
||||||
class PackageManagerUpdateMixin(object):
|
class PackageManagerUpdateMixin(object):
|
||||||
@ -97,7 +97,7 @@ class PackageManagerUpdateMixin(object):
|
|||||||
),
|
),
|
||||||
nl=False,
|
nl=False,
|
||||||
)
|
)
|
||||||
if not util.internet_on():
|
if not ensure_internet_on():
|
||||||
if not silent:
|
if not silent:
|
||||||
click.echo("[%s]" % (click.style("Off-line", fg="yellow")))
|
click.echo("[%s]" % (click.style("Off-line", fg="yellow")))
|
||||||
return pkg
|
return pkg
|
||||||
|
@ -17,7 +17,7 @@ import os
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from platformio import __core_packages__, exception, util
|
from platformio import __core_packages__, fs, exception, util
|
||||||
from platformio.compat import PY2
|
from platformio.compat import PY2
|
||||||
from platformio.package.manager.tool import ToolPackageManager
|
from platformio.package.manager.tool import ToolPackageManager
|
||||||
from platformio.package.meta import PackageSpec
|
from platformio.package.meta import PackageSpec
|
||||||
@ -93,7 +93,7 @@ def inject_contrib_pysite(verify_openssl=False):
|
|||||||
|
|
||||||
def build_contrib_pysite_deps(target_dir):
|
def build_contrib_pysite_deps(target_dir):
|
||||||
if os.path.isdir(target_dir):
|
if os.path.isdir(target_dir):
|
||||||
util.rmtree_(target_dir)
|
fs.rmtree(target_dir)
|
||||||
os.makedirs(target_dir)
|
os.makedirs(target_dir)
|
||||||
with open(os.path.join(target_dir, "package.json"), "w") as fp:
|
with open(os.path.join(target_dir, "package.json"), "w") as fp:
|
||||||
json.dump(
|
json.dump(
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from platformio import util
|
from platformio import util
|
||||||
from platformio.exception import APIRequestError, InternetIsOffline
|
from platformio.clients.http import HTTPClientError, InternetIsOffline
|
||||||
from platformio.package.exception import UnknownPackageError
|
from platformio.package.exception import UnknownPackageError
|
||||||
from platformio.package.manager.base import BasePackageManager
|
from platformio.package.manager.base import BasePackageManager
|
||||||
from platformio.package.manager.tool import ToolPackageManager
|
from platformio.package.manager.tool import ToolPackageManager
|
||||||
@ -176,7 +176,7 @@ class PlatformPackageManager(BasePackageManager): # pylint: disable=too-many-an
|
|||||||
key = "%s:%s" % (board["platform"], board["id"])
|
key = "%s:%s" % (board["platform"], board["id"])
|
||||||
if key not in know_boards:
|
if key not in know_boards:
|
||||||
boards.append(board)
|
boards.append(board)
|
||||||
except (APIRequestError, InternetIsOffline):
|
except (HTTPClientError, InternetIsOffline):
|
||||||
pass
|
pass
|
||||||
return sorted(boards, key=lambda b: b["name"])
|
return sorted(boards, key=lambda b: b["name"])
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import re
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
from platformio import util
|
from platformio import util
|
||||||
|
from platformio.clients.http import fetch_remote_content
|
||||||
from platformio.compat import get_object_members, string_types
|
from platformio.compat import get_object_members, string_types
|
||||||
from platformio.package.exception import ManifestParserError, UnknownManifestError
|
from platformio.package.exception import ManifestParserError, UnknownManifestError
|
||||||
from platformio.project.helpers import is_platformio_project
|
from platformio.project.helpers import is_platformio_project
|
||||||
@ -106,7 +107,7 @@ class ManifestParserFactory(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def new_from_url(remote_url):
|
def new_from_url(remote_url):
|
||||||
content = util.fetch_remote_content(remote_url)
|
content = fetch_remote_content(remote_url)
|
||||||
return ManifestParserFactory.new(
|
return ManifestParserFactory.new(
|
||||||
content,
|
content,
|
||||||
ManifestFileType.from_uri(remote_url) or ManifestFileType.LIBRARY_JSON,
|
ManifestFileType.from_uri(remote_url) or ManifestFileType.LIBRARY_JSON,
|
||||||
|
@ -21,7 +21,7 @@ import requests
|
|||||||
import semantic_version
|
import semantic_version
|
||||||
from marshmallow import Schema, ValidationError, fields, validate, validates
|
from marshmallow import Schema, ValidationError, fields, validate, validates
|
||||||
|
|
||||||
from platformio import util
|
from platformio.clients.http import fetch_remote_content
|
||||||
from platformio.package.exception import ManifestValidationError
|
from platformio.package.exception import ManifestValidationError
|
||||||
from platformio.util import memoized
|
from platformio.util import memoized
|
||||||
|
|
||||||
@ -256,4 +256,4 @@ class ManifestSchema(BaseSchema):
|
|||||||
"https://raw.githubusercontent.com/spdx/license-list-data"
|
"https://raw.githubusercontent.com/spdx/license-list-data"
|
||||||
"/v%s/json/licenses.json" % version
|
"/v%s/json/licenses.json" % version
|
||||||
)
|
)
|
||||||
return json.loads(util.fetch_remote_content(spdx_data_url))
|
return json.loads(fetch_remote_content(spdx_data_url))
|
||||||
|
@ -19,7 +19,7 @@ from zipfile import ZipFile
|
|||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from platformio import util
|
from platformio import fs
|
||||||
from platformio.package.exception import PackageException
|
from platformio.package.exception import PackageException
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ class ZIPArchiver(BaseArchiver):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def preserve_mtime(item, dest_dir):
|
def preserve_mtime(item, dest_dir):
|
||||||
util.change_filemtime(
|
fs.change_filemtime(
|
||||||
os.path.join(dest_dir, item.filename),
|
os.path.join(dest_dir, item.filename),
|
||||||
mktime(tuple(item.date_time) + tuple([0, 0, 0])),
|
mktime(tuple(item.date_time) + tuple([0, 0, 0])),
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from contextlib import contextmanager
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
from platformio import exception
|
from platformio import exception
|
||||||
@ -137,6 +138,17 @@ def exec_command(*args, **kwargs):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def capture_std_streams(stdout, stderr=None):
|
||||||
|
_stdout = sys.stdout
|
||||||
|
_stderr = sys.stderr
|
||||||
|
sys.stdout = stdout
|
||||||
|
sys.stderr = stderr or stdout
|
||||||
|
yield
|
||||||
|
sys.stdout = _stdout
|
||||||
|
sys.stderr = _stderr
|
||||||
|
|
||||||
|
|
||||||
def is_ci():
|
def is_ci():
|
||||||
return os.getenv("CI", "").lower() == "true"
|
return os.getenv("CI", "").lower() == "true"
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ class MeasurementProtocol(TelemetryBase):
|
|||||||
caller_id = str(app.get_session_var("caller_id"))
|
caller_id = str(app.get_session_var("caller_id"))
|
||||||
self["cd1"] = util.get_systype()
|
self["cd1"] = util.get_systype()
|
||||||
self["cd4"] = (
|
self["cd4"] = (
|
||||||
1 if (not util.is_ci() and (caller_id or not is_container())) else 0
|
1 if (not is_ci() and (caller_id or not is_container())) else 0
|
||||||
)
|
)
|
||||||
if caller_id:
|
if caller_id:
|
||||||
self["cd5"] = caller_id.lower()
|
self["cd5"] = caller_id.lower()
|
||||||
|
@ -19,26 +19,17 @@ import math
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
import socket
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from contextlib import contextmanager
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
import click
|
import click
|
||||||
import requests
|
|
||||||
|
|
||||||
from platformio import DEFAULT_REQUESTS_TIMEOUT, __apiurl__, __version__, exception
|
from platformio import __version__, exception, proc
|
||||||
from platformio.commands import PlatformioCLI
|
|
||||||
from platformio.compat import PY2, WINDOWS
|
from platformio.compat import PY2, WINDOWS
|
||||||
from platformio.fs import cd # pylint: disable=unused-import
|
|
||||||
from platformio.fs import load_json # pylint: disable=unused-import
|
from platformio.fs import load_json # pylint: disable=unused-import
|
||||||
from platformio.fs import rmtree as rmtree_ # pylint: disable=unused-import
|
|
||||||
from platformio.proc import exec_command # pylint: disable=unused-import
|
from platformio.proc import exec_command # pylint: disable=unused-import
|
||||||
from platformio.proc import is_ci # pylint: disable=unused-import
|
|
||||||
|
|
||||||
# KEEP unused imports for backward compatibility with PIO Core 3.0 API
|
|
||||||
|
|
||||||
|
|
||||||
class memoized(object):
|
class memoized(object):
|
||||||
@ -97,17 +88,6 @@ def singleton(cls):
|
|||||||
return get_instance
|
return get_instance
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
|
||||||
def capture_std_streams(stdout, stderr=None):
|
|
||||||
_stdout = sys.stdout
|
|
||||||
_stderr = sys.stderr
|
|
||||||
sys.stdout = stdout
|
|
||||||
sys.stderr = stderr or stdout
|
|
||||||
yield
|
|
||||||
sys.stdout = _stdout
|
|
||||||
sys.stderr = _stderr
|
|
||||||
|
|
||||||
|
|
||||||
def get_systype():
|
def get_systype():
|
||||||
type_ = platform.system().lower()
|
type_ = platform.system().lower()
|
||||||
arch = platform.machine().lower()
|
arch = platform.machine().lower()
|
||||||
@ -116,16 +96,6 @@ def get_systype():
|
|||||||
return "%s_%s" % (type_, arch) if arch else type_
|
return "%s_%s" % (type_, arch) if arch else type_
|
||||||
|
|
||||||
|
|
||||||
def pioversion_to_intstr():
|
|
||||||
vermatch = re.match(r"^([\d\.]+)", __version__)
|
|
||||||
assert vermatch
|
|
||||||
return [int(i) for i in vermatch.group(1).split(".")[:3]]
|
|
||||||
|
|
||||||
|
|
||||||
def change_filemtime(path, mtime):
|
|
||||||
os.utime(path, (mtime, mtime))
|
|
||||||
|
|
||||||
|
|
||||||
def get_serial_ports(filter_hwid=False):
|
def get_serial_ports(filter_hwid=False):
|
||||||
try:
|
try:
|
||||||
# pylint: disable=import-outside-toplevel
|
# pylint: disable=import-outside-toplevel
|
||||||
@ -164,7 +134,7 @@ def get_logical_devices():
|
|||||||
items = []
|
items = []
|
||||||
if WINDOWS:
|
if WINDOWS:
|
||||||
try:
|
try:
|
||||||
result = exec_command(
|
result = proc.exec_command(
|
||||||
["wmic", "logicaldisk", "get", "name,VolumeName"]
|
["wmic", "logicaldisk", "get", "name,VolumeName"]
|
||||||
).get("out", "")
|
).get("out", "")
|
||||||
devicenamere = re.compile(r"^([A-Z]{1}\:)\s*(\S+)?")
|
devicenamere = re.compile(r"^([A-Z]{1}\:)\s*(\S+)?")
|
||||||
@ -177,12 +147,12 @@ def get_logical_devices():
|
|||||||
except WindowsError: # pylint: disable=undefined-variable
|
except WindowsError: # pylint: disable=undefined-variable
|
||||||
pass
|
pass
|
||||||
# try "fsutil"
|
# try "fsutil"
|
||||||
result = exec_command(["fsutil", "fsinfo", "drives"]).get("out", "")
|
result = proc.exec_command(["fsutil", "fsinfo", "drives"]).get("out", "")
|
||||||
for device in re.findall(r"[A-Z]:\\", result):
|
for device in re.findall(r"[A-Z]:\\", result):
|
||||||
items.append({"path": device, "name": None})
|
items.append({"path": device, "name": None})
|
||||||
return items
|
return items
|
||||||
|
|
||||||
result = exec_command(["df"]).get("out")
|
result = proc.exec_command(["df"]).get("out")
|
||||||
devicenamere = re.compile(r"^/.+\d+\%\s+([a-z\d\-_/]+)$", flags=re.I)
|
devicenamere = re.compile(r"^/.+\d+\%\s+([a-z\d\-_/]+)$", flags=re.I)
|
||||||
for line in result.split("\n"):
|
for line in result.split("\n"):
|
||||||
match = devicenamere.match(line.strip())
|
match = devicenamere.match(line.strip())
|
||||||
@ -370,60 +340,27 @@ def get_api_result(url, params=None, data=None, auth=None, cache_valid=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
PING_REMOTE_HOSTS = [
|
def pioversion_to_intstr():
|
||||||
"140.82.118.3", # Github.com
|
vermatch = re.match(r"^([\d\.]+)", __version__)
|
||||||
"35.231.145.151", # Gitlab.com
|
assert vermatch
|
||||||
"88.198.170.159", # platformio.org
|
return [int(i) for i in vermatch.group(1).split(".")[:3]]
|
||||||
"github.com",
|
|
||||||
"platformio.org",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@memoized(expire="10s")
|
|
||||||
def _internet_on():
|
|
||||||
timeout = 2
|
|
||||||
socket.setdefaulttimeout(timeout)
|
|
||||||
for host in PING_REMOTE_HOSTS:
|
|
||||||
try:
|
|
||||||
for var in ("HTTP_PROXY", "HTTPS_PROXY"):
|
|
||||||
if not os.getenv(var, var.lower()):
|
|
||||||
continue
|
|
||||||
requests.get("http://%s" % host, allow_redirects=False, timeout=timeout)
|
|
||||||
return True
|
|
||||||
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, 80))
|
|
||||||
return True
|
|
||||||
except: # pylint: disable=bare-except
|
|
||||||
pass
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def internet_on(raise_exception=False):
|
|
||||||
result = _internet_on()
|
|
||||||
if raise_exception and not result:
|
|
||||||
raise exception.InternetIsOffline()
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_remote_content(*args, **kwargs):
|
|
||||||
# pylint: disable=import-outside-toplevel
|
|
||||||
from platformio.app import get_user_agent
|
|
||||||
|
|
||||||
kwargs["headers"] = kwargs.get("headers", {})
|
|
||||||
if "User-Agent" not in kwargs["headers"]:
|
|
||||||
kwargs["headers"]["User-Agent"] = get_user_agent()
|
|
||||||
|
|
||||||
if "timeout" not in kwargs:
|
|
||||||
kwargs["timeout"] = DEFAULT_REQUESTS_TIMEOUT
|
|
||||||
|
|
||||||
r = requests.get(*args, **kwargs)
|
|
||||||
r.raise_for_status()
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
|
|
||||||
def pepver_to_semver(pepver):
|
def pepver_to_semver(pepver):
|
||||||
return re.sub(r"(\.\d+)\.?(dev|a|b|rc|post)", r"\1-\2.", pepver, 1)
|
return re.sub(r"(\.\d+)\.?(dev|a|b|rc|post)", r"\1-\2.", pepver, 1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_original_version(version):
|
||||||
|
if version.count(".") != 2:
|
||||||
|
return None
|
||||||
|
_, raw = version.split(".")[:2]
|
||||||
|
if int(raw) <= 99:
|
||||||
|
return None
|
||||||
|
if int(raw) <= 9999:
|
||||||
|
return "%s.%s" % (raw[:-2], int(raw[-2:]))
|
||||||
|
return "%s.%s.%s" % (raw[:-4], int(raw[-4:-2]), int(raw[-2:]))
|
||||||
|
|
||||||
|
|
||||||
def items_to_list(items):
|
def items_to_list(items):
|
||||||
if isinstance(items, list):
|
if isinstance(items, list):
|
||||||
return items
|
return items
|
||||||
@ -472,14 +409,3 @@ def humanize_duration_time(duration):
|
|||||||
tokens.append(int(round(duration) if multiplier == 1 else fraction))
|
tokens.append(int(round(duration) if multiplier == 1 else fraction))
|
||||||
duration -= fraction * multiplier
|
duration -= fraction * multiplier
|
||||||
return "{:02d}:{:02d}:{:02d}.{:03d}".format(*tokens)
|
return "{:02d}:{:02d}:{:02d}.{:03d}".format(*tokens)
|
||||||
|
|
||||||
|
|
||||||
def get_original_version(version):
|
|
||||||
if version.count(".") != 2:
|
|
||||||
return None
|
|
||||||
_, raw = version.split(".")[:2]
|
|
||||||
if int(raw) <= 99:
|
|
||||||
return None
|
|
||||||
if int(raw) <= 9999:
|
|
||||||
return "%s.%s" % (raw[:-2], int(raw[-2:]))
|
|
||||||
return "%s.%s.%s" % (raw[:-4], int(raw[-4:-2]), int(raw[-2:]))
|
|
||||||
|
@ -389,7 +389,7 @@ check_tool = pvs-studio
|
|||||||
assert style == 0
|
assert style == 0
|
||||||
|
|
||||||
|
|
||||||
def test_check_embedded_platform_all_tools(clirunner, tmpdir):
|
def test_check_embedded_platform_all_tools(clirunner, validate_cliresult, tmpdir):
|
||||||
config = """
|
config = """
|
||||||
[env:test]
|
[env:test]
|
||||||
platform = ststm32
|
platform = ststm32
|
||||||
@ -422,11 +422,9 @@ int main() {
|
|||||||
for framework in frameworks:
|
for framework in frameworks:
|
||||||
for tool in ("cppcheck", "clangtidy", "pvs-studio"):
|
for tool in ("cppcheck", "clangtidy", "pvs-studio"):
|
||||||
tmpdir.join("platformio.ini").write(config % (framework, tool))
|
tmpdir.join("platformio.ini").write(config % (framework, tool))
|
||||||
|
|
||||||
result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir)])
|
result = clirunner.invoke(cmd_check, ["--project-dir", str(tmpdir)])
|
||||||
|
validate_cliresult(result)
|
||||||
defects = sum(count_defects(result.output))
|
defects = sum(count_defects(result.output))
|
||||||
|
|
||||||
assert result.exit_code == 0 and defects > 0, "Failed %s with %s" % (
|
assert result.exit_code == 0 and defects > 0, "Failed %s with %s" % (
|
||||||
framework,
|
framework,
|
||||||
tool,
|
tool,
|
||||||
|
@ -16,12 +16,12 @@ import os
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from platformio import util
|
from platformio import proc
|
||||||
from platformio.commands.test.command import cli as cmd_test
|
from platformio.commands.test.command import cli as cmd_test
|
||||||
|
|
||||||
|
|
||||||
def test_local_env():
|
def test_local_env():
|
||||||
result = util.exec_command(
|
result = proc.exec_command(
|
||||||
[
|
[
|
||||||
"platformio",
|
"platformio",
|
||||||
"test",
|
"test",
|
||||||
|
@ -20,7 +20,7 @@ import time
|
|||||||
import pytest
|
import pytest
|
||||||
from click.testing import CliRunner
|
from click.testing import CliRunner
|
||||||
|
|
||||||
from platformio import util
|
from platformio.clients import http
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
@ -74,7 +74,7 @@ def isolated_pio_core(request, tmpdir_factory):
|
|||||||
|
|
||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
def without_internet(monkeypatch):
|
def without_internet(monkeypatch):
|
||||||
monkeypatch.setattr(util, "_internet_on", lambda: False)
|
monkeypatch.setattr(http, "_internet_on", lambda: False)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -19,7 +19,7 @@ from os.path import basename, dirname, getsize, isdir, isfile, join, normpath
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from platformio import util
|
from platformio import fs, proc
|
||||||
from platformio.compat import PY2
|
from platformio.compat import PY2
|
||||||
from platformio.package.manager.platform import PlatformPackageManager
|
from platformio.package.manager.platform import PlatformPackageManager
|
||||||
from platformio.platform.factory import PlatformFactory
|
from platformio.platform.factory import PlatformFactory
|
||||||
@ -64,14 +64,14 @@ def pytest_generate_tests(metafunc):
|
|||||||
|
|
||||||
|
|
||||||
def test_run(pioproject_dir):
|
def test_run(pioproject_dir):
|
||||||
with util.cd(pioproject_dir):
|
with fs.cd(pioproject_dir):
|
||||||
config = ProjectConfig()
|
config = ProjectConfig()
|
||||||
build_dir = config.get_optional_dir("build")
|
build_dir = config.get_optional_dir("build")
|
||||||
if isdir(build_dir):
|
if isdir(build_dir):
|
||||||
util.rmtree_(build_dir)
|
fs.rmtree(build_dir)
|
||||||
|
|
||||||
env_names = config.envs()
|
env_names = config.envs()
|
||||||
result = util.exec_command(
|
result = proc.exec_command(
|
||||||
["platformio", "run", "-e", random.choice(env_names)]
|
["platformio", "run", "-e", random.choice(env_names)]
|
||||||
)
|
)
|
||||||
if result["returncode"] != 0:
|
if result["returncode"] != 0:
|
||||||
|
@ -17,29 +17,33 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from platformio import exception, util
|
from platformio import proc
|
||||||
|
from platformio.clients import http
|
||||||
|
from platformio.clients.registry import RegistryClient
|
||||||
|
|
||||||
|
|
||||||
def test_platformio_cli():
|
def test_platformio_cli():
|
||||||
result = util.exec_command(["pio", "--help"])
|
result = proc.exec_command(["pio", "--help"])
|
||||||
assert result["returncode"] == 0
|
assert result["returncode"] == 0
|
||||||
# pylint: disable=unsupported-membership-test
|
# pylint: disable=unsupported-membership-test
|
||||||
assert "Usage: pio [OPTIONS] COMMAND [ARGS]..." in result["out"]
|
assert "Usage: pio [OPTIONS] COMMAND [ARGS]..." in result["out"]
|
||||||
|
|
||||||
|
|
||||||
def test_ping_internet_ips():
|
def test_ping_internet_ips():
|
||||||
for host in util.PING_REMOTE_HOSTS:
|
for host in http.PING_REMOTE_HOSTS:
|
||||||
requests.get("http://%s" % host, allow_redirects=False, timeout=2)
|
requests.get("http://%s" % host, allow_redirects=False, timeout=2)
|
||||||
|
|
||||||
|
|
||||||
def test_api_internet_offline(without_internet, isolated_pio_core):
|
def test_api_internet_offline(without_internet, isolated_pio_core):
|
||||||
with pytest.raises(exception.InternetIsOffline):
|
regclient = RegistryClient()
|
||||||
util.get_api_result("/stats")
|
with pytest.raises(http.InternetIsOffline):
|
||||||
|
regclient.fetch_json_data("get", "/v2/stats")
|
||||||
|
|
||||||
|
|
||||||
def test_api_cache(monkeypatch, isolated_pio_core):
|
def test_api_cache(monkeypatch, isolated_pio_core):
|
||||||
api_kwargs = {"url": "/stats", "cache_valid": "10s"}
|
regclient = RegistryClient()
|
||||||
result = util.get_api_result(**api_kwargs)
|
api_kwargs = {"method": "get", "path": "/v2/stats", "cache_valid": "10s"}
|
||||||
|
result = regclient.fetch_json_data(**api_kwargs)
|
||||||
assert result and "boards" in result
|
assert result and "boards" in result
|
||||||
monkeypatch.setattr(util, "_internet_on", lambda: False)
|
monkeypatch.setattr(http, "_internet_on", lambda: False)
|
||||||
assert util.get_api_result(**api_kwargs) == result
|
assert regclient.fetch_json_data(**api_kwargs) == result
|
||||||
|
Reference in New Issue
Block a user