Skip to content

Commit a7dfc86

Browse files
committed
Merge branch 'release/v1.0.0'
2 parents 1bdb495 + 700c69e commit a7dfc86

File tree

11 files changed

+116
-76
lines changed

11 files changed

+116
-76
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
fail-fast: false
99
matrix:
1010
os: [ubuntu-latest, windows-latest, macos-latest]
11-
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
11+
python-version: [3.6, 3.7, 3.8, 3.9]
1212
runs-on: ${{ matrix.os }}
1313
steps:
1414
- uses: actions/checkout@v2

get-platformio.py

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

pioinstaller/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@
1414

1515
import logging.config
1616

17-
VERSION = (0, 3, 5)
17+
VERSION = (1, 0, 0)
1818
__version__ = ".".join([str(s) for s in VERSION])
1919

2020
__title__ = "platformio-installer"
2121
__description__ = "An installer for PlatformIO Core"
2222

2323
__url__ = "https://platformio.org"
2424

25-
__author__ = "PlatformIO"
26-
__email__ = "[email protected]"
25+
__author__ = "PlatformIO Labs"
26+
__email__ = "[email protected]"
27+
2728

2829
__license__ = "Apache-2.0"
2930
__copyright__ = "Copyright 2014-present PlatformIO"

pioinstaller/__main__.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,31 @@
3636
multiple=True,
3737
help="A path to Python to be ignored (multiple options and unix wildcards are allowed)",
3838
)
39+
@click.option(
40+
"--pypi-index-url",
41+
help="Custom base URL of the Python Package Index (default `https://pypi.org/simple)`",
42+
)
3943
@click.pass_context
4044
def cli(
41-
ctx, verbose, shutdown_piohome, dev, ignore_python
45+
ctx, verbose, shutdown_piohome, dev, ignore_python, pypi_index_url
4246
): # pylint:disable=too-many-arguments
4347
if verbose:
4448
logging.getLogger("pioinstaller").setLevel(logging.DEBUG)
49+
if pypi_index_url:
50+
os.environ["PIP_INDEX_URL"] = pypi_index_url
4551
ctx.obj["dev"] = dev
46-
if not ctx.invoked_subcommand:
47-
click.echo("Installer version: %s" % __version__)
48-
click.echo("Platform: %s" % platform.platform(terse=True))
49-
click.echo("Python version: %s" % sys.version)
50-
click.echo("Python path: %s" % sys.executable)
51-
try:
52-
core.install_platformio_core(shutdown_piohome, dev, ignore_python)
53-
except exception.PIOInstallerException as e:
54-
raise click.ClickException(str(e))
52+
if ctx.invoked_subcommand:
53+
return
54+
55+
click.echo("Installer version: %s" % __version__)
56+
click.echo("Platform: %s" % platform.platform(terse=True))
57+
click.echo("Python version: %s" % sys.version)
58+
click.echo("Python path: %s" % sys.executable)
59+
60+
try:
61+
core.install_platformio_core(shutdown_piohome, dev, ignore_python)
62+
except exception.PIOInstallerException as exc:
63+
raise click.ClickException(str(exc))
5564

5665

5766
@cli.command()

pioinstaller/core.py

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,24 @@
3030
UPDATE_INTERVAL = 60 * 60 * 24 * 3 # 3 days
3131

3232

33-
def get_core_dir():
33+
def get_core_dir(force_to_root=False):
3434
if os.getenv("PLATFORMIO_CORE_DIR"):
3535
return os.getenv("PLATFORMIO_CORE_DIR")
3636

3737
core_dir = os.path.join(util.expanduser("~"), ".platformio")
3838
if not util.IS_WINDOWS:
3939
return core_dir
4040

41-
win_core_dir = os.path.splitdrive(core_dir)[0] + "\\.platformio"
42-
if os.path.isdir(win_core_dir):
43-
return win_core_dir
41+
win_root_dir = os.path.splitdrive(core_dir)[0] + "\\.platformio"
42+
if os.path.isdir(win_root_dir):
43+
return win_root_dir
4444
try:
45-
if util.has_non_ascii_char(core_dir):
46-
os.makedirs(win_core_dir)
47-
with open(os.path.join(win_core_dir, "file.tmp"), "w") as fp:
45+
if util.has_non_ascii_char(core_dir) or force_to_root:
46+
os.makedirs(win_root_dir)
47+
with open(os.path.join(win_root_dir, "file.tmp"), "w") as fp:
4848
fp.write("test")
49-
os.remove(os.path.join(win_core_dir, "file.tmp"))
50-
return win_core_dir
49+
os.remove(os.path.join(win_root_dir, "file.tmp"))
50+
return win_root_dir
5151
except: # pylint:disable=bare-except
5252
pass
5353

@@ -63,6 +63,29 @@ def get_cache_dir(path=None):
6363

6464

6565
def install_platformio_core(shutdown_piohome=True, develop=False, ignore_pythons=None):
66+
try:
67+
return _install_platformio_core(
68+
shutdown_piohome=shutdown_piohome,
69+
develop=develop,
70+
ignore_pythons=ignore_pythons,
71+
)
72+
except subprocess.CalledProcessError as exc:
73+
# Issue #221: Workaround for Windows OS when username contains a space
74+
# https://github.com/platformio/platformio-core-installer/issues/221
75+
if (
76+
util.IS_WINDOWS
77+
and " " in get_core_dir()
78+
and " " not in get_core_dir(force_to_root=True)
79+
):
80+
return _install_platformio_core(
81+
shutdown_piohome=shutdown_piohome,
82+
develop=develop,
83+
ignore_pythons=ignore_pythons,
84+
)
85+
raise exc
86+
87+
88+
def _install_platformio_core(shutdown_piohome=True, develop=False, ignore_pythons=None):
6689
# pylint: disable=bad-option-value, import-outside-toplevel, unused-import, import-error, unused-variable, cyclic-import
6790
from pioinstaller import penv
6891

@@ -96,10 +119,6 @@ def install_platformio_core(shutdown_piohome=True, develop=False, ignore_pythons
96119
penv.get_penv_bin_dir(penv_dir),
97120
"platformio.exe" if util.IS_WINDOWS else "platformio",
98121
)
99-
try:
100-
home.install_pio_home(platformio_exe)
101-
except Exception as e: # pylint:disable=broad-except
102-
log.debug(e)
103122

104123
click.secho(
105124
"\nPlatformIO Core has been successfully installed into an isolated environment `%s`!\n"
@@ -126,7 +145,8 @@ def check(dev=False, auto_upgrade=False, version_spec=None):
126145
from pioinstaller import penv
127146

128147
platformio_exe = os.path.join(
129-
penv.get_penv_bin_dir(), "platformio.exe" if util.IS_WINDOWS else "platformio",
148+
penv.get_penv_bin_dir(),
149+
"platformio.exe" if util.IS_WINDOWS else "platformio",
130150
)
131151
python_exe = os.path.join(
132152
penv.get_penv_bin_dir(), "python.exe" if util.IS_WINDOWS else "python"
@@ -185,7 +205,8 @@ def check(dev=False, auto_upgrade=False, version_spec=None):
185205
penv_state = json.load(fp)
186206
if penv_state.get("platform") != platform.platform(terse=True):
187207
raise exception.InvalidPlatformIOCore(
188-
"PlatformIO installed using another platform `%s`. Your platform: %s"
208+
"PlatformIO Core was installed using another platform `%s`. "
209+
"Your current platform: %s"
189210
% (penv_state.get("platform"), platform.platform(terse=True))
190211
)
191212

@@ -227,18 +248,33 @@ def check(dev=False, auto_upgrade=False, version_spec=None):
227248

228249

229250
def fetch_python_state(python_exe):
230-
code = """import platform
251+
code = """
231252
import json
253+
import platform
254+
import sys
255+
232256
import platformio
233257
258+
if sys.version_info < (3, 6):
259+
raise Exception(
260+
"Unsupported Python version: %s. "
261+
"Minimum supported Python version is 3.6 or above."
262+
% platform.python_version(),
263+
)
264+
234265
state = {
235266
"core_version": platformio.__version__,
236267
"python_version": platform.python_version()
237268
}
238269
print(json.dumps(state))
239270
"""
240271
state = subprocess.check_output(
241-
[python_exe, "-c", code,], stderr=subprocess.STDOUT,
272+
[
273+
python_exe,
274+
"-c",
275+
code,
276+
],
277+
stderr=subprocess.STDOUT,
242278
)
243279
return json.loads(state.decode())
244280

@@ -256,7 +292,8 @@ def upgrade_core(platformio_exe, dev=False):
256292
command.append("--dev")
257293
try:
258294
subprocess.check_output(
259-
command, stderr=subprocess.PIPE,
295+
command,
296+
stderr=subprocess.PIPE,
260297
)
261298
return True
262299
except Exception as e: # pylint:disable=broad-except

pioinstaller/home.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@
1414

1515
import logging
1616
import multiprocessing
17-
import subprocess
1817

1918
import requests
2019

21-
from pioinstaller import exception
22-
2320
HTTP_HOST = "127.0.0.1"
2421
HTTP_PORT_BEGIN = 8008
2522
HTTP_PORT_END = 8050
@@ -44,14 +41,3 @@ def shutdown_pio_home_servers():
4441
proc.join(10)
4542
proc.terminate()
4643
return True
47-
48-
49-
def install_pio_home(platformio_exe):
50-
try:
51-
subprocess.check_output(
52-
[platformio_exe, "home", "--host", "__do_not_start__"],
53-
stderr=subprocess.PIPE,
54-
)
55-
return True
56-
except Exception as e: # pylint:disable=broad-except
57-
raise exception.PIOInstallerException("Could not install PIO Home: %s" % str(e))

pioinstaller/penv.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ def create_virtualenv(python_exe, penv_dir):
9292
return create_with_remote_venv(python_exe, penv_dir)
9393
except Exception as e: # pylint:disable=broad-except
9494
log.debug(
95-
"Could not create virtualenv with downloaded script. Error: %s", str(e),
95+
"Could not create virtualenv with downloaded script. Error: %s",
96+
str(e),
9697
)
9798

9899

@@ -148,7 +149,10 @@ def add_state_info(python_exe, penv_dir):
148149
)
149150
state = {
150151
"created_on": int(round(time.time())),
151-
"python": {"path": python_exe, "version": python_version,},
152+
"python": {
153+
"path": python_exe,
154+
"version": python_version,
155+
},
152156
"installer_version": __version__,
153157
"platform": platform.platform(terse=True),
154158
}
@@ -176,6 +180,7 @@ def install_pip(python_exe, penv_dir):
176180
return True
177181
except Exception as e: # pylint:disable=broad-except
178182
log.debug(
179-
"Could not install pip. Error: %s", str(e),
183+
"Could not install pip. Error: %s",
184+
str(e),
180185
)
181186
return False

pioinstaller/python.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ def is_conda():
4848
[
4949
os.path.exists(os.path.join(sys.prefix, "conda-meta")),
5050
# (os.getenv("CONDA_PREFIX") or os.getenv("CONDA_DEFAULT_ENV")),
51-
"anaconda" in sys.executable,
52-
"miniconda" in sys.executable,
53-
"Continuum Analytics" in sys.version,
54-
"conda" in sys.version,
51+
"anaconda" in sys.executable.lower(),
52+
"miniconda" in sys.executable.lower(),
53+
"continuum analytics" in sys.version.lower(),
54+
"conda" in sys.version.lower(),
5555
]
5656
)
5757

@@ -93,15 +93,13 @@ def fetch_portable_python(dst):
9393
def check():
9494
# platform check
9595
if sys.platform == "cygwin":
96-
raise exception.IncompatiblePythonError("Unsupported cygwin platform")
96+
raise exception.IncompatiblePythonError("Unsupported Cygwin platform")
9797

9898
# version check
99-
if not (
100-
sys.version_info >= (2, 7, 9) and sys.version_info < (3,)
101-
) and not sys.version_info >= (3, 5):
99+
if sys.version_info < (3, 6):
102100
raise exception.IncompatiblePythonError(
103-
"Unsupported python version: %s. "
104-
"Supported version: >= 2.7.9 and < 3, or >= 3.5"
101+
"Unsupported Python version: %s. "
102+
"Minimum supported Python version is 3.6 or above."
105103
% platform.python_version(),
106104
)
107105

@@ -116,7 +114,7 @@ def check():
116114

117115
# portable Python 3 for macOS is not compatible with macOS < 10.13
118116
# https://github.com/platformio/platformio-core-installer/issues/70
119-
if util.IS_MACOS and sys.version_info >= (3, 5):
117+
if util.IS_MACOS:
120118
with tempfile.NamedTemporaryFile() as tmpfile:
121119
os.utime(tmpfile.name)
122120

@@ -142,11 +140,13 @@ def check():
142140
return True
143141

144142

145-
def find_compatible_pythons(ignore_pythons=None): # pylint: disable=too-many-branches
143+
def find_compatible_pythons(
144+
ignore_pythons=None, raise_exception=True
145+
): # pylint: disable=too-many-branches
146146
ignore_list = []
147147
for p in ignore_pythons or []:
148148
ignore_list.extend(glob.glob(p))
149-
exenames = ["python3", "python", "python2"]
149+
exenames = ["python3", "python"]
150150
if util.IS_WINDOWS:
151151
exenames = ["%s.exe" % item for item in exenames]
152152
log.debug("Current environment PATH %s", os.getenv("PATH"))
@@ -195,8 +195,16 @@ def find_compatible_pythons(ignore_pythons=None): # pylint: disable=too-many-br
195195
"""Can not install PlatformIO Core due to a missed `distutils` package in your Python installation.
196196
Please install this package manually using the OS package manager. For example:
197197
198-
$ apt-get install python3-distutils
198+
$ apt-get install python3-venv
199199
200200
(MAY require administrator access `sudo`)""",
201201
)
202+
203+
if not result and raise_exception:
204+
raise exception.IncompatiblePythonError(
205+
"Could not find compatible Python 3.6 or above in your system."
206+
"Please install the latest official Python 3 and restart installation:\n"
207+
"https://docs.platformio.org/page/faq.html#install-python-interpreter"
208+
)
209+
202210
return result

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@
3636
install_requires=[
3737
# Core
3838
"click==7.1.2",
39-
"requests==2.24.0",
40-
"colorama==0.4.3",
39+
"requests==2.25.1",
40+
"colorama==0.4.4",
4141
"semantic-version==2.8.5",
42-
"certifi==2020.6.20",
42+
"certifi==2020.12.5",
4343
# Misc
44-
"wheel==0.35.1",
44+
"wheel==0.36.2",
4545
],
4646
packages=find_packages(),
4747
entry_points={

tests/test_core.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,3 @@ def test_install_pio_core(pio_installer_script, tmpdir, monkeypatch):
6060
"platformio.exe" if util.IS_WINDOWS else "platformio",
6161
)
6262
)
63-
assert os.path.isfile(
64-
os.path.join(str(core_dir), "packages", "contrib-piohome", "package.json")
65-
)
66-
assert os.path.isfile(
67-
os.path.join(str(core_dir), "packages", "contrib-pysite", "package.json")
68-
)

0 commit comments

Comments
 (0)