Change recommended installation method to pipx (#325)

This commit is contained in:
Andres Perez 2022-02-23 17:46:50 -05:00 committed by GitHub
parent 99660e8645
commit 44472258ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 488 deletions

View File

@ -1,393 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import math
import os
import shutil
import sys
import tempfile
from subprocess import call
try:
from shutil import which
except ImportError:
from distutils.spawn import find_executable as which
try:
from urllib.request import urlretrieve
except ImportError:
from urllib import urlretrieve
IS_WIN = sys.platform == "win32"
if IS_WIN:
try:
import winreg
except ImportError:
import _winreg as winreg
from ctypes import windll, wintypes
VIRTUALENV_URL = "https://bootstrap.pypa.io/virtualenv.pyz"
# this difference is for backwards-compatibility with the previous installer
APP_NAME = "lektor" if not IS_WIN else "lektor-cli"
# where to search for a writable bin directory on *nix.
# this order makes sure we try a system install first.
POSIX_BIN_DIRS = [
"/usr/local/bin", "/opt/local/bin",
"{home}/.bin", "{home}/.local/bin",
]
SILENT = (
os.environ.get("LEKTOR_SILENT", "").lower()
not in ("", "0", "off", "false")
)
if not os.isatty(sys.stdin.fileno()):
# the script is being piped, we need to reset stdin
sys.stdin = open("CON:" if IS_WIN else "/dev/tty")
if sys.version_info.major == 2:
input = raw_input
def get_confirmation():
if SILENT:
return
while True:
user_input = input("Continue? [Yn] ").lower().strip()
if user_input in ("", "y"):
print()
return
if user_input == "n":
print()
print("Aborted!")
sys.exit()
def fail(message):
print("Error: %s" % message, file=sys.stderr)
sys.exit(1)
def multiprint(*lines, **kwargs):
for line in lines:
print(line, **kwargs)
def rm_recursive(*paths):
def _error(path):
multiprint(
"Problem deleting {}".format(path),
"Please try and delete {} manually".format(path),
"Aborted!",
file=sys.stderr,
)
sys.exit(1)
def _rm(path):
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.remove(path)
for path in paths:
if not os.path.lexists(path):
continue
try:
_rm(path)
except:
_error(path)
class Progress(object):
"A context manager to be used as a urlretrieve reporthook."
def __init__(self):
self.started = False
def progress(self, count, bsize, total):
size = count * bsize
if size > total:
progress = 100
else:
progress = math.floor(100 * size / total)
out = sys.stdout
if self.started:
out.write("\b" * 4)
out.write("{:3d}%".format(progress))
out.flush()
self.started = True
def finish(self):
sys.stdout.write("\n")
def __enter__(self):
return self.progress
def __exit__(self, exc_type, exc_value, traceback):
self.finish()
class FetchTemp(object):
"""
Fetches the given URL into a temporary file.
To be used as a context manager.
"""
def __init__(self, url):
self.url = url
fname = os.path.basename(url)
root, ext = os.path.splitext(fname)
self.filename = tempfile.mktemp(prefix=root + "-", suffix=ext)
def fetch(self):
with self.Progress() as hook:
urlretrieve(self.url, self.filename, reporthook=hook)
def cleanup(self):
os.remove(self.filename)
def __enter__(self):
self.fetch()
return self.filename
def __exit__(self, exc_type, exc_value, traceback):
self.cleanup()
def create_virtualenv(target_dir):
"""
Tries to create a virtualenv by using the built-in `venv` module,
or using the `virtualenv` executable if present, or falling back
to downloading the official zipapp.
"""
def use_venv():
try:
import venv
except ImportError:
return
# on Debian and Ubuntu systems Python is missing `ensurepip`,
# prompting the user to install `python3-venv` instead.
#
# we could handle this, but we'll just let the command fail
# and have the users install the package themselves.
return call([sys.executable, "-m", "venv", target_dir])
def use_virtualenv():
venv_exec = which("virtualenv")
if not venv_exec:
return
return call([venv_exec, "-p", sys.executable, target_dir])
def use_zipapp():
print("Downloading virtualenv: ", end="")
with FetchTemp(VIRTUALENV_URL) as zipapp:
return call([sys.executable, zipapp, target_dir])
print("Installing virtual environment...")
for func in use_venv, use_virtualenv, use_zipapp:
retval = func()
if retval is None:
# command did not run
continue
if retval == 0:
# command successful
return
# else...
sys.exit(1)
def get_pip(lib_dir):
return (
os.path.join(lib_dir, "Scripts", "pip.exe") if IS_WIN
else os.path.join(lib_dir, "bin", "pip")
)
def install_lektor(lib_dir):
create_virtualenv(lib_dir)
pip = get_pip(lib_dir)
args = [pip, "install"]
if IS_WIN:
# avoid fail due to PEP 517 on windows
args.append("--prefer-binary")
args.extend(["--upgrade", "Lektor"])
return call(args)
def posix_find_bin_dir():
home = os.environ["HOME"]
preferred = [d.format(home=home) for d in POSIX_BIN_DIRS]
# look for writable directories in the user's $PATH
# (that are not sbin)
dirs = [
item
for item in os.environ["PATH"].split(":")
if not item.endswith("/sbin") and os.access(item, os.W_OK)
]
if not dirs:
fail(
"None of the items in $PATH are writable. Run with "
"sudo or add a $PATH item that you have access to."
)
# ... and prioritize them according to our preferences
def _sorter(path):
try:
return preferred.index(path)
except ValueError:
return float("inf")
dirs.sort(key=_sorter)
return dirs[0]
def posix_find_lib_dir(bin_dir):
# the chosen lib_dir depends on the bin_dir found:
home = os.environ["HOME"]
if bin_dir.startswith(home):
# this is a local install
return os.path.join(home, ".local", "lib", APP_NAME)
# else, it's a system install
parent = os.path.dirname(bin_dir)
return os.path.join(parent, "lib", APP_NAME)
def windows_create_link(lib_dir, target_dir):
exe = os.path.join(lib_dir, "Scripts", "lektor.exe")
link = os.path.join(target_dir, "lektor.cmd")
with open(link, "w") as link_file:
link_file.write("@echo off\n")
link_file.write('"{}" %*'.format(exe))
def windows_add_to_path(location):
HWND_BROADCAST = 0xFFFF
WM_SETTINGCHANGE = 0x1A
key = winreg.OpenKey(
winreg.HKEY_CURRENT_USER, "Environment", 0, winreg.KEY_ALL_ACCESS
)
try:
value, _ = winreg.QueryValueEx(key, "Path")
except WindowsError:
value = ""
paths = [path for path in value.split(";") if path != ""]
if location not in paths:
paths.append(location)
value = ";".join(paths)
winreg.SetValueEx(
key, "Path", 0, winreg.REG_EXPAND_SZ, value
)
SendMessage = windll.user32.SendMessageW
SendMessage.argtypes = (
wintypes.HWND, wintypes.UINT, wintypes.WPARAM, wintypes.LPVOID
)
SendMessage.restype = wintypes.LPARAM
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, "Environment")
# also add the path to the environment,
# so it's available in the current console
os.environ['Path'] += ";%s" % location
key.Close()
def posix_install():
bin_dir = posix_find_bin_dir()
lib_dir = posix_find_lib_dir(bin_dir)
symlink_path = os.path.join(bin_dir, APP_NAME)
multiprint(
"Installing at:",
" bin: %s" % bin_dir,
" app: %s" % lib_dir,
"",
)
if os.path.exists(lib_dir) or os.path.lexists(symlink_path):
multiprint(
"An existing installation was detected. This will be removed!",
"",
)
get_confirmation()
rm_recursive(lib_dir, symlink_path)
install_lektor(lib_dir)
os.symlink(os.path.join(lib_dir, "bin", "lektor"), symlink_path)
def windows_install():
install_dir = os.path.join(os.environ["LocalAppData"], APP_NAME)
lib_dir = os.path.join(install_dir, "lib")
multiprint(
"Installing at:",
" %s" % install_dir,
"",
)
if os.path.exists(install_dir):
multiprint(
"An existing installation was detected. This will be removed!",
"",
)
get_confirmation()
rm_recursive(install_dir)
install_lektor(lib_dir)
windows_create_link(lib_dir, install_dir)
windows_add_to_path(install_dir)
def install():
multiprint(
"",
"Welcome to Lektor",
"This script will install Lektor on your computer.",
"",
)
if IS_WIN:
windows_install()
else:
posix_install()
multiprint(
"",
"All done!",
)
if __name__ == "__main__":
install()

View File

@ -27,9 +27,6 @@ contents:
><i class="glyphicon glyphicon-download-alt"></i> Download</a></div>
</div>
</div>
<div class="install-row hide-for-windows">
<pre>curl -sf https://www.getlektor.com/installer.py | sudo python3</pre>
</div>
</div>
#### text-block ####
text:

View File

@ -6,86 +6,84 @@ sort_key: 50
---
body:
Lektor comes in two flavors: as a command line executable and as a
desktop application. The desktop version also contains the command
line executable, but it also bundles together all dependencies of Lektor
in an easy to use package which heavily simplifies installation.
Lektor is a command line utility, and requires some terminal or command line work
to install. If you can read and follow instructions, you will most likely have no
issues.
## Desktop Application
## Requirements
!! Info: Support for the Mac Desktop Application is paused as of version 3.1. See [note](/blog/2018/1/lektor-31-released/#support-for-mac-installer-paused).
Although `lektor` would work without Imagemagick or FFmpeg, you would be missing on
significant parts of its capabilities. Therefore, you need to make sure you have the
following software installed on your computer:
Currently the desktop application is only available for OS X and can be
[downloaded from the Lektor website](../../downloads/). It comes as a downloadable
disk image that you can mount which contains one application by the name of
`Lektor.app`. Just drag it into your `Applications` folder and you are good to
go.
* Python 3.6+ is required. If you got an older version, look at
{Python 3 Installation & Setup Guide}(https://realpython.com/installing-python/).
* On Ubuntu you basically don't need anything new.
* On macOS you're done as well.
* On Windows, make sure that Python is in your `PATH`.
* ImageMagick.
* On macOS `brew install imagemagick` can get you this.
* On Ubuntu `sudo apt install imagemagick` will solve it.
* On Windows do `choco install imagemagick`, which requires [chocolatey :ext](https://chocolatey.org/),
or [download from here :ext](http://www.imagemagick.org)).
* FFmpeg (mostly for video thumbnailing).
* On Ubuntu you get it through `sudo apt install ffmpeg.`
* On macOS `brew install ffmpeg` will do the trick.
* On Windows you'll have to put a little [work](https://www.wikihow.com/Install-FFmpeg-on-Windows) in.
If you also want access to the command line tools just launch `Lektor.app`
and then click in the menu bar on *Lektor ➤ Install Shell Command*.
## Command Line Application
If you do not want to install the desktop app then you can just install the command
line executable. This runs on most operating systems (OSX, Linux and Windows) but
the installation is a bit more involved.
You need to make sure you have the following software installed on your computer:
* Python 3 is recommended (but 2.7 is also supported)
On Ubuntu `python3-dev`, `libssl-dev` and `libffi-dev` are also required
`sudo apt-get install python3-dev libssl-dev libffi-dev`
* ImageMagick (`brew install imagemagick` can get you this on OS X and `sudo apt-get install imagemagick`
on Ubuntu the `imagemagick` package needs to be installed.
On Windows do `choco install imagemagick`, which requires [chocolatey :ext](https://chocolatey.org/),
or [download from here :ext](http://www.imagemagick.org)).
## Install pipx
Once you have those installed and have made sure that they are on your `PATH`, you can
get Lektor installed with our installation script:
get Lektor installed with `pipx`. Selcet the `pipx` install method of your preference:
__On Ubuntu through `apt`.__
```
# curl -sf https://www.getlektor.com/installer.py | python3
apt update
sudo apt install python3-venv pipx
pipx ensurepath
```
__On Ubuntu through `pip`.__
```
sudo apt install python3-pip python3-venv
python3 -m pip install --user pipx
python3 -m pipx ensurepath
```
__On macOS__
```
brew install pipx
pipx ensurepath
```
__On Windows__
```
python -m pip install --user pipx
python -m pipx ensurepath
```
This will attempt to install lektor in your user's `HOME`. If you want a system-wide installation, try this instead:
For more information on `pipx` installation go to [pypa.github.io/pipx/installation/](https://pypa.github.io/pipx/installation/)
### Finally Install Lektor
Once installed, close terminal (or `Powershell` or `command prompt`) for those
changes to take effect. Then proceed to reopen and install Lektor with pipx:
```
$ curl -sf https://www.getlektor.com/installer.py | sudo python3
```
If you would like to install Lektor without being prompted, set LEKTOR_SILENT before running the prior command.
For Windows, make sure that Python is in your `PATH` and run in `Powershell`:
```
PS C:\> (new-object net.webclient).DownloadString('https://www.getlektor.com/installer.py') | python
```
or you can use the `command prompt` instead:
```
C:\> @powershell -NoProfile -Command "(new-object net.webclient).DownloadString('https://www.getlektor.com/installer.py') | python"
pipx install lektor
```
## pip
Alternatively you can manually install the command line version with
`virtualenv` if you know how that works. Note that this method is *heavily
discouraged* for anything other than advanced use cases such as build servers.
`pip` after creating a virtual environment, if you know how that works. `pipx` technically does this for you,
then if you need something particular and you know this will make it easier,
go for it.
```
$ virtualenv venv
$ . venv/bin/activate
$ pip install Lektor
virtualenv venv
. venv/bin/activate
pip install Lektor
```
!!!! When we say this installation type is discouraged we mean it. The reason
is that it encourages uses of Lektor which are entirely unsupported by us.
Lektor actively manages virtualenvs for plugin installations in very specific
ways and this might or might not work in your setup. We support pip
installations for deployment environments and local development only.
## Development Version
If you want to install the development version of Lektor you can do so. It's
@ -94,10 +92,10 @@ using PyPI you install directly from git and you need to have `npm` installed
to build the admin UI:
```
$ git clone https://github.com/lektor/lektor
$ cd lektor
$ make build-js
$ virtualenv venv
$ . venv/bin/activate
$ pip install --editable .
git clone https://github.com/lektor/lektor
cd lektor
make build-js
virtualenv venv
. venv/bin/activate
pip install --editable .
```

View File

@ -15,46 +15,51 @@ text:
Lektor is an [Open Source Project](../license/) and freely available to
download. It's currently still under heavy development and not all platforms
are equally well supported.
are equally well supported, although closer to it.
## Command Line Interface
If you are on Linux or Mac you can install the command line version of
You can install the command line version of
Lektor by copy/pasting a command into your terminal.
!!! Scared about copy/pasting this into a terminal? We will not do anything
before asking you for confirmation and you can download [the script](https://www.getlektor.com/installer.py)
upfront to see what it's doing.
!!! Scared about copy/pasting this into a terminal? We now use standard tools
to install lektor. `pipx` is the recommended method to install standalone
command line interface python packages as recommended by [PyPA](https://packaging.python.org/guides/installing-stand-alone-command-line-tools/).
### Mac/Linux
### First Install PipX
This will install Lektor in your `HOME`. Running it with `sudo` will result in
a system installation instead.
Let's first install `pipx`.
__Ubuntu__
```
sudo apt install python3-pip python3-venv
python3 -m pip install --user pipx
python3 -m pipx ensurepath
```
__macOS__
```
bew install pipx
pipx ensurepath
```
__Windows__
```
python -m pip install --user pipx
python -m pipx ensurepath
```
For more information on `pipx` installation go to [pypa.github.io/pipx/installation/](https://pypa.github.io/pipx/installation/)
### Let's install Lektor now
Close and reopen terminal (`Powershell` or `cmd` on Windows), then install `lektor`:
```
curl -sf https://www.getlektor.com/installer.py | python3
pipx install lektor
```
You might need additional dependencies for this installation. For more
information see [Installation](../docs/installation/).
### Windows
If you are on Windows copy/paste this command into `Powershell`:
```
(new-object net.webclient).DownloadString('https://www.getlektor.com/installer.py') | python
```
or alternatively use this in `command prompt`:
```
@powershell -NoProfile -Command "(new-object net.webclient).DownloadString('https://www.getlektor.com/installer.py') | python"
```
## Desktop Application
Lektor supported an installable version of Lektor on OSX. The current build process for these installers is [old and in need of refactoring](https://github.com/lektor/lektor/issues/420). Temporarily until this is resolved, as of version 3.1, this installer is no longer supported.
----
class: default