1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3 4# Copyright (C) 2011 Chris Dekter 5# 6# This program is free software: you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation, either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19import sys 20import re 21from collections import namedtuple 22import subprocess 23from pathlib import Path 24import warnings 25import shutil 26 27try: 28 from setuptools import setup 29except ImportError: 30 print("Autokey needs setuptools in order to build. Install it with your package" 31 "manager (python-setuptools) or via pip (pip install setuptools)") 32 sys.exit(1) 33else: 34 import setuptools.command.build_py 35 36if sys.version_info < (3, 5, 0): 37 print("Autokey requires Python 3.5 or later. You are using " + ".".join(map(str, sys.version_info[:3]))) 38 sys.exit(1) 39 40 41AutoKeyData = namedtuple("AutoKeyData", ["version", "author", "author_email", "maintainer", "maintainer_email"]) 42 43 44def extract_autokey_data() -> AutoKeyData: 45 source_file_name = "./lib/autokey/common.py" 46 with open(source_file_name, "r") as data_source_file: 47 source = data_source_file.read() 48 if not source: 49 print("Cannot read AutoKey source file containing required information. Unreadable: {}".format( 50 source_file_name)) 51 sys.exit(1) 52 53 def search_for(pattern: str) -> str: 54 return re.search( 55 r"""^{}\s*=\s*('(.*)'|"(.*)")""".format(pattern), # Search for assignments: VAR = 'VALUE' or VAR = "VALUE" 56 source, 57 re.M 58 ).group(1)[1:-1] # Cut off outer quotation marks 59 60 return AutoKeyData( 61 version=search_for("VERSION"), 62 author=search_for("AUTHOR"), 63 author_email=search_for("AUTHOR_EMAIL"), 64 maintainer=search_for("MAINTAINER"), 65 maintainer_email=search_for("MAINTAINER_EMAIL") 66 ) 67 68 69class BuildWithQtResources(setuptools.command.build_py.build_py): 70 """Try to build the Qt resources file for autokey-qt.""" 71 def run(self): 72 if not self.dry_run: 73 resource_dir = (Path(__file__).parent / "lib" / "autokey" / "qtui" / "resources").resolve() 74 resource_file = resource_dir / "resources.qrc" 75 self._copy_icon_files_into_qt_resources_directory(resource_dir) 76 compiled_qt_resources = self._compile_resource_file(resource_file) 77 if compiled_qt_resources: 78 target_directory = Path(self.build_lib) / "autokey" / "qtui" 79 self.mkpath(str(target_directory)) 80 with open(str(target_directory / "compiled_resources.py"), "w") as compiled_qt_resources_file: 81 compiled_qt_resources_file.write(compiled_qt_resources) 82 else: 83 # If here, compilation failed for a known reason, so include the resource files directly. 84 # Ok, always include this for now. setup.py seems to not like this 85 # self.package_data["autokey.qtui"] += ["resources/icons/*", "resources/ui/*.ui"] 86 pass 87 super(BuildWithQtResources, self).run() 88 89 @staticmethod 90 def _compile_resource_file(resource_file: Path) -> str: 91 command = ("pyrcc5", str(resource_file)) 92 try: 93 compiled = subprocess.check_output(command, universal_newlines=True) # type: str 94 except (FileNotFoundError, subprocess.CalledProcessError) as e: 95 warnings.warn("An exception occurred during resource compilation for autokey-qt: {}".format(e)) 96 return "" 97 else: 98 return compiled 99 100 def _copy_icon_files_into_qt_resources_directory(self, resource_dir: Path): 101 target_directory = resource_dir / "icons" 102 self.mkpath(str(target_directory)) 103 icon_source_path = (Path(__file__).parent / "config").resolve() # type: Path 104 for icon_name in ( 105 "autokey.png", 106 "autokey.svg", 107 "autokey-status.svg", 108 "autokey-status-dark.svg", 109 "autokey-status-error.svg"): 110 icon = icon_source_path / icon_name 111 shutil.copy(str(icon), str(target_directory)) 112 113 114ak_data = extract_autokey_data() 115 116setup( 117 name='autokey', 118 version=ak_data.version, 119 description='AutoKey (Python 3)', 120 author=ak_data.author, 121 author_email=ak_data.author_email, 122 maintainer=ak_data.maintainer, 123 maintainer_email=ak_data.maintainer_email, 124 url='https://github.com/autokey/autokey', 125 cmdclass={'build_py': BuildWithQtResources}, 126 license='GPLv3', 127 packages=[ 128 'autokey', 129 'autokey.iomediator', 130 'autokey.gtkui', 131 'autokey.qtui', 132 'autokey.qtui.dialogs', 133 'autokey.qtui.settings' 134 ], 135 package_dir={'': 'lib'}, 136 137 package_data={'autokey.qtui': ['data/*', 'resources/icons/*', 'resources/ui/*.ui'], 138 'autokey.gtkui': ['data/*']}, 139 data_files=[('share/icons/hicolor/scalable/apps', 140 ['config/autokey.svg', 141 'config/autokey-status.svg', 142 'config/autokey-status-dark.svg', 143 'config/autokey-status-error.svg']), 144 ('share/icons/hicolor/96x96/apps', # TODO: Remove later. https://github.com/autokey/autokey/issues/160 145 ['config/autokey.png']), 146 ('share/icons/Humanity/scalable/apps', 147 ['config/Humanity/autokey-status.svg', 148 'config/Humanity/autokey-status-error.svg']), 149 ('share/icons/ubuntu-mono-dark/apps/48', 150 ['config/ubuntu-mono-dark/autokey-status.svg', 151 'config/ubuntu-mono-dark/autokey-status-error.svg']), 152 ('share/icons/ubuntu-mono-light/apps/48', 153 ['config/ubuntu-mono-light/autokey-status.svg', 154 'config/ubuntu-mono-light/autokey-status-error.svg']), 155 ('share/applications', 156 ['config/autokey-qt.desktop', 157 'config/autokey-gtk.desktop']), 158 ('man/man1/', 159 ['doc/man/autokey-qt.1', 160 'doc/man/autokey-gtk.1', 161 'doc/man/autokey-run.1']) 162 ], 163 entry_points={ 164 'console_scripts': [ 165 'autokey-gtk=autokey.gtkui.__main__:main', 166 'autokey-qt=autokey.qtui.__main__:Application' 167 ] 168 }, 169 scripts=['autokey-run', 'autokey-shell'], 170 install_requires=['pyinotify', 'python-xlib'], 171 classifiers=[ 172 'Development Status :: 4 - Beta', 173 'Intended Audience :: Developers', 174 'Intended Audience :: End Users/Desktop', 175 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 176 'Natural Language :: English', 177 'Operating System :: POSIX :: Linux', 178 'Programming Language :: Python :: 3.5', 179 ], 180) 181