Restructure the source tree, modular installs
Restructure the source tree to be more like the target installation directory (share/...). Rewrite setup.py to only install a subset of the available UIs and to be more flexible and cleaner in general. I hope this doesn't cause too much breakage, but should result in a cleaner build/install system and more happy developers and packagers in the long run.
|
@ -2,7 +2,7 @@
|
|||
host = https://www.transifex.net
|
||||
|
||||
[gpodder.tres]
|
||||
file_filter = data/po/<lang>.po
|
||||
source_file = data/messages.pot
|
||||
file_filter = po/<lang>.po
|
||||
source_file = po/messages.pot
|
||||
source_lang = en
|
||||
|
||||
|
|
26
README
|
@ -96,9 +96,29 @@
|
|||
|
||||
[ RUNNING AND INSTALLATION ]
|
||||
|
||||
To run gPodder from source, use "bin/gpodder".
|
||||
To run gPodder from source, use..
|
||||
|
||||
To install gPodder system-wide, use "make install".
|
||||
bin/gpodder for the Gtk+ UI
|
||||
bin/gpodder --qml for the QML UI
|
||||
bin/gpo for the command-line interface
|
||||
|
||||
To install gPodder system-wide, use "make install". By default, this
|
||||
will install *all* UIs and all translations. The following environment
|
||||
variables are processed by setup.py:
|
||||
|
||||
LINGUAS space-separated list of languages to install
|
||||
GPODDER_INSTALL_UIS space-separated list of UIs to install
|
||||
|
||||
See setup.py for a list of recognized UIs.
|
||||
|
||||
Example: Install the CLI and Gtk UI with German and Dutch translations:
|
||||
|
||||
export LINGUAS="de nl"
|
||||
export GPODDER_INSTALL_UIS="cli gtk"
|
||||
make install
|
||||
|
||||
The "make install" target also support DESTDIR and PREFIX for installing
|
||||
into an alternative root (default /) and prefix (default /usr).
|
||||
|
||||
|
||||
[ PYTHON 3 SUPPORT ]
|
||||
|
@ -140,5 +160,5 @@
|
|||
- IRC channel #gpodder on irc.freenode.net
|
||||
|
||||
............................................................................
|
||||
Last updated: 2012-01-10 by Thomas Perl <thp.io/about>
|
||||
Last updated: 2012-02-23 by Thomas Perl <thp.io/about>
|
||||
|
||||
|
|
7
bin/gpo
|
@ -109,18 +109,17 @@ gpodder_dir = os.path.join(os.path.dirname(gpodder_script), '..')
|
|||
prefix = os.path.abspath(os.path.normpath(gpodder_dir))
|
||||
|
||||
src_dir = os.path.join(prefix, 'src')
|
||||
data_dir = os.path.join(prefix, 'data')
|
||||
|
||||
if (os.path.exists(src_dir) and os.path.exists(data_dir) and
|
||||
not os.path.exists(os.path.join(prefix, 'share'))):
|
||||
if os.path.exists(os.path.join(src_dir, 'gpodder', '__init__.py')):
|
||||
# Run gPodder from local source folder (not installed)
|
||||
sys.path.insert(0, src_dir)
|
||||
|
||||
|
||||
import gpodder
|
||||
_ = gpodder.gettext
|
||||
N_ = gpodder.ngettext
|
||||
|
||||
gpodder.prefix = prefix
|
||||
|
||||
# This is the command-line UI variant
|
||||
gpodder.ui.cli = True
|
||||
|
||||
|
|
17
bin/gpodder
|
@ -61,24 +61,15 @@ if __name__ == '__main__':
|
|||
prefix = os.path.abspath(os.path.normpath(gpodder_dir))
|
||||
|
||||
src_dir = os.path.join(prefix, 'src')
|
||||
data_dir = os.path.join(prefix, 'data')
|
||||
locale_dir = os.path.join(prefix, 'share', 'locale')
|
||||
ui_folder = os.path.join(prefix, 'share', 'gpodder', 'ui')
|
||||
credits_file = os.path.join(prefix, 'share', 'gpodder', 'credits.txt')
|
||||
images_folder = os.path.join(prefix, 'share', 'gpodder')
|
||||
images_folder = os.path.join(prefix, 'share', 'gpodder', 'images')
|
||||
icon_file = os.path.join(prefix, 'share', 'icons', 'hicolor', 'scalable', 'apps', 'gpodder.svg')
|
||||
|
||||
if (os.path.exists(src_dir) and os.path.exists(data_dir) and
|
||||
not os.path.exists(os.path.join(prefix, 'share'))):
|
||||
if os.path.exists(os.path.join(src_dir, 'gpodder', '__init__.py')):
|
||||
# Run gPodder from local source folder (not installed)
|
||||
print >>sys.stderr, 'Using modules from', src_dir
|
||||
sys.path.insert(0, src_dir)
|
||||
print >>sys.stderr, 'Using resources from', data_dir
|
||||
locale_dir = os.path.join(data_dir, 'locale')
|
||||
ui_folder = os.path.join(data_dir, 'ui')
|
||||
credits_file = os.path.join(data_dir, 'credits.txt')
|
||||
images_folder = os.path.join(data_dir, 'images')
|
||||
icon_file = os.path.join(data_dir, 'gpodder.svg')
|
||||
|
||||
# on Mac OS X, read from the defaults database the locale of the user
|
||||
if platform.system() == 'Darwin' and 'LANG' not in os.environ:
|
||||
|
@ -95,6 +86,8 @@ if __name__ == '__main__':
|
|||
|
||||
import gpodder
|
||||
|
||||
gpodder.prefix = prefix
|
||||
|
||||
# Platform detection (i.e. Maemo 5, etc..)
|
||||
gpodder.detect_platform()
|
||||
|
||||
|
@ -135,7 +128,7 @@ if __name__ == '__main__':
|
|||
(options, args) = parser.parse_args(sys.argv)
|
||||
|
||||
if gpodder.ui.desktop:
|
||||
gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'desktop'))
|
||||
gpodder.ui_folders.insert(0, os.path.join(ui_folder, 'gtk'))
|
||||
|
||||
if options.verbose:
|
||||
FMT = '%(created)f [%(name)s] %(levelname)s: %(message)s'
|
||||
|
|
|
@ -37,15 +37,15 @@ gpodder_dir = os.path.join(os.path.dirname(gpodder_script), '..')
|
|||
prefix = os.path.abspath(os.path.normpath(gpodder_dir))
|
||||
|
||||
src_dir = os.path.join(prefix, 'src')
|
||||
data_dir = os.path.join(prefix, 'data')
|
||||
|
||||
if (os.path.exists(src_dir) and os.path.exists(data_dir) and
|
||||
not os.path.exists(os.path.join(prefix, 'share'))):
|
||||
if os.path.exists(os.path.join(src_dir, 'gpodder', '__init__.py')):
|
||||
# Run gPodder from local source folder (not installed)
|
||||
sys.path.insert(0, src_dir)
|
||||
|
||||
import gpodder
|
||||
|
||||
gpodder.prefix = prefix
|
||||
|
||||
# Platform detection (i.e. Maemo 5, etc..)
|
||||
gpodder.detect_platform()
|
||||
|
||||
|
|
Before Width: | Height: | Size: 825 B |
Before Width: | Height: | Size: 615 B |
Before Width: | Height: | Size: 775 B |
Before Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 478 B |
Before Width: | Height: | Size: 887 B |
Before Width: | Height: | Size: 635 B |
|
@ -1,9 +0,0 @@
|
|||
|
||||
[gpodder-new-episodes]
|
||||
Destination=Gpodder
|
||||
Icon=gpodder
|
||||
Title-Text-Empty=gPodder
|
||||
Secondary-Text=New episodes available
|
||||
Text-Domain=gpodder
|
||||
LED-Pattern=PatternCommonNotification
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
Put your translated *.po files here, then execute "make" to generate
|
||||
machine-readable *.mo files in the locale directory.
|
||||
|
||||
More about translations at http://gpodder.berlios.de/i18n.html
|
79
makefile
|
@ -19,13 +19,14 @@
|
|||
|
||||
##########################################################################
|
||||
|
||||
BINFILE=bin/gpodder
|
||||
MESSAGESPOT=data/messages.pot
|
||||
BINFILE = bin/gpodder
|
||||
MESSAGESPOT = po/messages.pot
|
||||
POFILES = $(wildcard po/*.po)
|
||||
MANPAGE = share/man/man1/gpodder.1
|
||||
|
||||
UIFILES=$(wildcard data/ui/*.ui \
|
||||
data/ui/desktop/*.ui)
|
||||
UIFILES=$(wildcard share/gpodder/ui/gtk/*.ui)
|
||||
UIFILES_H=$(subst .ui,.ui.h,$(UIFILES))
|
||||
QMLFILES=$(wildcard data/ui/qml/*.qml)
|
||||
QMLFILES=$(wildcard share/gpodder/ui/qml/*.qml)
|
||||
TRANSLATABLE_SOURCE=$(wildcard src/gpodder/*.py \
|
||||
src/gpodder/gtkui/*.py \
|
||||
src/gpodder/gtkui/interface/*.py \
|
||||
|
@ -34,49 +35,26 @@ TRANSLATABLE_SOURCE=$(wildcard src/gpodder/*.py \
|
|||
src/gpodder/webui/*.py \
|
||||
src/gpodder/plugins/*.py)
|
||||
|
||||
HELP2MAN=help2man
|
||||
MANPAGE=data/man/gpodder.1
|
||||
|
||||
GPODDER_SERVICE_FILE=data/org.gpodder.service
|
||||
GPODDER_SERVICE_FILE=share/dbus-1/services/org.gpodder.service
|
||||
GPODDER_SERVICE_FILE_IN=$(addsuffix .in,$(GPODDER_SERVICE_FILE))
|
||||
|
||||
GPODDER_DESKTOP_FILE=data/gpodder.desktop
|
||||
GPODDER_DESKTOP_FILE=share/applications/gpodder.desktop
|
||||
GPODDER_DESKTOP_FILE_IN=$(addsuffix .in,$(GPODDER_DESKTOP_FILE))
|
||||
DESKTOPFILE_H=$(addsuffix .h,$(GPODDER_DESKTOP_FILE_IN))
|
||||
GPODDER_DESKTOP_FILE_H=$(addsuffix .h,$(GPODDER_DESKTOP_FILE_IN))
|
||||
|
||||
DESTDIR ?= /
|
||||
PREFIX ?= /usr
|
||||
|
||||
PYTHON ?= python
|
||||
HELP2MAN ?= help2man
|
||||
|
||||
##########################################################################
|
||||
|
||||
all: help
|
||||
|
||||
help:
|
||||
@echo 'make test run gpodder in local directory'
|
||||
@echo 'make qmltest run gpodder (qml ui) in local directory'
|
||||
@echo 'make unittest run doctests + unittests'
|
||||
@echo 'make release create source tarball in "dist/"'
|
||||
@echo 'make releasetest run some tests before the release'
|
||||
@echo 'make install install gpodder into "$(PREFIX)"'
|
||||
@echo 'make manpage update manpage (on release)'
|
||||
@echo 'make messages update messages.pot + .po files + .mo files'
|
||||
@echo 'make clean remove generated+temp+*.py{c,o} files'
|
||||
@echo 'make distclean do a "make clean" + remove "dist/"'
|
||||
@echo 'make headlink print URL for the current Git head'
|
||||
@cat tools/make-help.txt
|
||||
|
||||
##########################################################################
|
||||
|
||||
test:
|
||||
@# set xterm title to know what this window does ;)
|
||||
@echo -ne '\033]0;gPodder console (make test)\007'
|
||||
$(BINFILE) --verbose
|
||||
|
||||
qmltest:
|
||||
@echo -ne '\033]0;gPodder/QML console\007'
|
||||
$(BINFILE) --qml --verbose
|
||||
|
||||
unittest:
|
||||
PYTHONPATH=src/ $(PYTHON) -m gpodder.unittests
|
||||
|
||||
|
@ -88,13 +66,13 @@ release: distclean
|
|||
|
||||
releasetest: unittest $(GPODDER_DESKTOP_FILE)
|
||||
desktop-file-validate $(GPODDER_DESKTOP_FILE)
|
||||
$(MAKE) -C data/po validate
|
||||
sh po/validate.sh
|
||||
|
||||
$(GPODDER_SERVICE_FILE): $(GPODDER_SERVICE_FILE_IN)
|
||||
sed -e 's#__PREFIX__#$(PREFIX)#' $< >$@
|
||||
|
||||
$(GPODDER_DESKTOP_FILE): $(GPODDER_DESKTOP_FILE_IN) data/po/*.po
|
||||
intltool-merge -d -u data/po $< $@
|
||||
$(GPODDER_DESKTOP_FILE): $(GPODDER_DESKTOP_FILE_IN) $(POFILES)
|
||||
intltool-merge -d -u po $< $@
|
||||
|
||||
$(GPODDER_DESKTOP_FILE_IN).h: $(GPODDER_DESKTOP_FILE_IN)
|
||||
intltool-extract --quiet --type=gettext/ini $<
|
||||
|
@ -107,17 +85,17 @@ install: messages $(GPODDER_SERVICE_FILE) $(GPODDER_DESKTOP_FILE)
|
|||
manpage: $(MANPAGE)
|
||||
|
||||
$(MANPAGE): src/gpodder/__init__.py $(BINFILE)
|
||||
$(HELP2MAN) --name="A Media aggregator and Podcast catcher" -N $(BINFILE) >$(MANPAGE)
|
||||
$(HELP2MAN) --name="$(shell $(PYTHON) setup.py --description)" -N $(BINFILE) >$(MANPAGE)
|
||||
|
||||
##########################################################################
|
||||
|
||||
messages: $(MESSAGESPOT)
|
||||
$(MAKE) -C data/po
|
||||
$(MAKE) -C po
|
||||
|
||||
data/ui/%.ui.h: $(UIFILES)
|
||||
%.ui.h: $(UIFILES)
|
||||
intltool-extract --quiet --type=gettext/glade $(subst .ui.h,.ui,$@)
|
||||
|
||||
$(MESSAGESPOT): $(TRANSLATABLE_SOURCE) $(UIFILES_H) $(QMLFILES) $(BINFILE) $(DESKTOPFILE_H)
|
||||
$(MESSAGESPOT): $(TRANSLATABLE_SOURCE) $(UIFILES_H) $(QMLFILES) $(BINFILE) $(GPODDER_DESKTOP_FILE_H)
|
||||
xgettext -LPython -k_:1 -kN_:1 -kN_:1,2 -kn_:1,2 -o $(MESSAGESPOT) $^
|
||||
|
||||
##########################################################################
|
||||
|
@ -134,25 +112,22 @@ headlink:
|
|||
|
||||
clean:
|
||||
$(PYTHON) setup.py clean
|
||||
find src/ -name '*.pyc' -exec rm '{}' \;
|
||||
find src/ -name '*.pyo' -exec rm '{}' \;
|
||||
find src/ -type d -name '__pycache__' -exec rm -r '{}' \;
|
||||
find data/ui/ -name '*.ui.h' -exec rm '{}' \;
|
||||
rm -f MANIFEST PKG-INFO data/messages.pot~ $(DESKTOPFILE_H)
|
||||
rm -f data/gpodder-??x??.png .coverage
|
||||
rm -f $(GPODDER_SERVICE_FILE) $(GPODDER_DESKTOP_FILE)
|
||||
find src/ '(' -name '*.pyc' -o -name '*.pyo' ')' -exec rm '{}' +
|
||||
find src/ -type d -name '__pycache__' -exec rm -r '{}' +
|
||||
find share/gpodder/ui/ -name '*.ui.h' -exec rm '{}' +
|
||||
rm -f MANIFEST PKG-INFO .coverage messages.mo
|
||||
rm -f $(GPODDER_SERVICE_FILE)
|
||||
rm -f $(GPODDER_DESKTOP_FILE)
|
||||
rm -f $(GPODDER_DESKTOP_FILE_H)
|
||||
rm -rf build
|
||||
$(MAKE) -C data/po clean
|
||||
|
||||
debclean:
|
||||
fakeroot debian/rules clean
|
||||
$(MAKE) -C po clean
|
||||
|
||||
distclean: clean
|
||||
rm -rf dist
|
||||
|
||||
##########################################################################
|
||||
|
||||
.PHONY: all test unittest release releasetest install manpage clean distclean messages help headlink
|
||||
.PHONY: help unittest release releasetest install manpage clean distclean messages headlink
|
||||
|
||||
##########################################################################
|
||||
|
||||
|
|
|
@ -17,17 +17,19 @@
|
|||
#
|
||||
#
|
||||
|
||||
PO_FILES=$(wildcard *.po)
|
||||
POT_FILE=../messages.pot
|
||||
PO_FILES = $(wildcard *.po)
|
||||
POT_FILE = messages.pot
|
||||
|
||||
LOCALE_DIR = ../share/locale/
|
||||
|
||||
# Check for $LINGUAS presence.
|
||||
ifeq ($(origin LINGUAS), undefined)
|
||||
PO_INSTALL=$(PO_FILES)
|
||||
PO_INSTALL = $(PO_FILES)
|
||||
else
|
||||
PO_INSTALL=$(addsuffix .po,$(filter $(subst .po,,$(PO_FILES)),$(LINGUAS)))
|
||||
PO_INSTALL = $(addsuffix .po,$(filter $(subst .po,,$(PO_FILES)),$(LINGUAS)))
|
||||
endif
|
||||
|
||||
MO_FILES=$(addsuffix /LC_MESSAGES/gpodder.mo,$(addprefix ../locale/,$(subst .po,,$(PO_INSTALL))))
|
||||
MO_FILES = $(addsuffix /LC_MESSAGES/gpodder.mo,$(addprefix $(LOCALE_DIR),$(subst .po,,$(PO_INSTALL))))
|
||||
|
||||
all: $(PO_INSTALL) $(MO_FILES)
|
||||
|
||||
|
@ -36,18 +38,12 @@ all: $(PO_INSTALL) $(MO_FILES)
|
|||
@msgmerge --silent $@ $< --output-file=$@
|
||||
|
||||
%.mo: $(PO_INSTALL)
|
||||
@echo "Compiling $(subst /LC_MESSAGES/gpodder.mo,.po,$(subst ../locale/,,$@)) -> $(notdir $@)"
|
||||
@echo "Compiling $(subst /LC_MESSAGES/gpodder.mo,.po,$(subst $(LOCALE_DIR),,$@)) -> $(notdir $@)"
|
||||
@mkdir -p $(@D)
|
||||
@msgfmt $(subst /LC_MESSAGES/gpodder.mo,.po,$(subst ../locale/,,$@)) -o $@
|
||||
@msgfmt $(subst /LC_MESSAGES/gpodder.mo,.po,$(subst $(LOCALE_DIR),,$@)) -o $@
|
||||
|
||||
clean:
|
||||
rm -rf ../locale *~ *.mo
|
||||
rm -rf $(LOCALE_DIR) *.mo
|
||||
|
||||
statistics:
|
||||
@(for file in *.po; do echo -n "$$file (`cat $$file | grep Revision-Date | cut -d' ' -f2`): "; msgfmt --statistics $$file 2>&1; done) | sort -t: -k2 -rn; done
|
||||
|
||||
validate:
|
||||
./validate.sh
|
||||
|
||||
.PHONY: all clean statistics validate
|
||||
.PHONY: all clean
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
|
||||
MERGE_DIR=_tmp_merge_dir
|
||||
MESSAGES_POT=../messages.pot
|
||||
MESSAGES_POT=messages.pot
|
||||
|
||||
if [ "`which tx`" == "" ]; then
|
||||
echo "The Transifex client 'tx' was not found."
|
||||
|
@ -25,8 +25,8 @@ fi
|
|||
|
||||
cd `dirname $0`
|
||||
|
||||
if git status --porcelain | grep -q '^ M data/po'; then
|
||||
echo "Uncommitted changes in data/po/ - cannot continue."
|
||||
if git status --porcelain | grep -q '^ M po'; then
|
||||
echo "Uncommitted changes in po/ - cannot continue."
|
||||
echo "Please revert or commit current changes before continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
@ -41,7 +41,7 @@ echo "Downloading UPDATED translations from Transifex..."
|
|||
tx pull --force
|
||||
|
||||
FILES=`git status --porcelain |
|
||||
grep '^ M data/po/.*.po$' |
|
||||
grep '^ M po/.*.po$' |
|
||||
awk '{ print $2 }' |
|
||||
cut -d/ -f3`
|
||||
|
|
@ -8,13 +8,15 @@
|
|||
import sys
|
||||
import re
|
||||
import math
|
||||
import glob
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
width = 40
|
||||
|
||||
class Language(object):
|
||||
def __init__(self, code, updated, translated, fuzzy, untranslated):
|
||||
self.code = code
|
||||
self.updated = updated
|
||||
def __init__(self, language, translated, fuzzy, untranslated):
|
||||
self.language = language
|
||||
self.translated = int(translated)
|
||||
self.fuzzy = int(fuzzy)
|
||||
self.untranslated = int(untranslated)
|
||||
|
@ -27,28 +29,32 @@ class Language(object):
|
|||
|
||||
def get_untranslated_ratio(self):
|
||||
return float(self.untranslated)/float(self.translated+self.fuzzy+self.untranslated)
|
||||
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.get_translated_ratio(), other.get_translated_ratio())
|
||||
|
||||
languages = []
|
||||
|
||||
for line in sys.stdin:
|
||||
match = re.match('^(..)\.po \(([^)]*)\): ((\d+) translated message[s]?)?(, (\d+) fuzzy translation[s]?)?(, (\d+) untranslated message[s]?)?\.', line).groups()
|
||||
languages.append(Language(match[0], match[1], match[3] or '0', match[5] or '0', match[7] or '0'))
|
||||
COUNTS_RE = '((\d+) translated message[s]?)?(, (\d+) fuzzy translation[s]?)?(, (\d+) untranslated message[s]?)?\.'
|
||||
|
||||
for filename in glob.glob('*.po'):
|
||||
language, _ = os.path.splitext(filename)
|
||||
msgfmt = subprocess.Popen(['msgfmt', '--statistics', filename],
|
||||
stderr=subprocess.PIPE)
|
||||
_, stderr = msgfmt.communicate()
|
||||
|
||||
match = re.match(COUNTS_RE, stderr).groups()
|
||||
languages.append(Language(language, match[1] or '0', match[3] or '0', match[5] or '0'))
|
||||
|
||||
print ''
|
||||
print ' --== gPodder translation summary == --'
|
||||
print ''
|
||||
|
||||
for language in sorted(languages):
|
||||
tc = '#'*(int(math.floor(width*language.get_translated_ratio())))
|
||||
fc = '~'*(int(math.floor(width*language.get_fuzzy_ratio())))
|
||||
uc = ' '*(width-len(tc)-len(fc))
|
||||
|
||||
print ' %s (%s) [%s%s%s] -- %3.0f %% translated' % (language.code, language.updated, tc, fc, uc, language.get_translated_ratio()*100)
|
||||
|
||||
print ''
|
||||
print ' Total translations: %d' % len(languages)
|
||||
print ''
|
||||
print ' %5s [%s%s%s] -- %3.0f %% translated' % (language.language, tc, fc, uc, language.get_translated_ratio()*100)
|
||||
|
||||
print """
|
||||
Total translations: %s
|
||||
""" % (len(languages))
|
||||
|
|
@ -6,7 +6,7 @@ cat <<EOF
|
|||
|
||||
EOF
|
||||
|
||||
for translation in *.po; do
|
||||
for translation in `dirname $0`/*.po; do
|
||||
echo " Checking: $translation"
|
||||
msgfmt --check "$translation" || exit 1
|
||||
done
|
268
setup.py
|
@ -22,119 +22,185 @@ import glob
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
# import the gpodder module locally for module metadata
|
||||
sys.path.insert(0, 'src')
|
||||
import gpodder
|
||||
installing = ('install' in sys.argv)
|
||||
|
||||
# if we are running "setup.py sdist", include all targets (see below)
|
||||
building_source = ('sdist' in sys.argv)
|
||||
cleaning_target = ('clean' in sys.argv)
|
||||
# Read the metadata from gPodder's __init__ module (doesn't need importing)
|
||||
main_module = open('src/gpodder/__init__.py').read()
|
||||
metadata = dict(re.findall("__([a-z_]+)__\s*=\s*'([^']+)'", main_module))
|
||||
|
||||
# Ignore missing files if we are in clean or sdist mode
|
||||
ignore_missing = (building_source or cleaning_target)
|
||||
author, email = re.match(r'^(.*) <(.*)>$', metadata['author']).groups()
|
||||
|
||||
# search for translations, taking $LINGUAS into account
|
||||
translation_files = []
|
||||
linguas = os.environ.get('LINGUAS', None)
|
||||
if linguas is not None:
|
||||
linguas = linguas.split()
|
||||
|
||||
for mofile in glob.glob('data/locale/*/LC_MESSAGES/gpodder.mo'):
|
||||
_, _, lang, _ = mofile.split('/', 3)
|
||||
class MissingFile(BaseException): pass
|
||||
|
||||
# Only install if either $LINGUAS it not set or the
|
||||
# language is specified in the $LINGUAS variable
|
||||
if linguas is None or lang in linguas:
|
||||
modir = os.path.dirname(mofile).replace('data', 'share')
|
||||
translation_files.append((modir, [mofile]))
|
||||
def info(message, item=None):
|
||||
print '=>', message, item if item is not None else ''
|
||||
|
||||
if not len(translation_files) and \
|
||||
not ignore_missing and \
|
||||
linguas not in (None, []):
|
||||
|
||||
def find_data_files(uis, scripts):
|
||||
# Support for installing only a subset of translations
|
||||
linguas = os.environ.get('LINGUAS', None)
|
||||
if linguas is not None:
|
||||
linguas = linguas.split()
|
||||
info('Selected languages (from $LINGUAS):', linguas)
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk('share'):
|
||||
if not filenames:
|
||||
continue
|
||||
|
||||
# Skip data folders if we don't want the corresponding UI
|
||||
share_gpodder_ui = os.path.join('share', 'gpodder', 'ui')
|
||||
if uis is not None and dirpath.startswith(share_gpodder_ui):
|
||||
dirparts = dirpath.split(os.sep)
|
||||
if not any(part in uis for part in dirparts):
|
||||
info('Skipping folder:', dirpath)
|
||||
continue
|
||||
|
||||
# Skip translations if $LINGUAS is set
|
||||
share_locale = os.path.join('share', 'locale')
|
||||
if linguas is not None and dirpath.startswith(share_locale):
|
||||
_, _, language, _ = dirpath.split('/', 3)
|
||||
if language not in linguas:
|
||||
info('Skipping translation:', language)
|
||||
continue
|
||||
|
||||
# Skip share/icons if we don't have any UIs that requires them
|
||||
skip_folder = False
|
||||
uis_requiring_freedesktop = ('gtk', 'qml')
|
||||
freedesktop_folders = ('icons', 'dbus-1', 'applications')
|
||||
for folder in freedesktop_folders:
|
||||
share_folder = os.path.join('share', folder)
|
||||
if dirpath.startswith(share_folder) and uis is not None:
|
||||
if not any(ui in uis_requiring_freedesktop for ui in uis):
|
||||
info('Skipping freedesktop.org folder:', dirpath)
|
||||
skip_folder = True
|
||||
break
|
||||
|
||||
if skip_folder:
|
||||
continue
|
||||
|
||||
# Skip manpages if their scripts are not going to be installed
|
||||
share_man = os.path.join('share', 'man')
|
||||
if dirpath.startswith(share_man):
|
||||
def have_script(filename):
|
||||
if not filename.endswith('.1'):
|
||||
return True
|
||||
|
||||
basename, _ = os.path.splitext(filename)
|
||||
result = any(os.path.basename(s) == basename for s in scripts)
|
||||
if not result:
|
||||
info('Skipping file without script:', filename)
|
||||
return result
|
||||
filenames = filter(have_script, filenames)
|
||||
|
||||
def convert_filename(filename):
|
||||
filename = os.path.join(dirpath, filename)
|
||||
|
||||
# Skip header files generated by "make messages"
|
||||
if filename.endswith('.h'):
|
||||
return None
|
||||
|
||||
# Skip .in files, but check if their target exist
|
||||
if filename.endswith('.in'):
|
||||
filename = filename[:-3]
|
||||
if not os.path.exists(filename) and installing:
|
||||
raise MissingFile(filename)
|
||||
return None
|
||||
|
||||
return filename
|
||||
|
||||
filenames = filter(None, map(convert_filename, filenames))
|
||||
if filenames:
|
||||
yield (dirpath, filenames)
|
||||
|
||||
|
||||
def find_packages(uis):
|
||||
src_gpodder = os.path.join('src', 'gpodder')
|
||||
for dirpath, dirnames, filenames in os.walk(src_gpodder):
|
||||
if '__init__.py' not in filenames:
|
||||
continue
|
||||
|
||||
skip = False
|
||||
dirparts = dirpath.split(os.sep)
|
||||
dirparts.pop(0)
|
||||
package = '.'.join(dirparts)
|
||||
|
||||
# Find all parts of the package name ending in "ui"
|
||||
ui_parts = filter(lambda p: p.endswith('ui'), dirparts)
|
||||
if uis is not None and ui_parts:
|
||||
# Strip the trailing "ui", e.g. "gtkui" -> "gtk"
|
||||
folder_uis = map(lambda p: p[:-2], ui_parts)
|
||||
for folder_ui in folder_uis:
|
||||
if folder_ui not in uis:
|
||||
info('Skipping package:', package)
|
||||
skip = True
|
||||
break
|
||||
|
||||
if not skip:
|
||||
yield package
|
||||
|
||||
|
||||
def find_scripts(uis):
|
||||
# Functions for scripts to check if they should be installed
|
||||
file_checks = {
|
||||
'gpo': lambda uis: 'cli' in uis,
|
||||
'gpodder': lambda uis: any(x in uis for x in ('qml', 'gtk')),
|
||||
}
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk('bin'):
|
||||
for filename in filenames:
|
||||
# If we have a set of uis, check if we can skip this file
|
||||
if uis is not None and filename in file_checks:
|
||||
if not file_checks[filename](uis):
|
||||
info('Skipping script:', filename)
|
||||
continue
|
||||
|
||||
yield os.path.join(dirpath, filename)
|
||||
|
||||
|
||||
# Recognized UIs: gtk, qml, web (default: install all UIs)
|
||||
uis = os.environ.get('GPODDER_INSTALL_UIS', None)
|
||||
if uis is not None:
|
||||
uis = uis.split()
|
||||
|
||||
# The CLI depends on the Web UI to be available
|
||||
if 'cli' in uis and 'web' not in uis:
|
||||
info('Adding Web UI as dependency of CLI')
|
||||
uis.append('web')
|
||||
|
||||
info('Selected UIs (from $GPODDER_INSTALL_UIS):', uis)
|
||||
|
||||
|
||||
try:
|
||||
packages = list(sorted(find_packages(uis)))
|
||||
scripts = list(sorted(find_scripts(uis)))
|
||||
data_files = list(sorted(find_data_files(uis, scripts)))
|
||||
except MissingFile, mf:
|
||||
print >>sys.stderr, """
|
||||
Warning: No translation files. (Did you forget to run "make messages"?)
|
||||
"""
|
||||
Missing file: %s
|
||||
|
||||
DBUS_SERVICE_FILE = 'data/org.gpodder.service'
|
||||
DESKTOP_FILE = 'data/gpodder.desktop'
|
||||
If you want to install, use "make install" instead of using
|
||||
setup.py directly. See the README file for more information.
|
||||
""" % mf.message
|
||||
sys.exit(1)
|
||||
|
||||
for prerequisite in (DBUS_SERVICE_FILE, DESKTOP_FILE):
|
||||
if not os.path.exists(prerequisite) and not ignore_missing:
|
||||
print >>sys.stderr, 'Missing file:', prerequisite
|
||||
print >>sys.stderr, 'Use "make install" if you want to install.'
|
||||
sys.exit(1)
|
||||
|
||||
# files to install
|
||||
inst_manpages = glob.glob( 'data/man/*.1')
|
||||
inst_share_ui = glob.glob('data/ui/*.ui')
|
||||
inst_share_ui_desktop = glob.glob('data/ui/desktop/*.ui')
|
||||
inst_share_ui_qml = glob.glob('data/ui/qml/*.qml') + glob.glob('data/ui/qml/*.js')
|
||||
inst_share_ui_qml_artwork = glob.glob('data/ui/qml/artwork/*')
|
||||
inst_share_ui_qml_test = glob.glob('data/ui/qml/test/*')
|
||||
inst_share_gpodder = [ 'data/credits.txt' ] + glob.glob('data/images/*.png')
|
||||
inst_share_gpodder_examples = glob.glob('examples/*')
|
||||
inst_desktop = [ DESKTOP_FILE ]
|
||||
inst_share_dbus_services = [ DBUS_SERVICE_FILE ]
|
||||
|
||||
inst_icons = [ 'data/gpodder.png' ]
|
||||
inst_icons_64 = [ 'data/icons/64/gpodder.png' ]
|
||||
inst_icons_40 = [ 'data/icons/40/gpodder.png' ]
|
||||
inst_icons_32 = [ 'data/icons/32/gpodder.png' ]
|
||||
inst_icons_26 = [ 'data/icons/26/gpodder.png' ]
|
||||
inst_icons_24 = [ 'data/icons/24/gpodder.png' ]
|
||||
inst_icons_22 = [ 'data/icons/22/gpodder.png' ]
|
||||
inst_icons_16 = [ 'data/icons/16/gpodder.png' ]
|
||||
inst_icons_svg = [ 'data/gpodder.svg' ]
|
||||
|
||||
data_files = [
|
||||
('share/man/man1', inst_manpages),
|
||||
('share/gpodder/ui', inst_share_ui),
|
||||
('share/gpodder/ui/qml', inst_share_ui_qml),
|
||||
('share/gpodder/ui/qml/artwork', inst_share_ui_qml_artwork),
|
||||
('share/gpodder/ui/qml/test', inst_share_ui_qml_test),
|
||||
('share/pixmaps', inst_icons),
|
||||
('share/gpodder', inst_share_gpodder),
|
||||
('share/gpodder/examples', inst_share_gpodder_examples),
|
||||
('share/dbus-1/services',inst_share_dbus_services),
|
||||
]
|
||||
|
||||
packages = [
|
||||
'gpodder',
|
||||
'gpodder.plugins',
|
||||
'gpodder.gtkui',
|
||||
'gpodder.gtkui.interface',
|
||||
'gpodder.webui',
|
||||
'gpodder.qmlui',
|
||||
]
|
||||
|
||||
data_files += [
|
||||
('share/gpodder/ui/desktop', inst_share_ui_desktop),
|
||||
('share/applications', inst_desktop),
|
||||
('share/icons/hicolor/scalable/apps', inst_icons_svg),
|
||||
('share/icons/hicolor/48x48/apps', inst_icons),
|
||||
('share/icons/hicolor/24x24/apps', inst_icons_24),
|
||||
('share/icons/hicolor/22x22/apps', inst_icons_22),
|
||||
('share/icons/hicolor/16x16/apps', inst_icons_16),
|
||||
]
|
||||
packages += [
|
||||
'gpodder.gtkui.desktop',
|
||||
]
|
||||
|
||||
author, email = re.match(r'^(.*) <(.*)>$', gpodder.__author__).groups()
|
||||
|
||||
setup(
|
||||
name = 'gpodder',
|
||||
version = gpodder.__version__,
|
||||
package_dir = { '':'src' },
|
||||
packages = packages,
|
||||
description = 'Media aggregator and podcast client',
|
||||
author = author,
|
||||
author_email = email,
|
||||
url = gpodder.__url__,
|
||||
scripts = glob.glob('bin/*'),
|
||||
data_files = data_files + translation_files
|
||||
name = 'gpodder',
|
||||
version = metadata['version'],
|
||||
description = metadata['tagline'],
|
||||
license = metadata['license'],
|
||||
url = metadata['url'],
|
||||
|
||||
author = author,
|
||||
author_email = email,
|
||||
|
||||
package_dir = {'': 'src'},
|
||||
packages = packages,
|
||||
scripts = scripts,
|
||||
data_files = data_files,
|
||||
)
|
||||
|
||||
|
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 566 B |
Before Width: | Height: | Size: 569 B After Width: | Height: | Size: 569 B |
Before Width: | Height: | Size: 531 B After Width: | Height: | Size: 531 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
Before Width: | Height: | Size: 848 B After Width: | Height: | Size: 848 B |