Generate metadata as python module.

This commit is contained in:
Bastian Kleineidam 2013-04-08 20:12:50 +02:00
parent e5a4d8b317
commit d0540bb7a7
6 changed files with 158 additions and 12 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ Changelog.patool*
/doc/README.md /doc/README.md
/testresults.txt /testresults.txt
/tests/__pycache__ /tests/__pycache__
/_Patool_configdata.py

View File

@ -105,7 +105,10 @@ clean:
find . -name \*.pyo -delete find . -name \*.pyo -delete
rm -rf build dist rm -rf build dist
test: localbuild:
$(PYTHON) setup.py build
test: localbuild
$(PYTHON) -m pytest $(PYTESTOPTS) $(TESTOPTS) $(TESTS) $(PYTHON) -m pytest $(PYTESTOPTS) $(TESTOPTS) $(TESTS)
doc/$(LAPPNAME).txt: doc/$(LAPPNAME).1 doc/$(LAPPNAME).txt: doc/$(LAPPNAME).1
@ -135,5 +138,6 @@ changelog:
# closes issues mentioned in the changelog entries. # closes issues mentioned in the changelog entries.
github-changelog $(DRYRUN) $(GITUSER) $(GITREPO) doc/changelog.txt github-changelog $(DRYRUN) $(GITUSER) $(GITREPO) doc/changelog.txt
.PHONY: changelog update-copyright deb test clean count pyflakes check app .PHONY: changelog update-copyright deb test clean count pyflakes check
.PHONY: releasecheck release upload sign dist all tag register homepage .PHONY: releasecheck release upload sign dist all tag register homepage
.PHONY: localbuild doccheck

4
patool
View File

@ -22,8 +22,8 @@ import sys
import argparse import argparse
import pydoc import pydoc
import patoolib import patoolib
from patoolib.util import log_error, log_internal_error, PatoolError, App from patoolib.util import log_error, log_internal_error, PatoolError
from patoolib.configuration import App
def run_extract(args): def run_extract(args):
"""Extract files from archive(s).""" """Extract files from archive(s)."""

16
patoolib/configuration.py Normal file
View File

@ -0,0 +1,16 @@
# Copyright (C) 2013 Bastian Kleineidam
"""
Define basic configuration data like version or application name.
"""
import _Patool_configdata as configdata
Version = configdata.version
ReleaseDate = configdata.release_date
AppName = configdata.name
App = AppName+u" "+Version
Author = configdata.author
Maintainer = configdata.maintainer
Copyright = u"Copyright (C) 2004-2008 " + Author
Url = configdata.url
SupportUrl = Url + u"issues"
Email = configdata.author_email

View File

@ -23,6 +23,7 @@ import mimetypes
import tempfile import tempfile
import time import time
import traceback import traceback
from . import configuration
try: try:
from shutil import which from shutil import which
except ImportError: except ImportError:
@ -79,10 +80,6 @@ except ImportError:
return None return None
AppName = "patool"
App = "%s 1.1" % AppName
SupportUrl = "https://github.com/wummel/patool/issues"
# internal MIME database # internal MIME database
mimedb = None mimedb = None
@ -471,7 +468,7 @@ at %(url)s and include at least the information below:
Not disclosing some of the information below due to privacy reasons is ok. Not disclosing some of the information below due to privacy reasons is ok.
I will try to help you nonetheless, but you have to give me something I will try to help you nonetheless, but you have to give me something
I can work with ;) . I can work with ;) .
""" % dict(app=AppName, url=SupportUrl), file=out) """ % dict(app=configuration.AppName, url=configuration.SupportUrl), file=out)
if etype is None: if etype is None:
etype = sys.exc_info()[0] etype = sys.exc_info()[0]
if evalue is None: if evalue is None:
@ -483,7 +480,7 @@ I can work with ;) .
print_app_info(out=out) print_app_info(out=out)
print_locale_info(out=out) print_locale_info(out=out)
print(os.linesep, print(os.linesep,
"******** %s internal error, over and out ********" % AppName, file=out) "******** %s internal error, over and out ********" % configuration.AppName, file=out)
def print_env_info(key, out=sys.stderr): def print_env_info(key, out=sys.stderr):
"""If given environment key is defined, print it out.""" """If given environment key is defined, print it out."""
@ -501,7 +498,7 @@ def print_locale_info(out=sys.stderr):
def print_app_info(out=sys.stderr): def print_app_info(out=sys.stderr):
"""Print system and application info (output defaults to stderr).""" """Print system and application info (output defaults to stderr)."""
print("System info:", file=out) print("System info:", file=out)
print(App, file=out) print(configuration.App, file=out)
print("Python %(version)s on %(platform)s" % print("Python %(version)s on %(platform)s" %
{"version": sys.version, "platform": sys.platform}, file=out) {"version": sys.version, "platform": sys.platform}, file=out)
stime = strtime(time.time()) stime = strtime(time.time())

130
setup.py
View File

@ -22,6 +22,7 @@ import sys
if not hasattr(sys, "version_info") or sys.version_info < (2, 7, 0, "final", 0): if not hasattr(sys, "version_info") or sys.version_info < (2, 7, 0, "final", 0):
raise SystemExit("This program requires Python 2.7 or later.") raise SystemExit("This program requires Python 2.7 or later.")
import os import os
import re
import shutil import shutil
import glob import glob
import subprocess import subprocess
@ -29,7 +30,6 @@ try:
from cx_Freeze import setup, Executable from cx_Freeze import setup, Executable
except ImportError: except ImportError:
from distutils.core import setup from distutils.core import setup
from distutils.command.register import register
try: try:
# py2exe monkey-patches the distutils.core.Distribution class # py2exe monkey-patches the distutils.core.Distribution class
# So we need to import it before importing the Distribution class # So we need to import it before importing the Distribution class
@ -44,7 +44,10 @@ try:
except ImportError: except ImportError:
from distutils.core import Distribution from distutils.core import Distribution
executables = None executables = None
from distutils.command.register import register
from distutils.command.install_lib import install_lib
from distutils import util from distutils import util
from distutils.file_util import write_file
AppName = "Patool" AppName = "Patool"
AppVersion = "1.1" AppVersion = "1.1"
@ -74,6 +77,36 @@ MSVCP90Version = '9.0.21022.8'
MSVCP90Token = '1fc8b3b9a1e18e3b' MSVCP90Token = '1fc8b3b9a1e18e3b'
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
data_files = [] data_files = []
if os.name == 'nt': if os.name == 'nt':
data_files.append(('share', ['doc/patool.txt'])) data_files.append(('share', ['doc/patool.txt']))
@ -121,6 +154,63 @@ if 'py2exe' in sys.argv[1:]:
add_msvc_files(data_files) 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()
outs.append(self.get_conf_output())
return outs
class MyDistribution (Distribution, object): class MyDistribution (Distribution, object):
"""Custom distribution class generating config file.""" """Custom distribution class generating config file."""
@ -129,6 +219,43 @@ class MyDistribution (Distribution, object):
super(MyDistribution, self).__init__(attrs) super(MyDistribution, self).__init__(attrs)
self.console = ['patool'] self.console = ['patool']
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 InnoScript:
"""Class to generate INNO script.""" """Class to generate INNO script."""
@ -343,6 +470,7 @@ installed.
], ],
distclass = MyDistribution, distclass = MyDistribution,
cmdclass = { cmdclass = {
'install_lib': MyInstallLib,
'py2exe': MyPy2exe, 'py2exe': MyPy2exe,
'register': MyRegister, 'register': MyRegister,
}, },