Initial import of python-Levenshtein rhbz#429882
This commit is contained in:
parent
a5b30e9729
commit
d73258a4d0
5 changed files with 297 additions and 0 deletions
|
|
@ -0,0 +1 @@
|
|||
python-Levenshtein-0.10.1.tar.bz2
|
||||
216
genextdoc.py
Normal file
216
genextdoc.py
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
#!/usr/bin/env python
|
||||
# Simple Python extension module doc generator.
|
||||
# @(#) $Id: genextdoc.py,v 1.1 2008/10/30 05:13:27 dwayne Exp $
|
||||
# Written by Yeti <yeti@physics.muni.cz>
|
||||
# This program is in the public domain.
|
||||
import re, sys, types, inspect
|
||||
from cgi import escape as q
|
||||
|
||||
args = sys.argv
|
||||
args.pop(0)
|
||||
if not args:
|
||||
print 'Usage: genextdoc.py [--selfcontained] module_name'
|
||||
sys.exit(0)
|
||||
|
||||
selfcontained = False
|
||||
if args[0].startswith('-') and 'selfcontained'.startswith(args[0].strip('-')):
|
||||
selfcontained = True
|
||||
args.pop(0)
|
||||
if not args: sys.exit(0)
|
||||
modname = args.pop(0)
|
||||
plain_docs = args
|
||||
|
||||
html_head = """\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
|
||||
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
|
||||
<head><title>%s %s</title></head>
|
||||
<body>
|
||||
"""
|
||||
|
||||
html_foot = """\
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
def split_para(doc):
|
||||
p = []
|
||||
for x in doc.split('\n\n'):
|
||||
x = x.strip()
|
||||
if x.find('\n>>>') > -1:
|
||||
h, t = x.split('\n>>>', 1)
|
||||
p.append(h)
|
||||
p.append('>>>' + t)
|
||||
else:
|
||||
p.append(x)
|
||||
return p
|
||||
|
||||
def get_doc(members):
|
||||
try: doc = members['__doc__']
|
||||
except KeyError: pass
|
||||
if doc: return doc
|
||||
try: doc = 'Python module %s' % members['__name__']
|
||||
except KeyError: pass
|
||||
if doc: return doc
|
||||
else: return 'A Python module'
|
||||
|
||||
def format_synopsis(synopsis, link=False, classname=None):
|
||||
lst = synopsis.split('\n')
|
||||
for i, s in zip(range(len(lst)), lst):
|
||||
m = re.match(r'(?P<func>\w+)(?P<args>.*)', s)
|
||||
args = re.sub(r'([a-zA-Z]\w+)', r'<var>\1</var>', m.group('args'))
|
||||
func = m.group('func')
|
||||
if link:
|
||||
if classname:
|
||||
func = '<a href="#%s-%s">%s</a>' % (classname, func, func)
|
||||
else:
|
||||
func = '<a href="#%s">%s</a>' % (func, func)
|
||||
lst[i] = func + args
|
||||
return '<br/>\n'.join(lst)
|
||||
|
||||
def format_para(p):
|
||||
if not p: return ''
|
||||
doc = ''
|
||||
if p.startswith('>>>'): doc += '<pre>\n%s\n</pre>\n' % q(p)
|
||||
else:
|
||||
if not re.search('^- ', p, re.M): doc += '<p>%s</p>\n' % q(p)
|
||||
else:
|
||||
p = re.split('(?m)^- ', p)
|
||||
if p[0]: doc += '<p>%s</p>\n' % q(p[0].strip())
|
||||
del p[0]
|
||||
doc += ('<ul>%s</ul>\n'
|
||||
% '\n'.join(['<li>%s</li>' % q(p.strip()) for p in p]))
|
||||
return doc
|
||||
|
||||
def preprocess_routine(name, doc):
|
||||
parts = split_para(doc)
|
||||
if parts: summary = parts.pop(0)
|
||||
else: summary = 'FIXME'
|
||||
if parts and re.match(r'\w+\(.*\)', parts[0]): synopsis = parts.pop(0)
|
||||
else: synopsis = name + '()'
|
||||
return {'synopsis': synopsis, 'summary': summary, 'details': parts}
|
||||
|
||||
def analyse(obj):
|
||||
members = obj.__dict__
|
||||
if inspect.isclass(obj):
|
||||
main_doc = preprocess_routine(obj.__name__, get_doc(members))
|
||||
bases = [x.__name__ for x in obj.__bases__]
|
||||
else:
|
||||
main_doc = split_para(get_doc(members))
|
||||
bases = []
|
||||
routines = {}
|
||||
classes = {}
|
||||
data = {}
|
||||
for name, m in members.items():
|
||||
if name.startswith('__'): continue
|
||||
try:
|
||||
mro = list(inspect.getmro(m))
|
||||
if mro[0] != m: continue
|
||||
except AttributeError: pass
|
||||
if inspect.isroutine(m):
|
||||
try: doc = m.__doc__
|
||||
except KeyError: pass
|
||||
if not doc: doc = 'FIXME'
|
||||
routines[name] = preprocess_routine(name, doc)
|
||||
continue
|
||||
if inspect.isclass(m):
|
||||
classes[name] = analyse(m)
|
||||
continue
|
||||
t = type(m)
|
||||
if t == types.IntType or t == types.StringType:
|
||||
data[name] = repr(m)
|
||||
else:
|
||||
data[name] = m.__doc__
|
||||
return {'name': obj.__name__, 'doc': main_doc, 'routines': routines,
|
||||
'classes': classes, 'data': data, 'bases': bases}
|
||||
|
||||
def format(tree, level, prefix=''):
|
||||
name = tree['name']
|
||||
if prefix: fullname = '%s-%s' % (prefix, name)
|
||||
else: fullname = name
|
||||
##### Main doc
|
||||
doc = []
|
||||
if level > 1:
|
||||
doc = ['<h%d id="%s">' % (level, fullname)]
|
||||
try: doc.append(format_synopsis(tree['doc']['synopsis']))
|
||||
except TypeError:
|
||||
doc.append(name)
|
||||
doc.append('</h%d>\n' % level)
|
||||
if tree.has_key('bases'):
|
||||
doc.append('<p>Bases: %s.</p>\n' % ', '.join(tree['bases']))
|
||||
try: lst = [tree['doc']['summary']] + tree['doc']['details']
|
||||
except TypeError: lst = tree['doc']
|
||||
for p in lst: doc.append(format_para(p))
|
||||
##### Table of contents
|
||||
routines = tree['routines'].keys()
|
||||
classes = tree['classes'].keys()
|
||||
data = tree['data'].keys()
|
||||
if routines:
|
||||
routines.sort()
|
||||
if level == 1: doc.append('<p><b>Functions:</b></p>\n')
|
||||
else: doc.append('<p><b>Methods:</b></p>\n')
|
||||
doc.append('<ul class="ltoc">\n')
|
||||
for r in routines:
|
||||
synopsis = tree['routines'][r]['synopsis']
|
||||
doc.append('<li>%s</li>\n' % format_synopsis(synopsis, True,
|
||||
fullname))
|
||||
doc.append('</ul>\n')
|
||||
if classes:
|
||||
classes.sort()
|
||||
doc.append('<p><b>Classes:</b></p>\n')
|
||||
doc.append('<ul class="ltoc">\n')
|
||||
for r in classes:
|
||||
synopsis = tree['classes'][r]['doc']['synopsis']
|
||||
doc.append('<li>%s</li>\n' % format_synopsis(synopsis, True,
|
||||
fullname))
|
||||
doc.append('</ul>\n')
|
||||
if data:
|
||||
data.sort()
|
||||
doc.append('<p><b>Data:</b></p>\n')
|
||||
doc.append('<ul class="ltoc">\n')
|
||||
for r in data:
|
||||
doc.append('<li>%s = %s</li>\n' % (r, q(tree['data'][r])))
|
||||
doc.append('</ul>\n')
|
||||
##### Functions
|
||||
if routines:
|
||||
if level == 1: doc.append('<hr/>\n')
|
||||
doc.append('<dl>\n')
|
||||
for r in routines:
|
||||
doc.append('<dt id="%s-%s">' % (fullname, r))
|
||||
rt = tree['routines'][r]
|
||||
doc.append('%s</dt>\n<dd>' % format_synopsis(rt['synopsis']))
|
||||
for p in [rt['summary']] + rt['details']:
|
||||
doc.append(format_para(p))
|
||||
doc.append('</dd>\n')
|
||||
doc.append('</dl>\n')
|
||||
##### Classes
|
||||
if classes:
|
||||
for r in classes:
|
||||
doc.append('<hr/>\n')
|
||||
doc.append(format(tree['classes'][r], level+1, fullname))
|
||||
return ''.join(doc)
|
||||
|
||||
exec 'import %s as __test__' % modname
|
||||
doctree = analyse(__test__)
|
||||
document = format(doctree, 1)
|
||||
print modname + '.html'
|
||||
fh = file(modname + '.html', 'w')
|
||||
if selfcontained: fh.write(html_head % (modname, 'module API'))
|
||||
fh.write(document)
|
||||
if selfcontained: fh.write(html_foot)
|
||||
fh.close()
|
||||
for f in plain_docs:
|
||||
try: fh = file(f, 'r')
|
||||
except: continue
|
||||
document = fh.read()
|
||||
fh.close()
|
||||
print f + '.xhtml'
|
||||
fh = file(f + '.xhtml', 'w')
|
||||
if selfcontained: fh.write(html_head % (modname, f))
|
||||
fh.write('<h1>%s %s</h1>\n\n' % (modname, f))
|
||||
fh.write('<pre class="main">\n')
|
||||
fh.write(document)
|
||||
fh.write('</pre>\n')
|
||||
if selfcontained: fh.write(html_foot)
|
||||
fh.close()
|
||||
1
import.log
Normal file
1
import.log
Normal file
|
|
@ -0,0 +1 @@
|
|||
python-Levenshtein-0_10_1-6_fc9:HEAD:python-Levenshtein-0.10.1-6.fc9.src.rpm:1225343235
|
||||
78
python-Levenshtein.spec
Normal file
78
python-Levenshtein.spec
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
|
||||
|
||||
Name: python-Levenshtein
|
||||
Summary: Python extension computing string distances and similarities
|
||||
Version: 0.10.1
|
||||
Release: 6%{?dist}
|
||||
|
||||
Group: Development/Libraries
|
||||
License: GPLv2+
|
||||
|
||||
# The original site: http://trific.ath.cx/python/levenshtein/
|
||||
# no longer exists so pointing to the pypi listing instead.
|
||||
URL: http://pypi.python.org/pypi/python-Levenshtein/
|
||||
|
||||
# The wayback machine provides this link to the original source:
|
||||
# http://web.archive.org/web/20060715051500/http://trific.ath.cx/Ftp/python/levenshtein/python-Levenshtein-0.10.1.tar.bz2
|
||||
# SHA1: d630141e003f47a43e0f8eacdcbf593bf9d15ed6
|
||||
# The sourceforge files are a mirror of these files.
|
||||
Source: http://downloads.sourceforge.net/translate/python-Levenshtein-%{version}.tar.bz2
|
||||
|
||||
# The same applies to genextdoc.py see v 1.5:
|
||||
# http://web.archive.org/web/20060717041205/http://trific.ath.cx/Ftp/python/genextdoc.py
|
||||
# SHA1: 5c91974b102f42144529913ce181c1866451bcf6
|
||||
Source1: genextdoc.py
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
BuildRequires: python-devel
|
||||
BuildRequires: python-setuptools-devel
|
||||
|
||||
%description
|
||||
Levenshtein computes Levenshtein distances, similarity ratios, generalized
|
||||
medians and set medians of Strings and Unicodes. Because it's implemented
|
||||
in C, it's much faster than corresponding Python library functions and
|
||||
methods.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
cp %{SOURCE1} .
|
||||
|
||||
%build
|
||||
CFLAGS="$RPM_OPT_FLAGS" %{__python} -c 'import setuptools; execfile("setup.py")' build
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
%{__python} -c 'import setuptools; execfile("setup.py")' install --skip-build --root $RPM_BUILD_ROOT
|
||||
PYTHONPATH=$PYTHONPATH:$RPM_BUILD_ROOT/%{python_sitearch} %{__python} genextdoc.py Levenshtein
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc README COPYING NEWS StringMatcher.py Levenshtein.html
|
||||
%{python_sitearch}/*egg-info
|
||||
%{python_sitearch}/Levenshtein.so
|
||||
|
||||
%changelog
|
||||
* Thu Mar 27 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-6
|
||||
- Comments about location of source files
|
||||
- Update genextdoc.py to v1.5
|
||||
|
||||
* Thu Mar 27 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-5
|
||||
- Build and package *egg-info
|
||||
- Fix some rpmlint issues
|
||||
|
||||
* Thu Feb 14 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-4
|
||||
- Add genextdoc.py as Source not Patch
|
||||
|
||||
* Wed Jan 30 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-3
|
||||
- Some rpmlint fixes
|
||||
- Fix document generation
|
||||
|
||||
* Wed Jan 23 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-2
|
||||
- Add missing genextdoc.py to generate usage documentation
|
||||
|
||||
* Wed Jan 23 2008 Dwayne Bailey <dwayne@translate.org.za> - 0.10.1-1
|
||||
- Initial packaging
|
||||
1
sources
1
sources
|
|
@ -0,0 +1 @@
|
|||
af9b9c69c4563e211b11dc5184a93872 python-Levenshtein-0.10.1.tar.bz2
|
||||
Loading…
Add table
Add a link
Reference in a new issue