mirror of https://github.com/tLDP/python-tldp
initial commit
This commit is contained in:
commit
701657e54b
|
@ -0,0 +1,31 @@
|
||||||
|
tldp - tools for publishing from TLDP sources
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
TLDP = The Linux Documentation Project.
|
||||||
|
These are a set of scripts that process committed documents in the
|
||||||
|
TLDP document source repository to an output tree of choice.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
You can install, upgrade, uninstall tldp tools with these commands::
|
||||||
|
|
||||||
|
$ pip install tldp
|
||||||
|
$ pip install --upgrade tldp
|
||||||
|
$ pip uninstall tldp
|
||||||
|
|
||||||
|
There's also a package for Debian/Ubuntu, but it's not always the
|
||||||
|
latest version.
|
||||||
|
|
||||||
|
Example usages:
|
||||||
|
---------------
|
||||||
|
|
||||||
|
FIXME: Missing examples.
|
||||||
|
|
||||||
|
Links
|
||||||
|
-----
|
||||||
|
|
||||||
|
* `Output documentation tree (sample) <http://www.tldp.org/>`_
|
||||||
|
|
||||||
|
* `Source tree on GitHub <https://github.com/tLDP/LDP>`_
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
|
||||||
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
|
|
||||||
|
with open(os.path.join(os.path.dirname(__file__), 'README.rst')) as r_file:
|
||||||
|
readme = r_file.read()
|
||||||
|
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='tldp',
|
||||||
|
version='0.1',
|
||||||
|
license='GNU',
|
||||||
|
author='Martin A. Brown',
|
||||||
|
author_email='martin@linux-ip.net',
|
||||||
|
description='tools for processing all TLDP source documents',
|
||||||
|
long_description=readme,
|
||||||
|
packages=find_packages(),
|
||||||
|
test_suite='tests',
|
||||||
|
install_requires=[
|
||||||
|
'six>=1.7',
|
||||||
|
],
|
||||||
|
classifiers=[
|
||||||
|
'Development Status :: 3 - Alpha',
|
||||||
|
'Intended Audience :: Developers',
|
||||||
|
'License :: OSI Approved :: MIT License',
|
||||||
|
'Operating System :: OS Independent',
|
||||||
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
|
'Topic :: Software Development :: Libraries :: Python Modules'
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .text import Text
|
||||||
|
from .rst import RestructuredText
|
||||||
|
from .markdown import Markdown
|
||||||
|
from .linuxdoc import Linuxdoc
|
||||||
|
from .docbooksgml import DocbookSGML
|
||||||
|
from .docbook4xml import Docbook4XML
|
||||||
|
from .docbook5xml import Docbook5XML
|
|
@ -0,0 +1,27 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import string
|
||||||
|
from ..utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
class SignatureChecker(object):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def signatureLocation(cls, name, fin):
|
||||||
|
fin.seek(0)
|
||||||
|
buf = fin.read(1024)
|
||||||
|
for sig in cls.signatures:
|
||||||
|
try:
|
||||||
|
sindex = string.index(buf.lower(), sig.lower())
|
||||||
|
logger.debug("In file %s, signature %s found at %s; doctype %s found",
|
||||||
|
name, sig, sindex, cls)
|
||||||
|
return sindex
|
||||||
|
except ValueError:
|
||||||
|
logger.debug("In file %s, signature %s not found for document type %s",
|
||||||
|
name, sig, cls.__name__)
|
||||||
|
return None
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
|
||||||
|
from .common import SignatureChecker
|
||||||
|
|
||||||
|
|
||||||
|
class Docbook4XML(SignatureChecker):
|
||||||
|
extensions = ['.xml']
|
||||||
|
signatures = ['-//OASIS//DTD DocBook XML V4.1.2//EN',
|
||||||
|
'-//OASIS//DTD DocBook XML V4.2//EN',
|
||||||
|
'-//OASIS//DTD DocBook XML V4.2//EN',
|
||||||
|
'-//OASIS//DTD DocBook XML V4.4//EN',
|
||||||
|
'-//OASIS//DTD DocBook XML V4.5//EN', ]
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
from .common import SignatureChecker
|
||||||
|
|
||||||
|
|
||||||
|
class Docbook5XML(SignatureChecker):
|
||||||
|
extensions = ['.xml']
|
||||||
|
signatures = ['-//OASIS//DTD DocBook V5.0/EN',
|
||||||
|
'http://docbook.org/ns/docbook', ]
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
from .common import SignatureChecker
|
||||||
|
|
||||||
|
|
||||||
|
class DocbookSGML(SignatureChecker):
|
||||||
|
extensions = ['.sgml']
|
||||||
|
signatures = ['-//Davenport//DTD DocBook V3.0//EN',
|
||||||
|
'-//OASIS//DTD DocBook V3.1//EN',
|
||||||
|
'-//OASIS//DTD DocBook V4.1//EN',
|
||||||
|
'-//OASIS//DTD DocBook V4.2//EN', ]
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
from .common import SignatureChecker
|
||||||
|
|
||||||
|
|
||||||
|
class Linuxdoc(SignatureChecker):
|
||||||
|
extensions = ['.sgml']
|
||||||
|
signatures = ['<!doctype linuxdoc system', ]
|
||||||
|
|
||||||
|
def create_txt(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_pdf(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_html(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_htmls(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Markdown(object):
|
||||||
|
extensions = ['.md']
|
||||||
|
signatures = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
class RestructuredText(object):
|
||||||
|
extensions = ['.rst']
|
||||||
|
signatures = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,11 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from ..utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Text(object):
|
||||||
|
extensions = ['.txt']
|
||||||
|
signatures = []
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,86 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
from . import doctypes
|
||||||
|
from .utils import logger
|
||||||
|
|
||||||
|
|
||||||
|
def makefh(thing):
|
||||||
|
if isinstance(thing, file):
|
||||||
|
f = thing
|
||||||
|
elif isinstance(thing, str) and os.path.isfile(thing):
|
||||||
|
f = open(thing)
|
||||||
|
else:
|
||||||
|
raise TypeError("Cannot make file from type %s of %r" %
|
||||||
|
(type(thing), thing,))
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
def listDoctypes():
|
||||||
|
knowndoctypes = list()
|
||||||
|
for name, member in inspect.getmembers(doctypes, inspect.isclass):
|
||||||
|
logger.info("Located class %s (%r).", name, member)
|
||||||
|
knowndoctypes.append(member)
|
||||||
|
logger.info("Capable of handling %s document classes.", len(knowndoctypes))
|
||||||
|
return knowndoctypes
|
||||||
|
|
||||||
|
|
||||||
|
def guess(thing):
|
||||||
|
try:
|
||||||
|
fin = makefh(thing)
|
||||||
|
except TypeError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
_, ext = os.path.splitext(fin.name)
|
||||||
|
possible = [t for t in knowndoctypes if ext in t.extensions]
|
||||||
|
if not possible:
|
||||||
|
return None
|
||||||
|
if len(possible) == 1:
|
||||||
|
doctype = possible.pop()
|
||||||
|
return doctype
|
||||||
|
|
||||||
|
# -- for this extension, multiple document types, probably SGML, XML
|
||||||
|
#
|
||||||
|
logger.info("Extension is %s for %s; multiple possible document types.",
|
||||||
|
ext, fin.name)
|
||||||
|
for doctype in possible:
|
||||||
|
logger.debug("Extension is %s for %s; %s.", ext, fin.name, doctype)
|
||||||
|
|
||||||
|
guesses = list()
|
||||||
|
for doctype in possible:
|
||||||
|
sindex = doctype.signatureLocation(fin.name, fin)
|
||||||
|
if sindex is not None:
|
||||||
|
guesses.append((sindex, doctype))
|
||||||
|
|
||||||
|
if not guesses:
|
||||||
|
logger.info("Extension is %s for %s; but no matching signature found.",
|
||||||
|
ext, fin.name)
|
||||||
|
return None
|
||||||
|
if len(guesses) == 1:
|
||||||
|
_, doctype = guesses.pop()
|
||||||
|
return doctype
|
||||||
|
|
||||||
|
# -- OK, this is unusual; we still found multiple document type
|
||||||
|
# signatures. Seems rare but unlikely, so we should choose the
|
||||||
|
# first signature in the file as the more likely document type.
|
||||||
|
#
|
||||||
|
guesses.sort()
|
||||||
|
logger.info("Multiple guesses for file %s", fin.name)
|
||||||
|
for sindex, doctype in guesses:
|
||||||
|
logger.info("Could be %s (file position %s)", doctype, sindex)
|
||||||
|
logger.info("Going to guess that it is %s", doctype)
|
||||||
|
_, doctype = guesses.pop()
|
||||||
|
return doctype
|
||||||
|
|
||||||
|
|
||||||
|
knowndoctypes = listDoctypes()
|
||||||
|
knownextensions = set()
|
||||||
|
for x in knowndoctypes:
|
||||||
|
knownextensions.update(x.extensions)
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def getLogger(opts):
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
|
||||||
|
logger = logging.getLogger()
|
||||||
|
return logger
|
||||||
|
|
||||||
|
class SourceDocument(object):
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.filename = fname
|
||||||
|
self.stem =
|
||||||
|
|
||||||
|
def
|
||||||
|
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,20 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
|
def getLogger(opts):
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
|
||||||
|
logger = logging.getLogger()
|
||||||
|
return logger
|
||||||
|
|
||||||
|
class SourceDocument(object):
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.filename = fname
|
||||||
|
self.stem =
|
||||||
|
|
||||||
|
def
|
||||||
|
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,118 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from .utils import logger
|
||||||
|
from .guess import knownextensions
|
||||||
|
|
||||||
|
# class SourceTree(object):
|
||||||
|
#
|
||||||
|
# def __init__(self, root, config):
|
||||||
|
# pass
|
||||||
|
|
||||||
|
|
||||||
|
class SourceDir(object):
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.dirname
|
||||||
|
|
||||||
|
def __init__(self, dirname):
|
||||||
|
self.dirname = os.path.abspath(dirname)
|
||||||
|
self.docs = list()
|
||||||
|
if not os.path.exists(dirname):
|
||||||
|
raise OSError("[Errno 2] No such file or directory: " + dirname)
|
||||||
|
logger.info("Time to go for an enumeration stroll in %s", dirname)
|
||||||
|
self.enumerateDocuments()
|
||||||
|
|
||||||
|
def enumerateDocuments(self):
|
||||||
|
for fname in os.listdir(self.dirname):
|
||||||
|
possible = os.path.join(self.dirname, fname)
|
||||||
|
if os.path.isfile(possible):
|
||||||
|
self.docs.append(SourceDocument(possible))
|
||||||
|
elif os.path.isdir(fname):
|
||||||
|
stem = os.path.basename(fname)
|
||||||
|
for ext in knownextensions:
|
||||||
|
possible = os.path.join(self.dirname, fname, stem + ext)
|
||||||
|
if os.path.isfile(possible):
|
||||||
|
self.docs.append(SourceDocument(possible))
|
||||||
|
logger.info("Discovered %s documents in %s",
|
||||||
|
len(self.docs), self.dirname)
|
||||||
|
|
||||||
|
|
||||||
|
class SourceDocument(object):
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.filename
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
# -- canonicalize the pathname we are given.
|
||||||
|
self.filename = os.path.abspath(filename)
|
||||||
|
if not os.path.exists(self.filename):
|
||||||
|
raise OSError("Missing source document: " + self.filename)
|
||||||
|
|
||||||
|
self.dirname, self.basename = os.path.split(self.filename)
|
||||||
|
self.stem, self.ext = os.path.splitext(self.basename)
|
||||||
|
self.stat = os.stat(self.filename)
|
||||||
|
|
||||||
|
self.doctype = None
|
||||||
|
self.resources = False # -- assume no ./images/, ./resources/
|
||||||
|
self.singlefile = True # -- assume only one file
|
||||||
|
parentdir = os.path.basename(self.dirname)
|
||||||
|
if parentdir == self.stem:
|
||||||
|
self.singlefile = False
|
||||||
|
for rdir in ('resources', 'images'):
|
||||||
|
if os.path.exists(os.path.join(self.dirname, rdir)):
|
||||||
|
self.resources = True
|
||||||
|
|
||||||
|
def doctype(self):
|
||||||
|
if self.doctype is None:
|
||||||
|
self.doctype = guess(self.filename)
|
||||||
|
return self.doctype
|
||||||
|
|
||||||
|
|
||||||
|
class OutputDocument(object):
|
||||||
|
|
||||||
|
formats = {'pdf': '.pdf',
|
||||||
|
'txt': '.txt',
|
||||||
|
'html': '.html',
|
||||||
|
'htmls': '-single.html', }
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def txt(self):
|
||||||
|
return os.path.join(self.dirname, self.stem, '.txt')
|
||||||
|
|
||||||
|
|
||||||
|
class OutputDir(object):
|
||||||
|
|
||||||
|
def __init__(self, dirname):
|
||||||
|
self.dirname = os.path.abspath(dirname)
|
||||||
|
self.parent = os.path.dirname(dirname)
|
||||||
|
self.stem = os.path.basename(dirname)
|
||||||
|
self.members = list()
|
||||||
|
|
||||||
|
def mkdir(self):
|
||||||
|
if not os.path.exists(self.parent):
|
||||||
|
raise OSError("Missing parent directory: " + self.parent)
|
||||||
|
os.mkdir(self.dirname)
|
||||||
|
return os.path.exists(self.dirname)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def members(self):
|
||||||
|
return os.path.exists(self.dirname)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def exists(self):
|
||||||
|
return os.path.exists(self.dirname)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def isComplete(self):
|
||||||
|
return all(self.pdf, self.html, self.htmls, self.txt)
|
||||||
|
|
||||||
|
# -- end of file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#! /usr/bin/python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
def getLogger(**opts):
|
||||||
|
level = opts.get('level', logging.INFO)
|
||||||
|
logging.basicConfig(stream=sys.stderr, level=level)
|
||||||
|
logger = logging.getLogger()
|
||||||
|
return logger
|
||||||
|
|
||||||
|
logger = getLogger()
|
||||||
|
|
||||||
|
#
|
||||||
|
# -- end of file
|
Loading…
Reference in New Issue