BotZ/setup.py

269 lines
7.3 KiB
Python
Raw Normal View History

2019-01-17 18:17:56 +01:00
#!/usr/bin/env python3
2019-01-07 11:16:16 +01:00
# -*- coding: utf-8 -*-
"""The setup script."""
2019-01-17 18:17:56 +01:00
from collections import namedtuple
from html.parser import HTMLParser
import os
import pkg_resources
2019-01-21 09:32:41 +01:00
from setuptools import setup, find_packages # noqa
from setuptools.command.develop import develop # noqa
from setuptools.command.install import install # noqa
from setuptools.command.bdist_egg import bdist_egg # noqa
2019-01-17 18:17:56 +01:00
import sys
import tarfile
2019-01-21 09:32:41 +01:00
import typing as T
from urllib.error import HTTPError, URLError
from urllib.request import urlopen
from wheel.bdist_wheel import bdist_wheel # noqa
2019-01-17 18:17:56 +01:00
import zipfile
2019-01-07 11:16:16 +01:00
2019-01-17 18:17:56 +01:00
GECKO_RELEASE_PATH = "https://github.com/mozilla/geckodriver"
2019-01-21 17:59:44 +01:00
PKG_NAME = "bot_z"
VERSION = "0.1.0"
AUTHOR = "blallo"
AUTHOR_EMAIL = "blallo@autistici.org"
BIN_PATH = "bin/geckodriver"
2019-01-17 18:17:56 +01:00
2019-01-21 17:59:44 +01:00
with open("README.md") as readme_file:
2019-01-17 18:17:56 +01:00
readme = readme_file.read()
2019-01-07 11:16:16 +01:00
requirements = [
"Click>=7.0",
"selenium>=3.141.0",
"lockfile>=0.12.2",
"python-daemon>=2.2.3",
]
2019-01-07 11:16:16 +01:00
2019-01-21 17:59:44 +01:00
setup_requirements = [] # type: T.List[str]
2019-01-07 11:16:16 +01:00
2019-01-21 17:59:44 +01:00
test_requirements = [] # type: T.List[str]
2019-01-07 11:16:16 +01:00
2019-01-17 18:17:56 +01:00
class GitTags(HTMLParser):
2019-01-21 09:32:41 +01:00
tags: T.List[str] = list()
2019-01-17 18:17:56 +01:00
take_next = 0
def handle_starttag(self, tag, attrs):
dattrs = dict(attrs)
2019-01-21 17:59:44 +01:00
if "commit-title" in dattrs.get("class", ""):
2019-01-17 18:17:56 +01:00
self.take_next = 1
def handle_data(self, data):
if self.take_next == 0:
return
elif self.take_next == 1:
self.take_next = 2
elif self.take_next == 2:
2019-01-21 17:59:44 +01:00
self.tags.append(data.strip("\n").strip(" ").strip("\n"))
2019-01-17 18:17:56 +01:00
self.take_next = 0
def retrieve_page(url: str) -> bytes:
"""
Auxiliary function to download html body
from and URI, handling the errors.
"""
try:
2019-01-21 09:32:41 +01:00
with urlopen(url) as conn:
content = conn.read()
2019-01-17 18:17:56 +01:00
except HTTPError as e:
print("Connection error: {!s}".format(e))
raise
except URLError as e:
print("Check the URI: {!s}".format(e))
raise
return content
def find_latest_version(url: str) -> str:
"""
Retrieves latest geckodriver tag.
"""
2019-01-21 17:59:44 +01:00
tag_page = retrieve_page("{}/tags".format(url))
2019-01-17 18:17:56 +01:00
gt = GitTags()
2019-01-21 17:59:44 +01:00
gt.feed(tag_page.decode("utf-8"))
2019-01-17 18:17:56 +01:00
gt.tags.sort()
return gt.tags[-1]
def verify_if_superuser() -> bool:
"""
Checks if uid or euid is 0.
"""
_uid = os.getuid()
_euid = os.geteuid()
return _uid == 0 or _euid == 0
2019-01-21 11:21:33 +01:00
def ensure_local_folder() -> None:
2019-01-17 18:17:56 +01:00
"""
Create a bin/ folder in the current package installation path.
"""
bin_path = pkg_resources.resource_filename(PKG_NAME, BIN_PATH)
2019-01-21 11:21:33 +01:00
print("[LOCAL_FOLDER] ensuring local folder: {}".format(bin_path))
pkg_resources.ensure_directory(bin_path)
2019-01-17 18:17:56 +01:00
2019-01-21 09:32:41 +01:00
def assemble_driver_uri(
2019-01-21 17:59:44 +01:00
version: T.Optional[str] = None, platform: T.Optional[str] = None
) -> str:
2019-01-17 18:17:56 +01:00
"""
Selects the right geckodriver URI.
"""
# TODO: use pkg_resources.get_platform()
2019-01-21 09:32:41 +01:00
if not version:
version = find_latest_version(GECKO_RELEASE_PATH)
if not platform:
s_platform = sys.platform
2019-01-21 17:59:44 +01:00
is_64bits = sys.maxsize > 2 ** 32
2019-01-21 09:32:41 +01:00
if is_64bits:
2019-01-21 17:59:44 +01:00
platform = "{}64".format(s_platform)
2019-01-21 09:32:41 +01:00
else:
2019-01-21 17:59:44 +01:00
platform = "{}64".format(s_platform)
if "win" in platform:
ext = "zip"
2019-01-17 18:17:56 +01:00
else:
2019-01-21 17:59:44 +01:00
ext = "tar.gz"
return "{base}/releases/download/{vers}/geckodriver-{vers}-{platform}.{ext}".format(
base=GECKO_RELEASE_PATH, vers=version, platform=platform, ext=ext
2019-01-17 18:17:56 +01:00
)
def download_driver_bin(uri: str, path: str) -> None:
"""
Donwloads the geckodriver binary.
"""
2019-01-21 17:59:44 +01:00
name = uri.split("/")[-1]
2019-01-17 18:17:56 +01:00
filepath = os.path.join(path, name)
print("[DRIVER] downloading '{}' to {}".format(uri, filepath))
content = retrieve_page(uri)
try:
2019-01-21 17:59:44 +01:00
with open(filepath, "wb") as f:
2019-01-17 18:17:56 +01:00
f.write(content)
if name.endswith(".zip"):
2019-01-21 17:59:44 +01:00
with zipfile.ZipFile(filepath, "r") as z:
2019-01-17 18:17:56 +01:00
z.extractall(path)
elif name.endswith(".tar.gz"):
2019-01-21 17:59:44 +01:00
with tarfile.open(filepath, "r") as r:
2019-01-17 18:17:56 +01:00
r.extractall(path)
2019-01-21 09:32:41 +01:00
else:
raise RuntimeError("Unrecognized file extension: %s", name)
2019-01-17 18:17:56 +01:00
finally:
os.remove(filepath)
2019-01-21 17:59:44 +01:00
def preinstall(platform: T.Optional[str] = None) -> None:
2019-01-17 18:17:56 +01:00
"""
Performs all the postintallation flow, donwloading in the
right place the geckodriver binary.
"""
# target_path = os.path.join(os.path.abspath(os.path.curdir), 'bot_z', 'bin')
2019-01-21 17:59:44 +01:00
target_path = pkg_resources.resource_filename("bot_z", "bin")
2019-01-21 11:21:33 +01:00
ensure_local_folder()
2019-01-21 17:59:44 +01:00
version = os.environ.get("BOTZ_GECKO_VERSION")
2019-01-21 09:32:41 +01:00
gecko_uri = assemble_driver_uri(version, platform)
2019-01-17 18:17:56 +01:00
print("[POSTINSTALL] gecko_uri: {}".format(gecko_uri))
download_driver_bin(gecko_uri, target_path)
2019-01-21 09:32:41 +01:00
def translate_platform_to_gecko_vers(plat: str) -> str:
"""
Map appropriately the platform provided on the command line
to the one used by PEP 513.
"""
2019-01-21 11:21:33 +01:00
if plat is None:
return None
2019-01-21 09:32:41 +01:00
PLATS = {
"win32": "win32",
"win-amd64": "win64",
"manylinux1-i686": "linux32",
"manylinux1-x86_64": "linux64",
"macosx": "macos",
}
try:
return PLATS[plat]
except KeyError as e:
print("Allowed platforms are: {!r}".format(list(PLATS.keys())))
raise
2019-01-17 18:17:56 +01:00
# From: https://stackoverflow.com/a/36902139
2019-01-21 09:32:41 +01:00
class CustomDevelopCommand(develop):
"""Custom installation for development mode."""
2019-01-21 17:59:44 +01:00
2019-01-17 18:17:56 +01:00
def run(self):
print("POSTINSTALL")
2019-01-21 11:21:33 +01:00
preinstall()
super().run()
2019-01-17 18:17:56 +01:00
2019-01-21 09:32:41 +01:00
class CustomInstallCommand(install):
"""Custom installation for installation mode."""
2019-01-21 17:59:44 +01:00
2019-01-17 18:17:56 +01:00
def run(self):
2019-01-21 09:32:41 +01:00
opts = self.distribution.get_cmdline_options()
2019-01-21 11:21:33 +01:00
platform = None
2019-01-21 17:59:44 +01:00
if "bdist_wheel" in opts:
2019-01-21 09:32:41 +01:00
platform = translate_platform_to_gecko_vers(
2019-01-21 17:59:44 +01:00
opts["bdist_wheel"].get("plat-name")
2019-01-21 09:32:41 +01:00
)
2019-01-21 11:21:33 +01:00
preinstall(platform)
super().run()
2019-01-21 09:32:41 +01:00
# From: https://stackoverflow.com/a/45150383
class CustomBDistWheel(bdist_wheel):
"""
Custom bdist_wheel command to ship the right binary
of geckodriver.
"""
2019-01-21 17:59:44 +01:00
2019-01-21 09:32:41 +01:00
def finalize_options(self):
super().finalize_options()
self.root_is_pure = False
def get_tag(self):
python, abi, plat = super().get_tag()
2019-01-21 17:59:44 +01:00
python, abi = "py3", "none"
2019-01-21 09:32:41 +01:00
return python, abi, plat
2019-01-17 18:17:56 +01:00
2019-01-07 11:16:16 +01:00
setup(
2019-01-17 18:17:56 +01:00
name=PKG_NAME,
version=VERSION,
2019-01-07 11:16:16 +01:00
description="A bot to easen the daily routine with zucchetti virtual badge.",
2019-01-17 18:17:56 +01:00
long_description=readme,
author=AUTHOR,
author_email=AUTHOR_EMAIL,
2019-01-21 17:59:44 +01:00
url="https://git.abbiamoundominio.org/blallo/BotZ",
packages=find_packages(include=["bot_z"]),
2019-01-17 18:17:56 +01:00
cmdclass={
2019-01-21 17:59:44 +01:00
"develop": CustomDevelopCommand,
"install": CustomInstallCommand,
"bdist_wheel": CustomBDistWheel,
2019-01-07 11:16:16 +01:00
},
entry_points={"console_scripts": ["bot_z=bot_z.cli:cli"]},
2019-01-21 17:59:44 +01:00
package_data={"bot_z": ["bin/geckodriver"]},
2019-01-07 11:16:16 +01:00
include_package_data=True,
install_requires=requirements,
2019-01-17 18:17:56 +01:00
license="GLWTS Public Licence",
2019-01-07 11:16:16 +01:00
zip_safe=False,
2019-01-21 17:59:44 +01:00
keywords="bot_z",
2019-01-07 11:16:16 +01:00
classifiers=[
2019-01-21 17:59:44 +01:00
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"License :: GLWTS Public Licence",
"Natural Language :: English",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
2019-01-07 11:16:16 +01:00
],
2019-01-21 17:59:44 +01:00
test_suite="pytest",
2019-01-07 11:16:16 +01:00
tests_require=test_requirements,
setup_requires=setup_requirements,
)