#!/usr/bin/env python3 # -*- coding: utf-8 -*- """The setup script.""" from collections import namedtuple from html.parser import HTMLParser import os from urllib.error import HTTPError, URLError from urllib.request import urlopen import pkg_resources from setuptools import setup, find_packages from setuptools.command.develop import develop from setuptools.command.install import install import sys import tarfile import zipfile GECKO_RELEASE_PATH = "https://github.com/mozilla/geckodriver" PKG_NAME = 'bot_z' VERSION = '0.1.0' AUTHOR = 'blallo' AUTHOR_EMAIL = 'blallo@autistici.org' with open('README.md') as readme_file: readme = readme_file.read() requirements = [ 'Click>=6.0', 'selenium>=3.141.0', ] setup_requirements = [ ] test_requirements = [ ] class GitTags(HTMLParser): tags = list() take_next = 0 def handle_starttag(self, tag, attrs): dattrs = dict(attrs) if 'commit-title' in dattrs.get('class', ''): 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: self.tags.append(data.strip('\n').strip(' ').strip('\n')) self.take_next = 0 def retrieve_page(url: str) -> bytes: """ Auxiliary function to download html body from and URI, handling the errors. """ try: content = urlopen(url).read() 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. """ tag_page = retrieve_page('{}/tags'.format(url)) gt = GitTags() gt.feed(tag_page.decode('utf-8')) 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 def create_local_folder() -> None: """ Create a bin/ folder in the current package installation path. """ bin_path = pkg_resources.resource_filename(PKG_NAME, BIN_PATH) def assemble_driver_uri() -> str: """ Selects the right geckodriver URI. """ # TODO: use pkg_resources.get_platform() latest_vers = find_latest_version(GECKO_RELEASE_PATH) platform = sys.platform is_64bits = sys.maxsize > 2**32 if is_64bits: full_platform = '{}64'.format(platform) else: full_platform = '{}64'.format(platform) if 'win' in platform: ext = 'zip' else: ext = 'tar.gz' return '{base}/releases/download/{vers}/geckodriver-{vers}-{platform}.{ext}'.format( base=GECKO_RELEASE_PATH, vers=latest_vers, platform=full_platform, ext=ext ) def download_driver_bin(uri: str, path: str) -> None: """ Donwloads the geckodriver binary. """ name = uri.split('/')[-1] filepath = os.path.join(path, name) print("[DRIVER] downloading '{}' to {}".format(uri, filepath)) content = retrieve_page(uri) try: with open(filepath, 'wb') as f: f.write(content) if name.endswith(".zip"): with zipfile.ZipFile(filepath, 'r') as z: z.extractall(path) elif name.endswith(".tar.gz"): with tarfile.open(filepath, 'r') as r: r.extractall(path) finally: os.remove(filepath) def postinstall() -> None: """ 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') target_path = pkg_resources.resource_filename('bot_z', 'bin') pkg_resources.ensure_directory(os.path.join(target_path, 'target')) gecko_uri = assemble_driver_uri() print("[POSTINSTALL] gecko_uri: {}".format(gecko_uri)) download_driver_bin(gecko_uri, target_path) # From: https://stackoverflow.com/a/36902139 class PostDevelopCommand(develop): """Post-installation for development mode.""" def run(self): super().run() print("POSTINSTALL") postinstall() class PostInstallCommand(install): """Post-installation for installation mode.""" def run(self): super().run() postinstall() setup( name=PKG_NAME, version=VERSION, description="A bot to easen the daily routine with zucchetti virtual badge.", long_description=readme, author=AUTHOR, author_email=AUTHOR_EMAIL, url='https://git.abbiamoundominio.org/blallo/BotZ', packages=find_packages(include=['bot_z']), cmdclass={ 'develop': PostDevelopCommand, 'install': PostInstallCommand, }, entry_points={ 'console_scripts': [ 'bot_z=bot_z.cli:main' ] }, include_package_data=True, install_requires=requirements, license="GLWTS Public Licence", zip_safe=False, keywords='bot_z', classifiers=[ 'Development Status :: 2 - Pre-Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 'Natural Language :: English', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.7', ], test_suite='pytest', tests_require=test_requirements, setup_requires=setup_requirements, )