diff --git a/installers-conda/build_conda_pkgs.py b/installers-conda/build_conda_pkgs.py index df09c2fc2a2..42918205b1f 100644 --- a/installers-conda/build_conda_pkgs.py +++ b/installers-conda/build_conda_pkgs.py @@ -1,7 +1,13 @@ +# -*- coding: utf-8 -*- +# +# Copyright © Spyder Project Contributors +# Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) + """ Build conda packages to local channel. -This module builds conda packages for spyder and external-deps for +This module builds conda packages for Spyder and external-deps for inclusion in the conda-based installer. The Following classes are provided for each package: SpyderCondaPkg @@ -10,10 +16,10 @@ QtconsoleCondaPkg SpyderKernelsCondaPkg -spyder will be packaged from this repository (in its checked-out state). +Spyder will be packaged from this repository (in its checked-out state). qdarkstyle, qtconsole, and spyder-kernels will be packaged from the external-deps directory of this repository (in its checked-out state). -python-lsp-server, however, will be packaged from the upstream remote +Python-lsp-server, however, will be packaged from the upstream remote at the same commit as the external-deps state. Alternatively, any external-deps may be packaged from a local git repository @@ -24,21 +30,25 @@ QTCONSOLE_SOURCE SPYDER_KERNELS_SOURCE """ + +# Standard library imports import os import re from argparse import ArgumentParser from configparser import ConfigParser from datetime import timedelta -from git import Repo from logging import Formatter, StreamHandler, getLogger from pathlib import Path -from ruamel.yaml import YAML -from setuptools_scm import get_version from shutil import rmtree from subprocess import check_call from textwrap import dedent from time import time +# Third-party imports +from git import Repo +from ruamel.yaml import YAML +from setuptools_scm import get_version + fmt = Formatter('%(asctime)s [%(levelname)s] [%(name)s] -> %(message)s') h = StreamHandler() h.setFormatter(fmt) @@ -69,7 +79,7 @@ def remove_readonly(func, path, exc): raise -class BuildCondaPkg(): +class BuildCondaPkg: name = None src_path = None feedstock = None @@ -101,7 +111,7 @@ def __init__(self, data={}, debug=False): self._patched_build = False def _get_source(self): - self._build_cleanup() # Remove existing if HERE + self._build_cleanup() if not self.src_path.exists(): cfg = ConfigParser() @@ -182,7 +192,6 @@ def build(self): check_call( ["mamba", "mambabuild", str(self.fdstk_path / "recipe")] ) - finally: self._patched_meta = False self._patched_build = False @@ -281,11 +290,11 @@ class SpyderKernelsCondaPkg(BuildCondaPkg): p = ArgumentParser( description=dedent( """ - Build conda packages from local spyder and external-deps sources. + Build conda packages from local Spyder and external-deps sources. Alternative git repo for python-lsp-server may be provided by setting the environment variable PYTHON_LSP_SERVER_SOURCE, otherwise the upstream remote will be used. All other external-deps - use the subrepo source within the spyder repo. + use the subrepo source within the Spyder repo. """ ), usage="python build_conda_pkgs.py " diff --git a/installers-conda/build_installers.py b/installers-conda/build_installers.py index e9194392306..869a1f19630 100644 --- a/installers-conda/build_installers.py +++ b/installers-conda/build_installers.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- +# +# Copyright © Spyder Project Contributors +# Licensed under the terms of the MIT License +# (see spyder/__init__.py for details) + """ Create Spyder installers using `constructor`. @@ -16,23 +22,27 @@ Path to PFX certificate to sign the EXE installer on Windows """ -import json -import os -import platform -import re -import sys -import zipfile +# Standard library imports from argparse import ArgumentParser from datetime import timedelta from distutils.spawn import find_executable from functools import partial +import json from logging import getLogger +import os from pathlib import Path -from ruamel.yaml import YAML +import platform +import re from subprocess import check_call +import sys from textwrap import dedent, indent from time import time +import zipfile + +# Third-party imports +from ruamel.yaml import YAML +# Local imports from build_conda_pkgs import HERE, DIST, RESOURCES, SPECS, h, get_version logger = getLogger('BuildInstallers') @@ -45,11 +55,12 @@ MACOS = sys.platform == "darwin" LINUX = sys.platform.startswith("linux") TARGET_PLATFORM = os.environ.get("CONSTRUCTOR_TARGET_PLATFORM") +PY_VER = f"{sys.version_info.major}.{sys.version_info.minor}" + if TARGET_PLATFORM == "osx-arm64": ARCH = "arm64" else: ARCH = (platform.machine() or "generic").lower().replace("amd64", "x86_64") -PY_VER = f"{sys.version_info.major}.{sys.version_info.minor}" if WINDOWS: EXT, OS = "exe", "Windows" elif LINUX: @@ -125,6 +136,7 @@ "paramiko": "", "pyxdg": "", } + if SPECS.exists(): logger.info(f"Reading specs from {SPECS}...") _specs = yaml.load(SPECS.read_text()) @@ -146,7 +158,7 @@ def _generate_background_images(installer_type): - """Requires pillow""" + """This requires Pillow.""" if installer_type == "sh": # shell installers are text-based, no graphics return @@ -183,7 +195,6 @@ def _get_condarc(): contents = dedent( f""" channels: #!final - - spyder-ide - conda-forge {defaults} repodata_fns: #!final @@ -211,7 +222,6 @@ def _definitions(): "version": SPYVER, "channels": [ "napari/label/bundle_tools", - "spyder-ide", "conda-forge", ], "conda_default_channels": ["conda-forge"], @@ -237,6 +247,7 @@ def _definitions(): condarc: ".condarc", }, } + if not args.no_local: definitions["channels"].insert(0, "local") @@ -268,6 +279,7 @@ def _definitions(): "post_install": str(RESOURCES / "post-install.sh"), } ) + if args.cert_id: definitions["signing_identity_name"] = args.cert_id definitions["notarization_identity_name"] = args.cert_id @@ -293,6 +305,7 @@ def _definitions(): "installer_type": "exe", } ) + signing_certificate = os.environ.get("CONSTRUCTOR_SIGNING_CERTIFICATE") if signing_certificate: definitions["signing_certificate"] = signing_certificate @@ -307,16 +320,6 @@ def _constructor(): """ Create a temporary `construct.yaml` input file and run `constructor`. - - Parameters - ---------- - version: str - Version of `spyder` to be built. Defaults to the - one detected by `importlib` from the source code. - extra_specs: list of str - Additional packages to be included in the installer. - A list of conda spec strings (`numpy`, `python=3`, etc) - is expected. """ constructor = find_executable("constructor") if not constructor: diff --git a/installers-conda/resources/bundle_readme.md b/installers-conda/resources/bundle_readme.md index 0bc76757af3..ac6bd600792 100644 --- a/installers-conda/resources/bundle_readme.md +++ b/installers-conda/resources/bundle_readme.md @@ -8,9 +8,9 @@ This is the base installation of Spyder, the Scientific Python Development Envir In most cases, you would run it through the platform-specific shortcut we created for your convenience. In other words, _not_ through this directory! -* Linux: check your desktop launcher. -* MacOS: check `~/Applications` or the Launchpad. -* Windows: check the Start Menu or the Desktop. +* Linux: Check your desktop launcher. +* MacOS: Check `~/Applications` or the Launchpad. +* Windows: Check the Start Menu or the Desktop. We generally recommend using the shortcut because it will pre-activate the `conda` environment for you! That said, you can also execute the `spyder` executable directly from these locations: @@ -23,13 +23,13 @@ need to activate the `conda` environment to ensure all dependencies are importab ## What does `conda` have to do with `spyder`? -The Spyder installer uses `conda` packages to bundle all its dependencies (Python, qt, etc). +The Spyder installer uses `conda` packages to bundle all its dependencies (Python, Qt, etc). This directory is actually a full `conda` installation! If you have used `conda` before, this is equivalent to what you usually call the `base` environment. ## Can I modify the `spyder` installation? -Yes. In practice, you can consider it a `conda` environment. You can even activate it as usual, +Yes, but it is not recommended (see below). In practice, you can consider it a `conda` environment. You can even activate it as usual, provided you specify the full path to the location, instead of the _name_. ```