Switch to setuptools and cleanup metadata.

py2exe support is gone for now, will be restored later.
This commit is contained in:
Tobias Gruetzmacher 2015-04-22 22:22:03 +02:00
parent bf9bf5e9b0
commit bf9f45b380
5 changed files with 45 additions and 672 deletions

8
.gitignore vendored
View file

@ -1,16 +1,12 @@
*.orig *.orig
*.pyc *.pyc
*.pyo *.pyo
/*.egg
/Comics /Comics
/build /build
/dist /dist
/.achievements
/MANIFEST
/todo
/Changelog.dosage* /Changelog.dosage*
/_dosage_configdata.py
/comics.test
/testresults.txt /testresults.txt
/dosage.prof /dosage.prof
/test.sh /dosage.egg-info
/scripts/*.json /scripts/*.json

View file

@ -1,6 +1,3 @@
include MANIFEST.in exclude .git*
include COPYING Makefile requirements.txt exclude .travis.yml
include doc/Makefile doc/*.txt doc/*.1 doc/*.html doc/*.md doc/dosage-completion recursive-exclude scripts dosage.*
include doc/css/*.css doc/js/*.js
include scripts/*.py scripts/*.sh scripts/*.bat scripts/*.iss
recursive-include tests *.py

View file

@ -1,25 +1,21 @@
# Copyright (C) 2012-2014 Bastian Kleineidam # Copyright (C) 2012-2014 Bastian Kleineidam
# Copyright (C) 2015 Tobias Gruetzmacher
""" """
Define basic configuration data like version or application name. Define basic configuration data like version or application name.
""" """
import _dosage_configdata as configdata
Version = configdata.version AppName = u'dosage'
ReleaseDate = configdata.release_date Version = u'2.16' # Should be PEP 440 compatible
AppName = configdata.name App = AppName + u' ' + Version
App = AppName+u" "+Version Maintainer = u'Tobias Gruetzmacher'
Author = configdata.author MaintainerEmail = u'tobias-dosage@23.gs'
HtmlAuthor = Author.replace(u' ', u' ') Url = u'http://dosage.rocks/'
Maintainer = configdata.maintainer SupportUrl = u'https://github.com/webcomics/dosage/issues'
HtmlMaintainer = Maintainer.replace(u' ', u' ')
Copyright = u"Copyright (C) 2004-2008 " + \
(u",".join(Author.split(",")[:2]))+u" (C) 2012-2014 "+Maintainer
HtmlCopyright = u"Copyright © 2004-2008 " + \
(u",".join(HtmlAuthor.split(",")[:2]))+u" © 2012-2014 "+HtmlMaintainer
Url = configdata.url
SupportUrl = Url + u"issues"
Email = configdata.maintainer_email
UserAgent = u"Mozilla/5.0 (compatible; %s/%s; +%s)" % (AppName, Version, Url) UserAgent = u"Mozilla/5.0 (compatible; %s/%s; +%s)" % (AppName, Version, Url)
Copyright = u"""Copyright (C) 2004-2005 Tristan Seligmann and Jonathan Jacobs
Copyright (C) 2012-2014 Bastian Kleineidam
Copyright (C) 2015 Tobias Gruetzmacher
"""
Freeware = AppName + u""" comes with ABSOLUTELY NO WARRANTY! Freeware = AppName + u""" comes with ABSOLUTELY NO WARRANTY!
This is free software, and you are welcome to redistribute it This is free software, and you are welcome to redistribute it
under certain conditions. Look at the file `COPYING' within this under certain conditions. Look at the file `COPYING' within this

View file

@ -1,219 +0,0 @@
// ----------------------------------------------------------------------------
//
// Inno Setup Ver: 5.4.2
// Script Version: 1.4.2
// Author: Jared Breland <jbreland@legroom.net>
// Homepage: http://www.legroom.net/software
// License: GNU Lesser General Public License (LGPL), version 3
// http://www.gnu.org/licenses/lgpl.html
//
// Script Function:
// Allow modification of environmental path directly from Inno Setup installers
//
// Instructions:
// Copy modpath.iss to the same directory as your setup script
//
// Add this statement to your [Setup] section
// ChangesEnvironment=true
//
// Add this statement to your [Tasks] section
// You can change the Description or Flags
// You can change the Name, but it must match the ModPathName setting below
// Name: modifypath; Description: &Add application directory to your environmental path; Flags: unchecked
//
// Add the following to the end of your [Code] section
// ModPathName defines the name of the task defined above
// ModPathType defines whether the 'user' or 'system' path will be modified;
// this will default to user if anything other than system is set
// setArrayLength must specify the total number of dirs to be added
// Result[0] contains first directory, Result[1] contains second, etc.
// const
// ModPathName = 'modifypath';
// ModPathType = 'user';
//
// function ModPathDir(): TArrayOfString;
// begin
// setArrayLength(Result, 1);
// Result[0] := ExpandConstant('{app}');
// end;
// #include "modpath.iss"
// ----------------------------------------------------------------------------
procedure ModPath();
var
oldpath: String;
newpath: String;
updatepath: Boolean;
pathArr: TArrayOfString;
aExecFile: String;
aExecArr: TArrayOfString;
i, d: Integer;
pathdir: TArrayOfString;
regroot: Integer;
regpath: String;
begin
// Get constants from main script and adjust behavior accordingly
// ModPathType MUST be 'system' or 'user'; force 'user' if invalid
if ModPathType = 'system' then begin
regroot := HKEY_LOCAL_MACHINE;
regpath := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
end else begin
regroot := HKEY_CURRENT_USER;
regpath := 'Environment';
end;
// Get array of new directories and act on each individually
pathdir := ModPathDir();
for d := 0 to GetArrayLength(pathdir)-1 do begin
updatepath := true;
// Modify WinNT path
if UsingWinNT() = true then begin
// Get current path, split into an array
RegQueryStringValue(regroot, regpath, 'Path', oldpath);
oldpath := oldpath + ';';
i := 0;
while (Pos(';', oldpath) > 0) do begin
SetArrayLength(pathArr, i+1);
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
i := i + 1;
// Check if current directory matches app dir
if pathdir[d] = pathArr[i-1] then begin
// if uninstalling, remove dir from path
if IsUninstaller() = true then begin
continue;
// if installing, flag that dir already exists in path
end else begin
updatepath := false;
end;
end;
// Add current directory to new path
if i = 1 then begin
newpath := pathArr[i-1];
end else begin
newpath := newpath + ';' + pathArr[i-1];
end;
end;
// Append app dir to path if not already included
if (IsUninstaller() = false) AND (updatepath = true) then
newpath := newpath + ';' + pathdir[d];
// Write new path
RegWriteStringValue(regroot, regpath, 'Path', newpath);
// Modify Win9x path
end else begin
// Convert to shortened dirname
pathdir[d] := GetShortName(pathdir[d]);
// If autoexec.bat exists, check if app dir already exists in path
aExecFile := 'C:\AUTOEXEC.BAT';
if FileExists(aExecFile) then begin
LoadStringsFromFile(aExecFile, aExecArr);
for i := 0 to GetArrayLength(aExecArr)-1 do begin
if IsUninstaller() = false then begin
// If app dir already exists while installing, skip add
if (Pos(pathdir[d], aExecArr[i]) > 0) then
updatepath := false;
break;
end else begin
// If app dir exists and = what we originally set, then delete at uninstall
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then
aExecArr[i] := '';
end;
end;
end;
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path
if (IsUninstaller() = false) AND (updatepath = true) then begin
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True);
// If uninstalling, write the full autoexec out
end else begin
SaveStringsToFile(aExecFile, aExecArr, False);
end;
end;
end;
end;
// Split a string into an array using passed delimeter
procedure MPExplode(var Dest: TArrayOfString; Text: String; Separator: String);
var
i: Integer;
begin
i := 0;
repeat
SetArrayLength(Dest, i+1);
if Pos(Separator,Text) > 0 then begin
Dest[i] := Copy(Text, 1, Pos(Separator, Text)-1);
Text := Copy(Text, Pos(Separator,Text) + Length(Separator), Length(Text));
i := i + 1;
end else begin
Dest[i] := Text;
Text := '';
end;
until Length(Text)=0;
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
taskname: String;
begin
taskname := ModPathName;
if CurStep = ssPostInstall then
if IsTaskSelected(taskname) then
ModPath();
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
aSelectedTasks: TArrayOfString;
i: Integer;
taskname: String;
regpath: String;
regstring: String;
appid: String;
begin
// only run during actual uninstall
if CurUninstallStep = usUninstall then begin
// get list of selected tasks saved in registry at install time
appid := '{#emit SetupSetting("AppId")}';
if appid = '' then appid := '{#emit SetupSetting("AppName")}';
regpath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\'+appid+'_is1');
RegQueryStringValue(HKLM, regpath, 'Inno Setup: Selected Tasks', regstring);
if regstring = '' then RegQueryStringValue(HKCU, regpath, 'Inno Setup: Selected Tasks', regstring);
// check each task; if matches modpath taskname, trigger patch removal
if regstring <> '' then begin
taskname := ModPathName;
MPExplode(aSelectedTasks, regstring, ',');
if GetArrayLength(aSelectedTasks) > 0 then begin
for i := 0 to GetArrayLength(aSelectedTasks)-1 do begin
if comparetext(aSelectedTasks[i], taskname) = 0 then
ModPath();
end;
end;
end;
end;
end;
function NeedRestart(): Boolean;
var
taskname: String;
begin
taskname := ModPathName;
if IsTaskSelected(taskname) and not UsingWinNT() then begin
Result := True;
end else begin
Result := False;
end;
end;

451
setup.py
View file

@ -2,409 +2,12 @@
# -*- coding: iso-8859-1 -*- # -*- coding: iso-8859-1 -*-
# Copyright (C) 2004-2005 Tristan Seligmann and Jonathan Jacobs # Copyright (C) 2004-2005 Tristan Seligmann and Jonathan Jacobs
# Copyright (C) 2012-2014 Bastian Kleineidam # Copyright (C) 2012-2014 Bastian Kleineidam
""" # Copyright (C) 2015 Tobias Gruetzmacher
Setup file for the distuils module.
It includes the following features:
- py2exe support (including InnoScript installer generation)
- Microsoft Visual C++ DLL installation for py2exe
- creation and installation of configuration files with installation data
- automatic MANIFEST.in check
"""
from __future__ import print_function from __future__ import print_function
import os import os
import sys
import codecs import codecs
import re from setuptools import setup, find_packages
import glob
import shutil
import subprocess
import warnings
try:
# py2exe monkey-patches the distutils.core.Distribution class
# So we need to import it before importing the Distribution class
import py2exe
has_py2exe = True
except ImportError:
# py2exe is not installed
has_py2exe = False
from distutils.core import setup, Distribution
from distutils.command.install_lib import install_lib
from distutils.command.register import register
from distutils import util
from distutils.file_util import write_file
AppVersion = '2.16'
AppName = 'dosage'
py_excludes = ['doctest', 'unittest', 'Tkinter', 'pdb',
'email', 'ftplib', 'pickle',
]
py_includes = ['dosagelib.plugins.*']
# py2exe options for Windows packaging
py2exe_options = dict(
packages=["encodings"],
excludes=py_excludes,
includes=py_includes,
# silence py2exe error about not finding msvcp90.dll
dll_excludes=['MSVCP90.dll'],
compressed=1,
optimize=2,
)
warnings.filterwarnings("ignore", r"Unknown distribution option")
def normpath (path):
"""Norm a path name to platform specific notation."""
return os.path.normpath(path)
def cnormpath (path):
"""Norm a path name to platform specific notation and make it absolute."""
path = normpath(path)
if os.name == 'nt':
# replace slashes with backslashes
path = path.replace("/", "\\")
if not os.path.isabs(path):
path = normpath(os.path.join(sys.prefix, path))
return path
release_ro = re.compile(r"\(released (.+)\)")
def get_release_date ():
"""Parse and return relase date as string from doc/changelog.txt."""
fname = os.path.join("doc", "changelog.txt")
release_date = "unknown"
with open(fname) as fd:
# the release date is on the first line
line = fd.readline()
mo = release_ro.search(line)
if mo:
release_date = mo.groups(1)
return release_date
# Microsoft Visual C++ runtime version (tested with Python 2.7.2)
MSVCP90Version = '9.0.21022.8'
MSVCP90Token = '1fc8b3b9a1e18e3b'
if os.name == 'nt':
data_files = []
else:
data_files = [('share/man/man1', ['doc/dosage.1'])]
def get_nt_platform_vars ():
"""Return program file path and architecture for NT systems."""
platform = util.get_platform()
if platform == "win-amd64":
# the Visual C++ runtime files are installed in the x86 directory
progvar = "%ProgramFiles(x86)%"
architecture = "amd64"
elif platform == "win32":
progvar = "%ProgramFiles%"
architecture = "x86"
else:
raise ValueError("Unsupported platform %r" % platform)
return os.path.expandvars(progvar), architecture
def add_msvc_files (files):
"""Add needed MSVC++ runtime files. Only Version 9.0.21022.8 is tested
and can be downloaded here:
http://www.microsoft.com/en-us/download/details.aspx?id=29
"""
prog_dir, architecture = get_nt_platform_vars()
dirname = "Microsoft.VC90.CRT"
version = "%s_%s_x-ww_d08d0375" % (MSVCP90Token, MSVCP90Version)
args = (architecture, dirname, version)
path = r'C:\Windows\WinSxS\%s_%s_%s\*.*' % args
files.append((dirname, glob.glob(path)))
# Copy the manifest file into the build directory and rename it
# because it must have the same name as the directory.
path = r'C:\Windows\WinSxS\Manifests\%s_%s_%s.manifest' % args
target = os.path.join(os.getcwd(), 'build', '%s.manifest' % dirname)
shutil.copy(path, target)
files.append((dirname, [target]))
if 'py2exe' in sys.argv[1:]:
if not has_py2exe:
raise SystemExit("py2exe module could not be imported")
add_msvc_files(data_files)
class MyInstallLib (install_lib, object):
"""Custom library installation."""
def install (self):
"""Install the generated config file."""
outs = super(MyInstallLib, self).install()
infile = self.create_conf_file()
outfile = os.path.join(self.install_dir, os.path.basename(infile))
self.copy_file(infile, outfile)
outs.append(outfile)
return outs
def create_conf_file (self):
"""Create configuration file."""
cmd_obj = self.distribution.get_command_obj("install")
cmd_obj.ensure_finalized()
# we have to write a configuration file because we need the
# <install_data> directory (and other stuff like author, url, ...)
# all paths are made absolute by cnormpath()
data = []
for d in ['purelib', 'platlib', 'lib', 'headers', 'scripts', 'data']:
attr = 'install_%s' % d
if cmd_obj.root:
# cut off root path prefix
cutoff = len(cmd_obj.root)
# don't strip the path separator
if cmd_obj.root.endswith(os.sep):
cutoff -= 1
val = getattr(cmd_obj, attr)[cutoff:]
else:
val = getattr(cmd_obj, attr)
if attr == 'install_data':
cdir = os.path.join(val, "share", "dosage")
data.append('config_dir = %r' % cnormpath(cdir))
elif attr == 'install_lib':
if cmd_obj.root:
_drive, tail = os.path.splitdrive(val)
if tail.startswith(os.sep):
tail = tail[1:]
self.install_lib = os.path.join(cmd_obj.root, tail)
else:
self.install_lib = val
data.append("%s = %r" % (attr, cnormpath(val)))
self.distribution.create_conf_file(data, directory=self.install_lib)
return self.get_conf_output()
def get_conf_output (self):
"""Get filename for distribution configuration file."""
return self.distribution.get_conf_filename(self.install_lib)
def get_outputs (self):
"""Add the generated config file to the list of outputs."""
outs = super(MyInstallLib, self).get_outputs()
conf_output = self.get_conf_output()
outs.append(conf_output)
if self.compile:
outs.extend(self._bytecode_filenames([conf_output]))
return outs
class MyDistribution (Distribution, object):
"""Custom distribution class generating config file."""
def __init__ (self, attrs):
"""Set console and windows scripts."""
super(MyDistribution, self).__init__(attrs)
self.console = ['dosage']
def run_commands (self):
"""Generate config file and run commands."""
cwd = os.getcwd()
data = []
data.append('config_dir = %r' % os.path.join(cwd, "config"))
data.append("install_data = %r" % cwd)
data.append("install_scripts = %r" % cwd)
self.create_conf_file(data)
super(MyDistribution, self).run_commands()
def get_conf_filename (self, directory):
"""Get name for config file."""
return os.path.join(directory, "_%s_configdata.py" % self.get_name())
def create_conf_file (self, data, directory=None):
"""Create local config file from given data (list of lines) in
the directory (or current directory if not given)."""
data.insert(0, "# this file is automatically created by setup.py")
data.insert(0, "# -*- coding: iso-8859-1 -*-")
if directory is None:
directory = os.getcwd()
filename = self.get_conf_filename(directory)
# add metadata
metanames = ("name", "version", "author", "author_email",
"maintainer", "maintainer_email", "url",
"license", "description", "long_description",
"keywords", "platforms", "fullname", "contact",
"contact_email")
for name in metanames:
method = "get_" + name
val = getattr(self.metadata, method)()
data.append("%s = %r" % (name, val))
data.append('release_date = "%s"' % get_release_date())
# write the config file
util.execute(write_file, (filename, data),
"creating %s" % filename, self.verbose >= 1, self.dry_run)
class InnoScript:
"""Class to generate INNO script."""
def __init__(self, lib_dir, dist_dir, windows_exe_files=[],
console_exe_files=[], service_exe_files=[],
comserver_files=[], lib_files=[]):
"""Store INNO script infos."""
self.lib_dir = lib_dir
self.dist_dir = dist_dir
if not self.dist_dir[-1] in "\\/":
self.dist_dir += "\\"
self.name = AppName
self.lname = AppName.lower()
self.version = AppVersion
self.windows_exe_files = [self.chop(p) for p in windows_exe_files]
self.console_exe_files = [self.chop(p) for p in console_exe_files]
self.service_exe_files = [self.chop(p) for p in service_exe_files]
self.comserver_files = [self.chop(p) for p in comserver_files]
self.lib_files = [self.chop(p) for p in lib_files]
self.icon = os.path.abspath(r'doc\icon\favicon.ico')
def chop(self, pathname):
"""Remove distribution directory from path name."""
assert pathname.startswith(self.dist_dir)
return pathname[len(self.dist_dir):]
def create(self, pathname=r"dist\omt.iss"):
"""Create Inno script."""
print("*** creating the inno setup script ***")
self.pathname = pathname
self.distfilebase = "%s-%s" % (self.name, self.version)
self.distfile = self.distfilebase + ".exe"
with open(self.pathname, "w") as fd:
self.write_inno_script(fd)
def write_inno_script (self, fd):
"""Write Inno script contents."""
print("; WARNING: This script has been created by py2exe. Changes to this script", file=fd)
print("; will be overwritten the next time py2exe is run!", file=fd)
print("[Setup]", file=fd)
print("AppName=%s" % self.name, file=fd)
print("AppVerName=%s %s" % (self.name, self.version), file=fd)
print("ChangesEnvironment=true", file=fd)
print(r"DefaultDirName={pf}\%s" % self.name, file=fd)
print("DefaultGroupName=%s" % self.name, file=fd)
print("OutputBaseFilename=%s" % self.distfilebase, file=fd)
print("OutputDir=..", file=fd)
print("SetupIconFile=%s" % self.icon, file=fd)
print(file=fd)
print("[Tasks]", file=fd)
print("Name: modifypath; Description: Add application directory to %PATH%", file=fd)
print(file=fd)
# List of source files
files = self.windows_exe_files + \
self.console_exe_files + \
self.service_exe_files + \
self.comserver_files + \
self.lib_files
print('[Files]', file=fd)
for path in files:
print(r'Source: "%s"; DestDir: "{app}\%s"; Flags: ignoreversion' % (path, os.path.dirname(path)), file=fd)
# Set icon filename
print('[Icons]', file=fd)
for path in self.windows_exe_files:
print(r'Name: "{group}\%s"; Filename: "{app}\%s"' %
(self.name, path), file=fd)
for path in self.console_exe_files:
name = os.path.basename(path).capitalize()
print(r'Name: "{group}\%s help"; Filename: "cmd.exe"; Parameters: "/K %s --help"' % (name, path), file=fd)
print(r'Name: "{group}\Uninstall %s"; Filename: "{uninstallexe}"' % self.name, file=fd)
print(file=fd)
# Uninstall optional log files
print('[UninstallDelete]', file=fd)
for path in (self.console_exe_files + self.windows_exe_files):
exename = os.path.basename(path)
print(r'Type: files; Name: "{pf}\%s\%s.log"' % (self.lname, exename), file=fd)
print(file=fd)
# Add app dir to PATH
print("[Code]", file=fd)
print("""\
const
ModPathName = 'modifypath';
ModPathType = 'user';
function ModPathDir(): TArrayOfString;
begin
setArrayLength(Result, 1)
Result[0] := ExpandConstant('{app}');
end;
#include "modpath.iss"
""", file=fd)
shutil.copy(r"scripts\modpath.iss", "dist")
def compile (self):
"""Compile Inno script with iscc.exe."""
print("*** compiling the inno setup script ***")
progpath = get_nt_platform_vars()[0]
cmd = r'%s\Inno Setup 5\iscc.exe' % progpath
subprocess.check_call([cmd, self.pathname])
def sign (self):
"""Sign InnoSetup installer with local self-signed certificate."""
print("*** signing the inno setup installer ***")
pfxfile = r'scripts\%s.pfx' % self.lname
if os.path.isfile(pfxfile):
path = get_windows_sdk_path()
signtool = os.path.join(path, "bin", "signtool.exe")
if os.path.isfile(signtool):
cmd = [signtool, 'sign', '/f', pfxfile, self.distfile]
subprocess.check_call(cmd)
else:
print("No signed installer: signtool.exe not found.")
else:
print("No signed installer: certificate %s not found." % pfxfile)
def get_windows_sdk_path():
"""Return path of Microsoft Windows SDK installation, or None if
not found."""
try:
import _winreg as winreg
except ImportError:
import winreg
sub_key = r"Software\Microsoft\Microsoft SDKs\Windows"
with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, sub_key) as key:
name = "CurrentInstallFolder"
return winreg.QueryValueEx(key, name)[0]
return None
try:
from py2exe.build_exe import py2exe as py2exe_build
class MyPy2exe (py2exe_build):
"""First builds the exe file(s), then creates a Windows installer.
Needs InnoSetup to be installed."""
def run (self):
"""Generate py2exe installer."""
# First, let py2exe do it's work.
py2exe_build.run(self)
print("*** preparing the inno setup script ***")
lib_dir = self.lib_dir
dist_dir = self.dist_dir
# create the Installer, using the files py2exe has created.
script = InnoScript(lib_dir, dist_dir, self.windows_exe_files,
self.console_exe_files, self.service_exe_files,
self.comserver_files, self.lib_files)
script.create()
script.compile()
script.sign()
except ImportError:
class MyPy2exe:
"""Dummy py2exe class."""
pass
class MyRegister (register, object):
"""Custom register command."""
def build_post_data(self, action):
"""Force application name to lower case."""
data = super(MyRegister, self).build_post_data(action)
data['name'] = data['name'].lower()
return data
def get_authors(): def get_authors():
"""Read list of authors from a text file, filtering comments.""" """Read list of authors from a text file, filtering comments."""
@ -418,48 +21,48 @@ def get_authors():
return u", ".join(authors) return u", ".join(authors)
args = dict( config = {}
name = AppName, with codecs.open(os.path.join('dosagelib', 'configuration.py')) as fp:
version = AppVersion, exec(fp.read(), config)
setup(
name = config['AppName'],
version = config['Version'],
description = 'a comic strip downloader and archiver', description = 'a comic strip downloader and archiver',
keywords = 'comic,webcomic,downloader,archiver', keywords = 'comic,webcomic,downloader,archiver',
author = get_authors(), author = get_authors(),
maintainer = 'Bastian Kleineidam', maintainer = config['Maintainer'],
maintainer_email = 'bastian.kleineidam@web.de', maintainer_email = config['MaintainerEmail'],
license = 'MIT', license = 'MIT',
url = 'http://wummel.github.io/dosage/', url = config['Url'],
packages = ( packages = find_packages(exclude=['tests']),
'dosagelib',
'dosagelib.plugins',
),
data_files = data_files,
scripts = ( scripts = (
'dosage', 'dosage',
), ),
distclass = MyDistribution,
cmdclass = {
'install_lib': MyInstallLib,
'py2exe': MyPy2exe,
'register': MyRegister,
},
options = {
"py2exe": py2exe_options,
},
classifiers = ( classifiers = (
'Environment :: Console', 'Environment :: Console',
'Intended Audience :: End Users/Desktop', 'Intended Audience :: End Users/Desktop',
'Topic :: Multimedia :: Graphics', 'Topic :: Multimedia :: Graphics',
'Topic :: Internet :: WWW/HTTP', 'Topic :: Internet :: WWW/HTTP',
'Development Status :: 4 - Beta', 'Development Status :: 4 - Beta',
'License :: OSI Approved :: GNU General Public License (GPL)', 'License :: OSI Approved :: MIT License',
'Programming Language :: Python', 'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Operating System :: OS Independent', 'Operating System :: OS Independent',
), ),
install_requires = ( install_requires = (
'requests', 'requests',
'pycountry', 'pycountry',
),
extras_require = {
'xpath': ["lxml"],
'css': ['cssselect'],
},
setup_requires = [
"setuptools_git >= 1.0",
]
) )
)
if __name__ == '__main__':
setup(**args)