Add all python versions to test matrix.
[gpodder.git] / setup.py
blob050be572e5572685610f7f9d9b0ba15df53e30cf
1 #!/usr/bin/env python3
4 # gPodder - A media aggregator and podcast client
5 # Copyright (c) 2005-2018 The gPodder Team
7 # gPodder is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # gPodder is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 import os
22 import re
23 import sys
24 from distutils.core import setup
26 installing = ('install' in sys.argv and '--help' not in sys.argv)
28 # distutils depends on setup.py beeing executed from the same dir.
29 # Most of our custom commands work either way, but this makes
30 # it work in all cases.
31 os.chdir(os.path.dirname(os.path.realpath(__file__)))
34 # Read the metadata from gPodder's __init__ module (doesn't need importing)
35 main_module = open('src/gpodder/__init__.py', 'r', encoding='utf-8').read()
36 metadata = dict(re.findall("__([a-z_]+)__\\s*=\\s*'([^']+)'", main_module))
38 author, email = re.match(r'^(.*) <(.*)>$', metadata['author']).groups()
41 class MissingFile(BaseException):
42 pass
45 def info(message, item=None):
46 print('=>', message, item if item is not None else '')
49 def find_data_files(uis, scripts):
50 # Support for installing only a subset of translations
51 linguas = os.environ.get('LINGUAS', None)
52 if linguas is not None:
53 linguas = linguas.split()
54 info('Selected languages (from $LINGUAS):', linguas)
56 for dirpath, dirnames, filenames in os.walk('share'):
57 if not filenames:
58 continue
60 # Skip data folders if we don't want the corresponding UI
61 share_gpodder_ui = os.path.join('share', 'gpodder', 'ui')
62 if uis is not None and dirpath.startswith(share_gpodder_ui):
63 dirparts = dirpath.split(os.sep)
64 if not any(part in uis for part in dirparts):
65 info('Skipping folder:', dirpath)
66 continue
68 # Skip translations if $LINGUAS is set
69 share_locale = os.path.join('share', 'locale')
70 if linguas is not None and dirpath.startswith(share_locale):
71 _, _, language, _ = dirpath.split(os.sep, 3)
72 if language not in linguas:
73 info('Skipping translation:', language)
74 continue
76 # Skip desktop stuff if we don't have any UIs requiring it
77 skip_folder = False
78 uis_requiring_freedesktop = ('gtk',)
79 freedesktop_folders = ('applications', 'dbus-1', 'icons', 'metainfo')
80 for folder in freedesktop_folders:
81 share_folder = os.path.join('share', folder)
82 if dirpath.startswith(share_folder) and uis is not None:
83 if not any(ui in uis_requiring_freedesktop for ui in uis):
84 info('Skipping freedesktop.org folder:', dirpath)
85 skip_folder = True
86 break
88 if skip_folder:
89 continue
91 # Skip manpages if their scripts are not going to be installed
92 share_man = os.path.join('share', 'man')
93 if dirpath.startswith(share_man):
94 def have_script(filename):
95 if not filename.endswith('.1'):
96 return True
98 basename, _ = os.path.splitext(filename)
99 result = any(os.path.basename(s) == basename for s in scripts)
100 if not result:
101 info('Skipping manpage without script:', filename)
102 return result
103 filenames = list(filter(have_script, filenames))
105 def convert_filename(filename):
106 filename = os.path.join(dirpath, filename)
108 # Skip header files generated by "make messages"
109 if filename.endswith('.h'):
110 return None
112 # Skip .in files, but check if their target exist
113 if filename.endswith('.in'):
114 filename = filename[:-3]
115 if installing and not os.path.exists(filename):
116 raise MissingFile(filename)
117 return None
119 return filename
121 filenames = [_f for _f in map(convert_filename, filenames) if _f]
122 if filenames:
123 # Some distros/ports install manpages into $PREFIX/man instead
124 # of $PREFIX/share/man (e.g. FreeBSD). To allow this, we strip
125 # the "share/" part if the variable GPODDER_MANPATH_NO_SHARE is
126 # set to any value in the environment.
127 if dirpath.startswith(share_man):
128 if 'GPODDER_MANPATH_NO_SHARE' in os.environ:
129 dirpath = dirpath.replace(share_man, 'man')
131 yield (dirpath, filenames)
134 def find_packages(uis):
135 src_gpodder = os.path.join('src', 'gpodder')
136 for dirpath, dirnames, filenames in os.walk(src_gpodder):
137 if '__init__.py' not in filenames:
138 continue
140 skip = False
141 dirparts = dirpath.split(os.sep)
142 dirparts.pop(0)
143 package = '.'.join(dirparts)
145 # Extract all parts of the package name ending in "ui"
146 ui_parts = [p for p in dirparts if p.endswith('ui')]
147 if uis is not None and ui_parts:
148 # Strip the trailing "ui", e.g. "gtkui" -> "gtk"
149 folder_uis = [p[:-2] for p in ui_parts]
150 for folder_ui in folder_uis:
151 if folder_ui not in uis:
152 info('Skipping package:', package)
153 skip = True
154 break
156 if not skip:
157 yield package
160 def find_scripts(uis):
161 # Functions for scripts to check if they should be installed
162 file_checks = {
163 'gpo': lambda uis: 'cli' in uis,
164 'gpodder': lambda uis: any(ui in uis for ui in ('gtk',)),
167 for dirpath, dirnames, filenames in os.walk('bin'):
168 for filename in filenames:
169 # If we have a set of uis, check if we can skip this file
170 if uis is not None and filename in file_checks:
171 if not file_checks[filename](uis):
172 info('Skipping script:', filename)
173 continue
175 yield os.path.join(dirpath, filename)
178 # Recognized UIs: cli, gtk (default: install all UIs)
179 uis = os.environ.get('GPODDER_INSTALL_UIS', None)
180 if uis is not None:
181 uis = uis.split()
183 info('Selected UIs (from $GPODDER_INSTALL_UIS):', uis)
186 try:
187 packages = list(sorted(find_packages(uis)))
188 scripts = list(sorted(find_scripts(uis)))
189 data_files = list(sorted(find_data_files(uis, scripts)))
190 except MissingFile as mf:
191 print("""
192 Missing file: %s
194 If you want to install, use "make install" instead of using
195 setup.py directly. See the README file for more information.
196 """ % mf, file=sys.stderr)
197 sys.exit(1)
200 setup(
201 name='gpodder',
202 version=metadata['version'],
203 description=metadata['tagline'],
204 license=metadata['license'],
205 url=metadata['url'],
207 author=author,
208 author_email=email,
210 package_dir={'': 'src'},
211 packages=packages,
212 scripts=scripts,
213 data_files=data_files,