#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2019, Wolfgang Scherer, <Wolfgang.Scherer at gmx.de>
#
# This file is part of Documentation Standard.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# (progn (forward-line 1) (snip-insert "py_doc.main" t t "python") (insert "\n"))
r"""
sphinx_doc_snip.py - process sphinx-doc document snippets.
====== ====================
usage: sphinx_doc_snip.py [OPTIONS] file-to-process ...
or import sphinx_doc_snip
====== ====================
Options
=======
===================== ==================================================
--force overwrite existing files.
:rem:`space`
--no-defaults do not read default configuration files.
-c, --config CFG add CFG to list of configuration files.
-i, --include INC add INC as document to parse for snippets
only. The document is not resolved.
-r, --replace REPL add replacement `WHAT=WITH`. `@WHAT@` is
replaced by string `WITH` after resolving
snippets.
-f, --format FMT format for output documents. Default:
`{dir}/{base}-x{ext}`.
Placeholders: `path`, `dir`, `file`, `base`,
`ext`, `sbase` (secondary base of `base`),
`sext`.
If format is `-`, standard output is used.
:rem:`space`
--html convert to HTML with sphinx-readme.sh(1)
--pdf convert to PDF with sphinx-readme.sh(1)
-q, --quiet suppress warnings
-v, --verbose verbose test output
-d, --debug[=NUM] show debug information
-h, --help display this help message
--template list show available templates.
--eide[=COMM] Emacs IDE template list (implies --template list).
--template[=NAME] extract named template to standard
output. Default NAME is ``-``.
--extract[=DIR] extract adhoc files to directory DIR (default: ``.``)
--explode[=DIR] explode script with adhoc in directory DIR
(default ``__adhoc__``)
--setup[=install] explode script into temporary directory and call
`python setup.py install`
--implode implode script with adhoc
-t, --test run doc tests
===================== ==================================================
Description
===========
:program:`sphinx_doc_snip.py` parses a set of documents for
document snippet defintions and resolves document snippet references
accordingly. The specification is in |chapter-document-snippets|.
Configuration Files
-------------------
The configuration files
- doc/.doc-snip.rc.default
- .doc-snip.rc.default
- doc/.doc-snip.rc
- .doc-snip.rc
are read in that order.
Example::
FORCE=no
FORMAT='{sbase}{sext}'
INCLUDE='
README.txt
README-stations.txt
'
REPLACE='
user=Max Benutzer
user_short=mb
'
Replacements
------------
The replacement facility allows to specify arbitrary replacement text
for placeholders enclosed in ``@``. With the following replacement
options:
+-----------------------------------------------------+--------------------------+--------------------------------+
| replacement option | placeholder | replacement |
+=====================================================+==========================+================================+
| --replace 'user=Max Benutzer' | `@`\ `user`\ `@` | Max Benutzer |
+-----------------------------------------------------+--------------------------+--------------------------------+
| --replace 'user_short=mb' | `@`\ `user_short`\ `@` | mb |
+-----------------------------------------------------+--------------------------+--------------------------------+
| --replace 'hostname_pfx=laptop-' | `@`\ `hostname_pfx`\ `@` | laptop- |
+-----------------------------------------------------+--------------------------+--------------------------------+
| --replace 'hostname=@\ hostname_pfx@@\ user_short@' | `@`\ `hostname`\ `@` | @\ hostname_pfx@@\ user_short@ |
+-----------------------------------------------------+--------------------------+--------------------------------+
the placeholder `@`\ `hostname`\ `@` is replaced recursively
accordingly:
@hostname@ => `laptop-mb`
- |:todo:| recursive snippet resolution
Module
======
Automatic Exports
=================
>>> for ex in __all__: printf(sformat('from {0} import {1}', __name__, ex))
from sphinx_doc_snip import Documentation
from sphinx_doc_snip import Document
from sphinx_doc_snip import Snippet
from sphinx_doc_snip import Section
Explicit Exports
================
>>> if '__all_internal__' in globals():
... for ex in __all_internal__:
... printf(sformat('from {0} import {1}', __name__, ex))
.. _END_OF_HELP_sphinx_doc_snip:
Details
=======
"""
# (progn (forward-line 1) (snip-insert "py.b.future.with" t t "python") (insert "\n"))
# for python 2.5
from __future__ import with_statement
# (progn (forward-line 1) (snip-insert "py.main.pyramid.activate" t t "py") (insert ""))
# --------------------------------------------------
# |||:sec:||| COMPATIBILITY
# --------------------------------------------------
import sys
# (progn (forward-line 1) (snip-insert "py.b.printf" t t "py") (insert "\n"))
# adapted from http://www.daniweb.com/software-development/python/code/217214
try:
printf = eval("print") # python 3.0 case
except SyntaxError:
printf_dict = dict()
try:
exec("from __future__ import print_function\nprintf=print", printf_dict)
printf = printf_dict["printf"] # 2.6 case
except SyntaxError:
def printf(*args, **kwd): # 2.4, 2.5, define our own Print function
fout = kwd.get("file", sys.stdout)
w = fout.write
if args:
w(str(args[0]))
sep = kwd.get("sep", " ")
for a in args[1:]:
w(sep)
w(str(a))
w(kwd.get("end", "\n"))
del printf_dict
# (progn (forward-line 1) (snip-insert "py.b.sformat" t t "py") (insert "\n"))
try:
('{0}').format(0)
def sformat (fmtspec, *args, **kwargs):
return fmtspec.format(*args, **kwargs)
except AttributeError:
try:
import stringformat
def sformat (fmtspec, *args, **kwargs):
return stringformat.FormattableString(fmtspec).format(
*args, **kwargs)
except ImportError:
printf('error: stringformat missing. Try `easy_install stringformat`.', file=sys.stderr)
# (progn (forward-line 1) (snip-insert "py.b.isstring" t t "python") (insert "\n"))
try:
from ws_seq_type import isstring, issequence, sequence_type, UCHAR_FMT
except ImportError:
# (progn (forward-line 1) (snip-insert "py.f.isstring" t t "py") (insert "\n"))
exec('''
def isstring(obj):
return isinstance(obj, basestring)
'''.strip())
try:
isstring("")
UCHAR_FMT = 'u"{0}u{1:04x}"'
except NameError:
def isstring(obj):
return isinstance(obj, str) or isinstance(obj, bytes)
UCHAR_FMT = '"{0}u{1:04x}"'
# (progn (forward-line 1) (snip-insert "py.f.issequence" t t "py") (insert "\n"))
def issequence(arg, or_dict=False, or_seq=True): # ||:fnc:||
if not isstring(arg):
if hasattr(arg, 'items'):
return or_dict
if hasattr(arg, '__getitem__'):
return True
if hasattr(arg, '__iter__'):
return or_seq
return False
# (progn (forward-line 1) (snip-insert-mode "py.f.sequence_type" t) (insert "\n"))
_st_strg = (True, False, False, False)
_st_list = (False, True, False, False)
_st_dict = (False, False, True, False)
_st_seq = (False, False, False, True)
_st_none = (False, False, False, False)
def sequence_type(value): # ||:fnc:||
if isstring(value):
return _st_strg
if hasattr(value, 'items'):
return _st_dict
if hasattr(value, '__getitem__'):
return _st_list
if hasattr(value, '__iter__'):
return _st_seq
return _st_none
# (progn (forward-line 1) (snip-insert-mode "py.f.uchar" t) (insert "\n"))
def uchar(num):
'''Make UNICODE character.'''
return eval(sformat(UCHAR_FMT,'\\', num))
# (progn (forward-line 1) (snip-insert "py.b.dict.items" t t "py") (insert "\n"))
try:
getattr(dict(), 'iteritems')
except AttributeError:
ditems = lambda d: getattr(d, 'items')()
dkeys = lambda d: getattr(d, 'keys')()
dvalues = lambda d: getattr(d, 'values')()
else:
ditems = lambda d: getattr(d, 'iteritems')()
dkeys = lambda d: getattr(d, 'iterkeys')()
dvalues = lambda d: getattr(d, 'itervalues')()
# (progn (forward-line 1) (snip-insert "py.b.xrange" t t "py") (insert "\n"))
# `xrange` returns a generator, which `range` already does for python3
# note: use l.. and g.. to get list/generator versions
try:
xrange(0)
lrange = lambda *args, **kwargs: range(*args, **kwargs)
except NameError:
xrange = range
lrange = lambda *args, **kwargs: list(range(*args, **kwargs))
grange = xrange
# `xfilter` returns a list, `filter` may return a generator. This is
# different from the range/xrange semantics!
if isinstance(filter(str, []), list):
xfilter = filter
gfilter = lambda _f, _s, *args, **kwargs: (_e for _e in _s if _f(_e))
else:
xfilter = lambda *args, **kwargs: list(filter(*args, **kwargs))
gfilter = filter
lfilter = xfilter
# `xmap` returns a list, `map` may return a generator. This is
# different from the range/xrange semantics!
if isinstance(map(str, []), list):
xmap = map
gmap = lambda _f, _s, *args, **kwargs: (_f(_e) for _e in _s)
else:
xmap = lambda *args, **kwargs: list(map(*args, **kwargs))
gmap = map
lmap = xmap
# `long` is gone in python3
try:
isinstance(int, long)
except NameError:
long = int
# (progn (forward-line 1) (snip-insert "py_f.lfind" t t "python") (insert "\n"))
def lfind(l, elt):
try:
return l.index(elt)
except ValueError:
return -1
import os
import re
# --------------------------------------------------
# |||:sec:||| CONFIGURATION
# --------------------------------------------------
__all__ = []
__all_internal__ = []
# (progn (forward-line 1) (snip-insert "py.b.dbg.def" t t "python") (insert ""))
dbg_fwid = globals().get('dbg_fwid', 15)
# (progn (forward-line 1) (snip-insert "py.b.canonize.module" t t "python") (insert ""))
def _canonize_module_(module_or_name, full=None, drop=None):
if isstring(module_or_name):
module = sys.modules[module_or_name]
else:
module = module_or_name
module_name = module.__name__
# flag for __main__
_is_main_ = (module_name == '__main__')
if not hasattr(module, '_is_main_'):
module._is_main_ = _is_main_
if not full:
return _is_main_
# module file name -> canonical name
try:
mfile = module.__file__
except AttributeError:
return
canon_name_ = mfile
canon_name_ = os.path.basename(canon_name_)
canon_name_, _ext = os.path.splitext(canon_name_)
# adhoc compiliation xx_.py -> xx.py
if canon_name_.endswith('_') and not canon_name_.endswith('__'):
canon_name_ = canon_name_[:-1]
canon_name_ = re.sub('[^0-9A-Za-z_]+', '_', canon_name_)
# find parent module |:check:| distutils/pkg_resources?
mdir = os.path.abspath(os.path.dirname(mfile))
mparts = []
while mdir and os.path.exists(os.path.join(mdir, '__init__.py')):
mdir, pfx = os.path.split(mdir)
mparts.insert(0, pfx)
parent = '.'.join(mparts)
if canon_name_ != '__init__':
mparts.append(canon_name_)
if drop:
mparts = mparts[:-drop]
canon_name = '.'.join(mparts)
if module_name != canon_name:
if parent != canon_name or drop: # |:check:| why?
if parent:
# fix parent module
exec('import ' + parent)
if parent in (sys.modules):
setattr(sys.modules[parent], canon_name_, module)
sys.modules[canon_name] = module
module.__name__ = canon_name
# adjust module members
for t in dvalues(vars(module)):
try:
if '__module__' in vars(t) and t.__module__ == module_name:
t.__module__ = canon_name
except TypeError:
pass
return _is_main_
#_canonize_module_(__name__, __name__ == '__main__')
# (progn (forward-line 1) (snip-insert "py.b.strings" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.strclean" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.logging" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py.b.ordereddict" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.dbg.setup" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.project.libdir" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.sql.alchemy" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.main.sql.ws" t t "py") (insert "\n"))
# @:adhoc_run_time:@
#import adhoc # @:adhoc:@
# (progn (forward-line 1) (snip-insert "py.b.posix" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.os.system.sh" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.b.prog.path" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.line-loop" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.table_standalone" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py.wsrfid.pylons.imports" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py.main.wsgi.get.app" t t "python") (insert ""))
# (progn (forward-line 1) (snip-insert "py_wsrfid.config_delayed" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.wsrfid.config_translate_shortcuts" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_imports" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_datainit" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_jsmo.imports" t t "python") (insert "\n"))
import pyjsmo # @:adhoc:@
# (progn (forward-line 1) (snip-insert "py_jsmo.compat" t t "python") (insert "\n"))
from pyjsmo.compat import OrderedDict
from pyjsmo.compat import ucs, u8s, nts
from pyjsmo.compat import BytesIO, StringIO
# (progn (forward-line 1) (snip-insert "py_jsmo.result" t t "python") (insert "\n"))
from pyjsmo.result import ERR_WARNING, ERR_NONE, ERR_UNKNOWN
from pyjsmo.result import Result, IResult, vmsg
# (progn (forward-line 1) (snip-insert "py_jsmo.translate" t t "python") (insert "\n"))
from pyjsmo.translate import trans_identity, trans_string, trans_empty_null, trans_null_empty
from pyjsmo.translate import trans_int, trans_bool_int, trans_bool_check, trans_to_crlf, trans_from_crlf
from pyjsmo.translate import trans_list_space_comma_bar, trans_list_space_comma, trans_list_space_bar, trans_list_comma_bar, trans_list_bar
from pyjsmo.translate import parse_isodate, parse_isodate_naive, trans_date_str, trans_str_date
# (progn (forward-line 1) (snip-insert "py_jsmo.formatv" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_jsmo.quick" t t "python") (insert "\n"))
import datetime
try:
from urllib2 import URLError # as URLError
from urllib import urlopen # as urlopen
pass
except ImportError:
from urllib.error import URLError # as URLError
from urllib.request import urlopen # as urlopen
pass
from pyjsmo.config import ConfigIO, cfs, LConfigParser
from pyjsmo.config import config_from_rc_files, rc_string_from_config
import pyjsmo.tags
import pyjsmo.sections
# |||:here:|||
# --------------------------------------------------
# |||:sec:||| DATA
# --------------------------------------------------
# =====
# Title
# =====
# Subtitle
# --------
# Titles are underlined (or over-
# and underlined) with a printing
# nonalphanumeric 7-bit ASCII
# character. Recommended choices
# are "``= - ` : ' " ~ ^ _ * + # < >``".
# The underline/overline must be at
# least as long as the title text.
SECTION_UNDERLINE_CHAR_RX = '[!-/:-@[-`{-~]'
SNIP_RX = re.escape('|<-snip->|')
HEADER_CHARS = '-#=~.+'
SNAP_RX = re.escape('|<-sn') + '([' + HEADER_CHARS + 'a0-9])' + re.escape('p->|')
BULLET_RX = '( *([-+* ]|(?:[#]|[0-9]+)[.]) +)'
COMM_RX = re.escape('.. ')
COMM_BS_RX = COMM_RX + re.escape('\\')
# cannot make the backslash optional, since the substitution
# definition would be recognized as snippet section by :class:`SectPart`
SEC_RX = re.compile('^(' + COMM_BS_RX + ')?' + SNIP_RX)
ITM_RX = re.compile('^(' + COMM_RX + ')?' + BULLET_RX + SNIP_RX)
# backslash can be optional, since the substitution definition can be
# reliably detected in :meth:`resolve
REF_RX = re.compile('^(' + COMM_BS_RX + '?)?' + BULLET_RX + '?' + SNAP_RX)
FLAGS_RX = '[-]'
SEARCH_PATH_DOC = [
'@input_file_dir@',
'@here@',
]
SEARCH_PATH_RC = [
'@input_file_dir@/doc',
'@here@/doc',
]
SEARCH_PATH_RC.extend(SEARCH_PATH_DOC)
RC_FILES = [
'.doc-snip.rc.default',
'.doc-snip.rc',
]
# |||:here:|||
DOC_SNIPPET_TEST = r'''
.. \|<-snip->|
.. _Labeled Section Label:
--------------------------------------------------
:rem:`||:sec:||`\ Labeled Section
--------------------------------------------------
Section body filled with labeled stuff.
Section body filled with labeled stuff.
Section body filled with labeled stuff.
field: value
field: value
.. \|<-snip->|
field: value
field: value
.. \|<-snip->| -
--------------------------------------------------
:rem:`||:sec:||`\ Unlabeled Section
--------------------------------------------------
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
.. \|<-snip->|
.. \|<-snip->| named paragraph
Section body filled with named stuff.
Section body filled with named stuff.
Section body filled with named stuff.
.. \|<-snip->|
- |<-snip->| some item
item body filled with stuff.
item body filled with stuff.
.. \|<-snip->| item 1
* |<-snip->| some indented item
indented item body filled with stuff.
indented item body filled with stuff.
.. \|<-snip->| item 2
.. |<-snap->| named paragraph
- |<-snap->| see :ref:`Labeled Section Label`
- |<-sn1p->| see `Unlabeled Section`_
#. |<-snap->| item 2
#. |<-snap->| item 1
|<-sn1p->| item 2
|<-sn3p->| item 2
|<-sn3p->| item 1
|<-sn5p->| item 2
|<-sn5p->| item 1
|<-sn4p->| item 2
|<-sn6p->| item 2
'''.strip()
# |||:here:|||
# --------------------------------------------------
# |||:sec:||| CLASSES
# --------------------------------------------------
__all__.append('Section')
[docs]class Section(pyjsmo.sections.Section): # ||:cls:||
r"""Text section.
Behaves like a :class:`pyjsmo.sections.Section`.
The method :meth:`resolve` replaces snippet references with
snippets.
"""
_pyjsmo_versions = [
(1, {'bases': [0],
'order': ['is_snippet', ],
'defaults': OrderedDict((
('is_snippet', None),
)),
'amap': [],
'expand': None,
}),
]
def __init__(self, *args, **kwargs): # |:mth:|
super(Section, self).__init__(*args, **kwargs)
[docs] def resolve(self, snippets): # |:mth:|
r"""Resolve snippets in section body.
"""
_body = []
for _line in self.body:
_mo = REF_RX.search(_line)
if not _mo:
_body.append(_line)
continue
_title = _line[_mo.end(0):].strip()
if _title.startswith('replace::'):
# skip substitution definition
_body.append(_line)
continue
for _rx, _group in (('`([^`]*)`_', 1), (':ref:`([^`]*)`', 1)):
_tmo = re.search(_rx, _title)
if _tmo:
_title = _tmo.group(_group)
break
_snippet = snippets.get(_title.lower())
if _snippet is None:
printe(sformat("# |"":WRN:| warning: snippet `{0}` not found", _title))
_body.append(_line)
continue
_pfx = _mo.group(2) or ''
_pfx_len = len(_pfx)
_ref_type = _mo.group(3)
_tag_type = _mo.group(4)
if not _ref_type and _pfx_len:
_ref_type = ' '
_feat_no_item = _tag_type == '0'
if _feat_no_item:
_pfx = ''
_pfx_len = 0
_ref_type = ''
_tag_type = ''
# |:info:|
# >>> print("" in "st")
# True
# >>> print("" in ("s", "t"))
# False
_feat_bold_title = (_tag_type and _tag_type in '12')
_feat_definition_list = (_tag_type and _tag_type in '34')
_feat_field_list = (_tag_type and _tag_type in '56')
_feat_replace_bullet = (_tag_type and _tag_type in '246')
_add_indent_len = 0
_feat_title = _feat_bold_title
_feat_title_sep_line = False
_feat_title_delim = ''
if _feat_bold_title:
_feat_title_delim = '**'
_feat_title_sep_line = True
if _feat_definition_list or _feat_field_list:
_feat_title = True
if _feat_field_list:
_feat_title_delim = ':'
_add_indent_len = 2
if _feat_replace_bullet:
if _ref_type == ' ':
_pfx = _pfx[:-2]
else:
_pfx = _pfx.rstrip()[:-1]
_pfx_len = len(_pfx)
_is_item = _ref_type or (_tag_type and _tag_type in '12345')
if _debug:
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "_mo.groups", (_mo.groups())))
# |||||:here:||||| reference features
_indent = ''.join((' ' for _i in xrange(_pfx_len)))
_body_indent = _indent + ''.join((' ' for _i in xrange(_add_indent_len)))
if not _is_item:
_body.append('')
_body.append(_indent + '.. Source: ' + _line)
if _snippet.label and not _snippet.label_done:
_body.append('')
_body.append(_indent + _snippet.label)
_snippet.label_done = True
if _snippet.header:
if _tag_type and _tag_type in HEADER_CHARS:
_header = list(_snippet.header)
_underline_len = len(_header[-1])
_underline = ''.join((_tag_type for _i in xrange(_underline_len)))
_header[-1] = _underline
if len(_header) > 2:
_header[0] = _underline
else:
_header = _snippet.header
_body.append('')
_body.extend((_indent + _l for _l in _header))
_body.append('')
if _feat_title:
_body.append(_pfx + _feat_title_delim + _snippet.title + _feat_title_delim)
if _feat_title_sep_line:
_body.append('')
_pfx = _body_indent
_prefixes = [_pfx]
_body.extend((((_prefixes and _prefixes.pop()) or _body_indent) + _l for _l in _snippet.body))
if _is_item:
_body.append('')
_body.append(_body_indent + '.. Source: ' + _line)
_body.append('')
self.body = _body
__all__.append('Snippet')
[docs]class Snippet(Section): # ||:cls:||
r"""Snippet section.
Behaves like a standard :class:`Section` instance until method
:meth:`prepare` is called, which converts the section to a
snippet.
"""
_pyjsmo_versions = [
(1, {'bases': [0],
'order': ['title', 'label', 'header', 'drop', 'titles', 'pfx', 'label_done'],
'defaults': OrderedDict((
('is_snippet', True),
('title', None),
('label', None),
('drop', None),
('titles', []),
('pfx', ''),
('label_done', None),
)),
'amap': [],
'expand': None,
}),
]
def __init__(self, *args, **kwargs): # |:mth:|
super(Snippet, self).__init__(*args, **kwargs)
self.prepare()
[docs] def reset(self): # |:mth:|
r"""Reset snippet for new resolution.
"""
self.label_done = False
[docs] def prepare(self, section=None): # |:mth:|
r"""Prepare snippet.
"""
if section is not None:
self.update(section)
elif not self.start and not self.end and not self.body:
# empty snippet
return
self.body = list(self.body)
_pfx = self.pfx or ''
_pfx_len = len(_pfx)
_titles = self.titles
# handle item snippets
if _pfx_len:
self.body = [_l[_pfx_len:] for _l in self.body]
self.end = self.end[_pfx_len:]
try:
_line = self.body[0]
_mo = SEC_RX.search(_line)
if _mo:
self.body[0] = _line[_mo.end(0):].lstrip()
except:
pass
# snippet flags and explicit title
for _marker in (self.start or '', self.end or ''):
_mo = SEC_RX.search(_marker)
if _mo:
_flag_title = _marker[_mo.end(0):].strip()
_mo = re.match('(' + FLAGS_RX + ')' + '( +|$)', _flag_title)
if _mo:
_flags = _mo.group(1)
_flag_title = _flag_title[_mo.end(0):]
if '-' in _flags:
self.drop = True
if _flag_title:
_titles.append(_flag_title)
# detect first label and/or first section
_label_indx = None
_label_title = None
_header_start = None
_header_end = None
_header_title = None
_body = self.body
_body_len = len(_body)
_body_bound = _body_len - 2
for _indx, _line in enumerate(_body):
if not _line:
continue
# detect label
_mo = re.match('[.][.] _(.*): *$', _line)
if _mo:
if _label_indx is None:
_label_indx = _indx
if _label_title is None:
_label_title = re.sub('`$', '', re.sub('^`', '', _mo.group(1))).strip()
continue
# |||||:here:||||| detect section
_hchar = _line[0]
if re.search(SECTION_UNDERLINE_CHAR_RX, _hchar):
_underline_rx = '^' + re.escape(_hchar) + '+$'
_mo = re.search(_underline_rx, _line)
if _mo:
_line_len = len(_line)
if _indx < _body_bound and _body[_indx + 1]:
_underline = _body[_indx + 2]
if re.search(_underline_rx, _underline):
_underline_len = len(_underline)
if _line_len != _underline_len:
printe(sformat("# |"":WRN:| warning: over/underline do not match:\n# {0}\n# {1}", _line, _underline))
if len(_body[_indx + 1]) > max(_line_len, _underline_len):
printe(sformat("# |"":WRN:| warning: over/underline too short:\n# {0}\n# {1}\n# {2}", _line, _body[_indx + 1], _underline))
_header_start = _indx
_header_end = _indx + 3
break
if _indx > 0 and _body[_indx - 1]:
if len(_body[_indx - 1]) > _line_len:
printe(sformat("# |"":WRN:| warning: underline too short:\n# {0}\n# {1}", _body[_indx + 1], _line))
_header_start = _indx - 1
_header_end = _indx + 1
break
# header must be removed before label
_header = None
if _header_start is not None:
_header = _body[_header_start:_header_end]
_line = _body[_header_end - 2]
_mo = re.match(':rem:`[|]+:sec:[|]+`[\\\\] ', _line)
if _mo:
_header_title = _line[_mo.end(0):].strip()
else:
_header_title = _line
del(self.body[_header_start:_header_end])
self.header = _header
_label = None
if _label_indx is not None:
_label = self.body[_label_indx]
del(self.body[_label_indx])
self.label = _label
if _header_title:
_titles.append(_header_title)
if _label_title:
_titles.append(_label_title)
if _titles:
self.title = _titles[0]
self.start = None
self.end = None
self.strip()
return
[docs] def dump(self, file=None): # |:mth:|
r"""Dump snippet.
"""
if file is None:
file = sys.stderr
_title = self.title or '<unnamed document snippet>'
_titles = ' | '.join(self.titles or (_title, ))
if self.drop:
_flag = '- '
else:
_flag = ''
printf(sformat(".. \\|<-snip->| {0}{1}", _flag, _titles), file=file)
if self.label:
printf(self.label, file=file)
if self.header:
printf('\n'.join(self.header), file=file)
printf(self, file=file)
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.meth" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -2) (insert "\n") (snip-insert "py.s.property" t t "py") (backward-symbol-tag 1 "fillme" "::"))
__all__.append('Document')
[docs]class Document(pyjsmo.PyJsMo): # ||:cls:||
r"""
.. \|||:here:|||
Initialize document, parse text or load from file handle/filename::
_doc = Document()
_doc.parse(TEXT)
_doc.load(file_handle)
_doc.load(filename)
Initialize document from filename (automatically loads file)::
_doc = Document((1, 'filename'))
Initialize document from filename and text. Text is parsed and
file is not loaded:
>>> _doc = Document((1, 'filename', DOC_SNIPPET_TEST))
>>> printf(_doc) #doctest: +ELLIPSIS
{
"filename": "filename",
"text": ".. \\|<-snip->|\n.. _Labeled Section Label:... |<-sn4p->| item 2\n |<-sn6p->| item 2",
"partition": {
"start_rx": {...},
"end_rx": {...},
"this": [],
"that": [],
"sections": [
...
]
},
"body": {
"start_rx": null,
"end_rx": null,
"this": [],
"that": [],
"sections": [
{
"start": ".. \\|<-snip->|",
"body": [
".. _Labeled Section Label:",
"",
"--------------------------------------------------",
":rem:`||:sec:||`\\ Labeled Section",
"--------------------------------------------------",
"",
"Section body filled with labeled stuff.",
"Section body filled with labeled stuff.",
"Section body filled with labeled stuff.",
"",
"field: value",
"field: value"
],
"end": ".. \\|<-snip->|",
"fsep": ": ",
"is_snippet": true,
"title": null,
"label": null,
"header": null,
"drop": null,
"titles": [
"Labeled Section",
"Labeled Section Label"
],
"pfx": "",
"label_done": null
},
{
"start": null,
"body": [
"",
"field: value",
"field: value",
""
],
"end": null,
"fsep": ": ",
"is_snippet": null
},
{
"start": null,
"body": [
""
],
"end": null,
"fsep": ": ",
"is_snippet": null
},
{
"start": ".. \\|<-snip->| named paragraph",
"body": [
"",
"Section body filled with named stuff.",
"Section body filled with named stuff.",
"Section body filled with named stuff.",
""
],
"end": ".. \\|<-snip->|",
"fsep": ": ",
"is_snippet": true,
"title": null,
"label": null,
"header": null,
"drop": null,
"titles": [
"named paragraph"
],
"pfx": "",
"label_done": null
},
{
"start": null,
"body": [
""
],
"end": null,
"fsep": ": ",
"is_snippet": null
},
{
"start": null,
"body": [
"- |<-snip->| some item",
"",
" item body filled with stuff.",
" item body filled with stuff."
],
"end": " .. \\|<-snip->| item 1",
"fsep": ": ",
"is_snippet": "-",
"title": null,
"label": null,
"header": null,
"drop": null,
"titles": [
"item 1"
],
"pfx": "- ",
"label_done": null
},
{
"start": null,
"body": [
""
],
"end": null,
"fsep": ": ",
"is_snippet": null
},
{
"start": null,
"body": [
" * |<-snip->| some indented item",
"",
" indented item body filled with stuff.",
" indented item body filled with stuff."
],
"end": " .. \\|<-snip->| item 2",
"fsep": ": ",
"is_snippet": "*",
"title": null,
"label": null,
"header": null,
"drop": null,
"titles": [
"item 2"
],
"pfx": " * ",
"label_done": null
},
{
"start": null,
"body": [
"",
".. |<-snap->| named paragraph",
"",
"- |<-snap->| see :ref:`Labeled Section Label`",
"- |<-sn1p->| see `Unlabeled Section`_",
"",
" #. |<-snap->| item 2",
" #. |<-snap->| item 1",
"",
" |<-sn1p->| item 2",
"",
" |<-sn3p->| item 2",
" |<-sn3p->| item 1",
"",
" |<-sn5p->| item 2",
" |<-sn5p->| item 1",
"",
" |<-sn4p->| item 2",
" |<-sn6p->| item 2"
],
"end": null,
"fsep": ": ",
"is_snippet": null
}
]
},
"snippets": {
"start_rx": null,
"end_rx": null,
"this": [],
"that": [],
"sections": [
{
"start": null,
"body": [
"Section body filled with labeled stuff.",
"Section body filled with labeled stuff.",
"Section body filled with labeled stuff.",
"",
"field: value",
"field: value"
],
"end": null,
"fsep": ": ",
"is_snippet": true,
"title": "Labeled Section",
"label": null,
"header": [
"--------------------------------------------------",
":rem:`||:sec:||`\\ Labeled Section",
"--------------------------------------------------"
],
"drop": null,
"titles": [
"Labeled Section",
"Labeled Section Label"
],
"pfx": "",
"label_done": null
},
{
"start": null,
"body": [
"Section body filled with unlabeled stuff.",
"Section body filled with unlabeled stuff.",
"Section body filled with unlabeled stuff."
],
"end": null,
"fsep": ": ",
"is_snippet": true,
"title": "Unlabeled Section",
"label": null,
"header": [
"--------------------------------------------------",
":rem:`||:sec:||`\\ Unlabeled Section",
"--------------------------------------------------"
],
"drop": true,
"titles": [
"Unlabeled Section"
],
"pfx": "",
"label_done": null
},
{
"start": null,
"body": [
"Section body filled with named stuff.",
"Section body filled with named stuff.",
"Section body filled with named stuff."
],
"end": null,
"fsep": ": ",
"is_snippet": true,
"title": "named paragraph",
"label": null,
"header": null,
"drop": null,
"titles": [
"named paragraph"
],
"pfx": "",
"label_done": null
},
{
"start": null,
"body": [
"some item",
"",
"item body filled with stuff.",
"item body filled with stuff."
],
"end": null,
"fsep": ": ",
"is_snippet": "-",
"title": "item 1",
"label": null,
"header": null,
"drop": null,
"titles": [
"item 1"
],
"pfx": "- ",
"label_done": null
},
{
"start": null,
"body": [
"some indented item",
"",
"indented item body filled with stuff.",
"indented item body filled with stuff."
],
"end": null,
"fsep": ": ",
"is_snippet": "*",
"title": "item 2",
"label": null,
"header": null,
"drop": null,
"titles": [
"item 2"
],
"pfx": " * ",
"label_done": null
}
]
},
"resolved": null
}
.. \|||:here:|||
>>> _doc.dump_snippets(file=sys.stdout)
..
.. --------------------------------------------------
.. \|<-snip->| Labeled Section | Labeled Section Label
--------------------------------------------------
:rem:`||:sec:||`\ Labeled Section
--------------------------------------------------
Section body filled with labeled stuff.
Section body filled with labeled stuff.
Section body filled with labeled stuff.
<BLANKLINE>
field: value
field: value
..
.. --------------------------------------------------
.. \|<-snip->| - Unlabeled Section
--------------------------------------------------
:rem:`||:sec:||`\ Unlabeled Section
--------------------------------------------------
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
..
.. --------------------------------------------------
.. \|<-snip->| named paragraph
Section body filled with named stuff.
Section body filled with named stuff.
Section body filled with named stuff.
..
.. --------------------------------------------------
.. \|<-snip->| item 1
some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
..
.. --------------------------------------------------
.. \|<-snip->| item 2
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
.. \|||:here:|||
>>> printf(str(_doc.partition.sections) == DOC_SNIPPET_TEST)
True
>>> printf(str(_doc.body.sections) == DOC_SNIPPET_TEST)
False
.. \|||:here:|||
>>> _resolved = _doc.resolve()
>>> printf(str(_resolved.sections))
.. \|<-snip->|
.. _Labeled Section Label:
<BLANKLINE>
--------------------------------------------------
:rem:`||:sec:||`\ Labeled Section
--------------------------------------------------
<BLANKLINE>
Section body filled with labeled stuff.
Section body filled with labeled stuff.
Section body filled with labeled stuff.
<BLANKLINE>
field: value
field: value
.. \|<-snip->|
<BLANKLINE>
field: value
field: value
<BLANKLINE>
<BLANKLINE>
.. \|<-snip->| named paragraph
<BLANKLINE>
Section body filled with named stuff.
Section body filled with named stuff.
Section body filled with named stuff.
<BLANKLINE>
.. \|<-snip->|
<BLANKLINE>
- |<-snip->| some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
.. \|<-snip->| item 1
<BLANKLINE>
* |<-snip->| some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
.. \|<-snip->| item 2
<BLANKLINE>
<BLANKLINE>
.. Source: .. |<-snap->| named paragraph
<BLANKLINE>
Section body filled with named stuff.
Section body filled with named stuff.
Section body filled with named stuff.
<BLANKLINE>
<BLANKLINE>
- Section body filled with labeled stuff.
Section body filled with labeled stuff.
Section body filled with labeled stuff.
<BLANKLINE>
field: value
field: value
<BLANKLINE>
.. Source: - |<-snap->| see :ref:`Labeled Section Label`
<BLANKLINE>
- **Unlabeled Section**
<BLANKLINE>
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
<BLANKLINE>
.. Source: - |<-sn1p->| see `Unlabeled Section`_
<BLANKLINE>
<BLANKLINE>
#. some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: #. |<-snap->| item 2
<BLANKLINE>
#. some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
<BLANKLINE>
.. Source: #. |<-snap->| item 1
<BLANKLINE>
<BLANKLINE>
**item 2**
<BLANKLINE>
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn1p->| item 2
<BLANKLINE>
<BLANKLINE>
item 2
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn3p->| item 2
<BLANKLINE>
item 1
some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn3p->| item 1
<BLANKLINE>
<BLANKLINE>
:item 2:
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn5p->| item 2
<BLANKLINE>
:item 1:
some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn5p->| item 1
<BLANKLINE>
<BLANKLINE>
item 2
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn4p->| item 2
<BLANKLINE>
:item 2:
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
<BLANKLINE>
.. Source: |<-sn6p->| item 2
<BLANKLINE>
.. \|||:here:|||
"""
_pyjsmo_versions = [
(1, {'bases': [0],
'order': ['filename', 'text', 'partition', 'body', 'snippets', 'resolved'],
'defaults': OrderedDict((
('filename', None),
('text', None),
('partition', None),
('body', None),
('snippets', None),
)),
'amap': [],
'expand': None,
}),
]
def __init__(self, *args, **kwargs): # |:mth:|
super(Document, self).__init__(*args, **kwargs)
if self.text is not None or self.partition is not None:
self.parse(self.text, self.partition)
elif self.filename:
self.load(self.filename)
else:
self.parse()
[docs] def parse(self, text=None, partition=None): # |:mth:|
r"""Parse document for document snippets.
"""
if self.body is not None:
return
if text is None:
if partition is None:
text = ''
else:
text = str(partition)
self.text = text
if partition is None:
partition = pyjsmo.sections.SectPart((1, SEC_RX, SEC_RX))
partition.parse(text)
partition.this = []
partition.that = []
self.partition = partition
# detect document snippets
_sections = partition.sections.__class__()
for _sec in partition.sections:
# mark section snippets
if _sec.start is not None:
_nsec = Snippet()
_nsec.update(_sec)
_sections.append(_nsec)
continue
# detect item document snippets
_nsec = Section()
_body = _nsec.body
_itm_end_rx = None
_pfx_len = 0
for _line in _sec.body:
if _itm_end_rx:
_mo = _itm_end_rx.search(_line[_pfx_len:])
if _mo:
_nsec.end = _line
_sections.append(_nsec)
_nsec = Section()
_body = _nsec.body
_itm_end_rx = None
_pfx_len = 0
continue
else:
_mo = ITM_RX.search(_line)
if _mo:
_type = _mo.group(3)
_pfx = _mo.group(2)
_pfx_len = len(_pfx)
if _body:
_sections.append(_nsec)
_nsec = Snippet()
_nsec.is_snippet = _type
_nsec.pfx = _pfx
_body = _nsec.body
_itm_end_rx = SEC_RX
_body.append(_line)
if _body:
_sections.append(_nsec)
partition.sections = _sections
# construct body and snippets
self.body = body = pyjsmo.sections.SectPart()
self.snippets = snippets = pyjsmo.sections.SectPart()
for _sec in partition.sections:
if not _sec.is_snippet:
body.sections.append(_sec)
continue
_snippet = Snippet()
_snippet.prepare(_sec)
if not _snippet.drop:
_snippet.label = None
body.sections.append(_sec)
snippets.sections.append(_snippet)
[docs] def load(self, file_or_name): # |:mth:|
r"""Load document from file.
:param file_or_name: file handle or filename.
"""
if not isstring(file_or_name):
_filename = self.filename
_fh = file_or_name
_do_close = False
else:
_filename = file_or_name
if _filename == '-':
_fh = sys.stdin
_do_close = False
else:
_fh = None
_filename = re.sub('^file:/+(?i)', '/', _filename)
if os.path.exists(_filename):
_fh = open(_filename, 'rb')
elif re.match('[^:/]+:/', _filename):
try:
_fh = urlopen(_filename)
except:
(_t, _e, _tb) = sys.exc_info()
_msg = sformat('{0}: {1}', _t.__name__, _e)
printe(sformat("# ||"":ERR:|| error: cannot open `{0}`: {1}", _filename, _msg))
del(_tb)
raise
_do_close = _fh is not None
if _fh is None:
raise IOError(sformat("# ||"":ERR:|| error: could not open {0}", _filename))
self.clear()
self.filename = _filename
self.parse(_fh.read())
if _do_close:
_fh.close()
[docs] def register_snippets_with(self, snippets, include=None): # |:mth:|
r"""Register document snippets in snippets dict.
:param snippets: snippets dictionary.
"""
for _snippet in self.snippets.sections:
_title = _snippet.title
if not _title:
printe(sformat("# |"":WRN:| warning: snippet without title ignored {0}", ''))
continue
if include:
_snippet.label = None
for _key in (_t.lower() for _t in set(_snippet.titles)):
if _key in snippets:
printe(sformat("# |"":WRN:| warning: snippet `{0}` already defined ", _key))
continue
snippets[_key] = _snippet
return snippets
[docs] def map_snippets(self, include=None): # |:mth:|
r"""Get document snippets dictionary.
"""
return self.register_snippets_with(OrderedDict(), include)
[docs] def resolve(self, snippets=None): # |:mth:|
r"""Resolve snippets in document.
:returns: :class:`pyjsmo.sections.SectPart` instance with resolved body.
:param snippets: snippet section dictionary. I None, the document snippets are
"""
if snippets is None:
snippets = self.map_snippets()
self.resolved = _resolved = pyjsmo.sections.SectPart((1, SEC_RX, SEC_RX))
_sections = _resolved.sections
for _section in self.body.sections:
_nsec = _section.copy()
_sections.append(_nsec)
_nsec.resolve(snippets)
return _resolved
[docs] def dump_snippets(self, file=None): # |:mth:|
r"""Dump document snippets.
"""
if file is None:
file = sys.stderr
for _snippet in self.snippets.sections:
printf('..', file=file)
printf(".. --------------------------------------------------")
_snippet.dump(file=file)
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.meth" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -2) (insert "\n") (snip-insert "py.s.property" t t "py") (backward-symbol-tag 1 "fillme" "::"))
__all__.append('Documentation')
[docs]class Documentation(pyjsmo.PyJsMo): # ||:cls:||
r"""
>>> _docs = Documentation()
>>> _docs.register(Document((1, 'doc_snippet_test.rst', DOC_SNIPPET_TEST)))
True
>>> _docs.dump_snippets(file=sys.stdout)
..
.. --------------------------------------------------
.. \|<-snip->| Labeled Section | Labeled Section Label
--------------------------------------------------
:rem:`||:sec:||`\ Labeled Section
--------------------------------------------------
Section body filled with labeled stuff.
Section body filled with labeled stuff.
Section body filled with labeled stuff.
<BLANKLINE>
field: value
field: value
..
.. --------------------------------------------------
.. \|<-snip->| - Unlabeled Section
--------------------------------------------------
:rem:`||:sec:||`\ Unlabeled Section
--------------------------------------------------
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
Section body filled with unlabeled stuff.
..
.. --------------------------------------------------
.. \|<-snip->| named paragraph
Section body filled with named stuff.
Section body filled with named stuff.
Section body filled with named stuff.
..
.. --------------------------------------------------
.. \|<-snip->| item 1
some item
<BLANKLINE>
item body filled with stuff.
item body filled with stuff.
..
.. --------------------------------------------------
.. \|<-snip->| item 2
some indented item
<BLANKLINE>
indented item body filled with stuff.
indented item body filled with stuff.
"""
_pyjsmo_versions = [
(1, {'bases': [0],
'order': ['format', 'docs', 'includes', 'snippets'],
'defaults': OrderedDict((
('format', None),
('docs', []),
('includes', []),
('snippets', OrderedDict()),
)),
'amap': [],
'expand': None,
}),
]
def __init__(self, *args, **kwargs): # |:mth:|
super(Documentation, self).__init__(*args, **kwargs)
[docs] def register(self, doc_or_filename, include=None): # |:mth:|
r"""
:returns: self for chaining.
"""
if isstring(doc_or_filename):
_doc = Document((1, doc_or_filename))
else:
_doc = doc_or_filename
if include:
self.includes.append(_doc)
else:
self.docs.append(_doc)
snippets = self.snippets
_doc.register_snippets_with(snippets, include)
return True
[docs] def dump_snippets(self, file=None): # |:mth:|
r"""
:returns: self for chaining.
"""
if file is None:
file = sys.stderr
_seen = set()
for _key, _snip in ditems(self.snippets):
if _snip in _seen:
continue
_seen.add(_snip)
printf('..', file=file)
printf(".. --------------------------------------------------", file=file)
_snip.dump(file=file)
[docs] def resolve(self, snippets=None, continued=None): # |:mth:|
r"""Resolve snippets in all registered documents.
"""
if snippets is None:
snippets = self.snippets
if not continued:
for _snippet in dvalues(snippets):
_snippet.reset()
for _doc in self.docs:
_doc.resolve(snippets)
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.meth" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -2) (insert "\n") (snip-insert "py.s.property" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.meth" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -2) (insert "\n") (snip-insert "py.s.property" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.class" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# --------------------------------------------------
# |||:sec:||| FUNCTIONS
# --------------------------------------------------
# (progn (forward-line 1) (snip-insert "py_f.search_path" t t "python" " --key xwith_docstrings --key xwith_all_append") (insert "\n"))
class SimpleSubst(object): # ||:cls:||
def __init__(self):
self.replacements = dict()
def add(self, placeholder, replacement):
self.replacements[placeholder] = replacement
def replace(self, string):
while True:
_string = string
for _ph, _rp in ditems(self.replacements):
string = string.replace(_ph, _rp)
if _string == string:
break
return string
def search_path_expand(search_path, replacements=None, reverse=None): # ||:fnc:||
if replacements is None:
replacements = SimpleSubst()
x_search_path = []
for _sd in (replacements.replace(_d) for _d in reversed(search_path)):
if _sd not in x_search_path:
x_search_path.append(_sd)
if not reverse:
return list(reversed(x_search_path))
return x_search_path
def search_candidates(search_path, files): # ||:fnc:||
candidates = []
for _file in files:
if not os.path.isabs(_file):
_candidates = [os.path.join(_sd, _file) for _sd in search_path]
else:
_candidates = [_file]
for _candidate in _candidates:
if _candidate not in candidates:
candidates.append(_candidate)
return candidates
def search_files(search_path, files): # ||:fnc:||
return [_file for _file in search_candidates(search_path, files) if os.path.exists(_file)]
def search_first(search_path, file_): # ||:fnc:||
try:
return search_files(search_path, [file_])[0]
except IndexError:
return None
def search_last(search_path, file_): # ||:fnc:||
try:
return search_files(search_path, [file_])[-1]
except IndexError:
return None
# (progn (forward-line -1) (insert "\n") (snip-insert "py.s.func" t t "py") (backward-symbol-tag 1 "fillme" "::"))
# (progn (forward-line 1) (snip-insert "py_wsrfid.customization" t t "python" " --key cust_delayed_skipx") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_setup_sql" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_id_maps" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.dba_commands_init" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.wsrfid.module.route" t t "py") (insert ""))
# --------------------------------------------------
# |||:sec:||| UTILITIES
# --------------------------------------------------
# (progn (forward-line 1) (snip-insert "py.wsrfid.dispatch.request" t t "py") (insert ""))
# (progn (forward-line 1) (snip-insert "py.f.findfile" t t "py") (insert ""))
# (progn (forward-line 1) (snip-insert "py_f.add_prefix_indent" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.c.placeholder.template" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.c.key.hash.ordered.dict" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.c.progress" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.hl" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.single.quote" t t "py") (insert "\n"))
def single_quote(string, enclose=True):
if enclose:
pfx="'"
sfx="'"
else:
pfx=''
sfx=''
return ''.join((pfx, re.sub("'", """'\\''""", string), sfx))
# (progn (forward-line 1) (snip-insert "py.f.remove.match" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.printenv" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.uname.s" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_f.decoded_email_headers" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_f.print_utf8" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.printe" t t "py") (insert ""))
def printe_(*args, **kwargs):
kwargs['file'] = kwargs.get('file', sys.stderr)
printf(*args, **kwargs)
if 'printe' not in globals(): # or globals().get('_is_main_', (__name__ == '__main__')):
printe = printe_
printd = printe_
printw = printe_
printx = printe_
# (progn (forward-line 1) (snip-insert "py.f.dbg.squeeze" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.dbg.indent" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.quick.dump" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_b.all.reverse" t t "python") (insert "\n"))
if '__all_internal__' in globals():
import sys
if 'sphinx.directives' in sys.modules:
__all__[:0] = __all_internal__
__all_internal__ = list(reversed(__all_internal__))
__all__ = list(reversed(__all__))
def run(parameters): # ||:fnc:||
"""Application runner, when called as __main__."""
# (progn (forward-line 1) (snip-insert "py.bf.sql.ws" t t "py") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.bf.file.arg.loop" t t "py") (insert "\n"))
documentation = Documentation()
_rc_files = []
if not parameters.no_defaults:
_rc_files.extend(RC_FILES)
_rc_files.extend(parameters.config)
if parameters.args:
input_file_dir = os.path.dirname(parameters.args[0]) or '.'
else:
input_file_dir = '.'
here = '.'
# |||:here:|||
_path_replacements = pyjsmo.tags.SubstAt()
_path_replacements.add('input_file_dir', os.path.abspath(input_file_dir))
_path_replacements.add('here', os.path.abspath(here))
search_path_rc = search_path_expand(SEARCH_PATH_RC, _path_replacements)
rc_files = search_candidates(search_path_rc, _rc_files)
search_path_doc = search_path_expand(SEARCH_PATH_DOC, _path_replacements, True)
if _debug:
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "search_path_rc", (search_path_rc)))
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "search_path_doc", (search_path_doc)))
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "_rc_files", (_rc_files)))
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "rc_files", (rc_files)))
CFG = config_from_rc_files(rc_files, cfg=LConfigParser())
CFGS = CFG['DEFAULT']
# |||:here:|||
opt_force = parameters.force
if opt_force is None:
opt_force = trans_bool_int(CFGS.get('force', 0))
opt_format = parameters.format
if opt_format is None:
opt_format = CFGS.get('format', None)
if opt_format is None:
opt_format = '{dir}/{base}-x{ext}'
def split_non_blank_lines(value):
return [_l for _l in value.strip().splitlines() if _l.strip()]
opt_include = []
opt_include.extend(parameters.include)
opt_include.extend(split_non_blank_lines(CFGS.get('include', '')))
opt_replace = []
opt_replace.extend(split_non_blank_lines(CFGS.get('replace', '')))
opt_replace.extend(parameters.replace)
replacements = pyjsmo.tags.SubstAt()
if _debug:
printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "opt_replace", (opt_replace)))
for _replace_def in opt_replace:
try:
_what, _with = _replace_def.split('=', 1)
except ValueError:
printe(sformat("# ||"":ERR:|| error: invalid replacement definition `{0}` in `{1}`", _replace_def, opt_replace))
return 1
replacements.add(_what, _with)
filenames = parameters.args
if len(filenames) == 0:
filenames.append('-')
for _filename in opt_include:
if not documentation.register(
search_first(search_path_doc, _filename) or _filename,
include=True):
continue
for _filename in filenames:
if not documentation.register(_filename):
continue
# |:here:|
documentation.resolve()
if _debug:
printe("# --------------------------------------------------")
printe(sformat("# ||"":sec:|| Snippets{0}", ""))
printe("# --------------------------------------------------")
documentation.dump_snippets()
printe("# --------------------------------------------------")
printe(sformat("# |||"":LOG:||| {date} Resolved{0}", "", date=datetime.datetime.now()))
printe("# --------------------------------------------------")
for _doc in documentation.docs:
_path = _doc.filename
_dir = os.path.dirname(_path) or '.'
_file = os.path.basename(_path)
_base, _ext = os.path.splitext(_file)
_sbase, _sext = os.path.splitext(_base)
_kwargs = dict((
('path', _path),
('file', _file),
('dir', _dir),
('base', _base),
('ext', _ext),
('sbase', _sbase),
('sext', _sext),
))
output_name = sformat(opt_format, **_kwargs)
if _debug:
printe("# --------------------------------------------------")
printe(sformat("# ||"":sec:|| Document `{0}` => `{1}`", _doc.filename, output_name))
printe("# --------------------------------------------------")
doc_text = replacements.replace(str(_doc.resolved.sections))
if output_name == '-':
printf(doc_text)
else:
if not opt_force and os.path.exists(output_name):
printe(sformat("# ||"":ERR:|| error: output file `{0}` exists", output_name))
continue
with open(output_name, 'w') as _fh:
printf(doc_text, file=_fh)
if parameters.convert:
_cmd = sformat("sphinx-readme.sh --format {0} {1}", parameters.convert, single_quote(output_name))
os.system(_cmd)
#printe(sformat("# "":DBG: {1:<{0}s}: ]{2!s}[", dbg_fwid, "DONE", ('DONE')))
# |||:here:|||
# (progn (forward-line 1) (snip-insert "py.wsrfid.wsuvv.run" t t "py" " --key py_wsrfid.wsuvv_run --key skip_for_new") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py_shell.run" t t "python") (insert "\n"))
# from pyjsmo.result import Result, IResult, ERR_NONE
# result = IResult()
# |:here:|
return
# result.report()
# return max(result.error, ERR_NONE)
# --------------------------------------------------
# |||:sec:||| MAIN
# --------------------------------------------------
_quiet = False
_verbose = False
_debug = False
# (progn (forward-line 1) (snip-insert "py_f.argparse_callbacks" t t "python") (insert "\n"))
_argparse_have_sub_commands = False
def _argparse_begin(parser, context=None): # ||:fnc:||
r"""
:returns: parser
"""
if context is None:
context = globals()
# |:here:|
parser.add_argument(
'--force', action='store_true',
default=None, help='overwrite existing files.')
parser.add_argument(
'--no-defaults', action='store_true',
default=None, help='do not read default configuration files.')
parser.add_argument(
'-c', '--config', action='append', type=str, metavar='CFG',
default=[], help='add file to list of configuration files.')
parser.add_argument(
'-i', '--include', action='append', type=str, metavar='INC',
default=[], help='add include document to parse for snippets.'
' The document is not resolved.')
parser.add_argument(
'-r', '--replace', action='append', type=str, metavar='REPL',
default=[], help='add replacement `WHAT=WITH`.'
' `@WHAT@` is replaced with `WITH` after resolving snippets.')
parser.add_argument(
'-f', '--format', action='store', type=str, metavar='FMT',
default=None, help='format for output documents.'
' Default: `{dir}/{base}-x{ext}`.'
' Placeholders: `path`, `dir`, `file`, `base`, `ext`, `sext`.'
' If format is `-`, standard output is used.')
parser.add_argument(
'--html', action='store_const', const='singlehtml', dest='convert',
default=None, help='convert to HTML with sphinx-readme.sh(1)')
parser.add_argument(
'--pdf', action='store_const', const='pdf', dest='convert',
default=None, help='convert to PDF with sphinx-readme.sh(1)')
return parser
def _argparse_end(parser, context=None): # ||:fnc:||
r"""
:returns: parser
"""
if context is None:
context = globals()
# |:here:|
return parser
# (progn (forward-line 1) (snip-insert "py_main.py" t t "python") (insert "\n"))
# (progn (forward-line 1) (snip-insert "py.f.setdefaultencoding" t t "py") (insert "\n"))
#file_encoding_is_clean = False
def setdefaultencoding(encoding=None, quiet=False, context=None):
if context is None:
context = globals()
if context.get('file_encoding_is_clean'):
return
if encoding is None:
encoding='utf-8'
try:
isinstance('', basestring)
if not hasattr(sys, '_setdefaultencoding'):
if not quiet:
printf('''\
Add this to /etc/python2.x/sitecustomize.py,
or put it in local sitecustomize.py and adjust PYTHONPATH=".:${PYTHONPATH}"::
try:
import sys
setattr(sys, '_setdefaultencoding', getattr(sys, 'setdefaultencoding'))
except AttributeError:
pass
Running with reload(sys) hack ...
''', file=sys.stderr)
reload(sys)
setattr(sys, '_setdefaultencoding', getattr(sys, 'setdefaultencoding'))
sys._setdefaultencoding(encoding)
except NameError:
# python3 already has utf-8 default encoding ;-)
pass
def main(argv=None, context=None): # ||:fnc:||
if argv is None:
argv = sys.argv
if context is None:
context = globals()
context.get(
'setup_logger', globals().get(
'setup_logger', lambda *args: None))(context, True)
try:
import argparse
except ImportError:
printe('error: argparse missing. Try `easy_install argparse`.')
sys.exit(1)
parser = argparse.ArgumentParser(add_help=False)
# parser.add_argument('--sum', dest='accumulate', action='store_const',
# const=sum, default=max,
# help='sum the integers (default: find the max)')
# |:opt:| add options
context.get('_argparse_begin', lambda _p, *_args: _p)(parser, context)
parser.add_argument(
'-q', '--quiet', action='store_const', const=-2,
dest='debug', default=0, help='suppress warnings')
parser.add_argument(
'-v', '--verbose', action='store_const', const=-1,
dest='debug', default=0, help='verbose test output')
parser.add_argument(
'-d', '--debug', nargs='?', action='store', type=int, metavar='NUM',
default = 0, const = 1,
help='show debug information')
parser.add_argument(
'-t', '--test', action='store_true',
help='run doc tests')
class AdHocAction(argparse.Action):
options = ('implode', 'setup', 'explode', 'extract', 'template', 'eide')
def __call__(self, parser, namespace, values, option_string=None):
for _opt in self.options:
setattr(namespace, 'adhoc_' + _opt, False)
setattr(namespace, 'adhoc_' + option_string[2:], True)
setattr(namespace, 'adhoc_arg', values)
parser.add_argument(
'--implode', nargs=0, action=AdHocAction, dest='adhoc_implode', default=False,
help='implode script with adhoc')
parser.add_argument(
'--setup', nargs='?', action=AdHocAction, type=str, metavar='install',
dest='adhoc_setup', default=False, const='install',
help='explode script into temporary directory and call'
' `python setup.py install`')
parser.add_argument(
'--explode', nargs='?', action=AdHocAction, type=str, metavar='DIR',
dest='adhoc_explode', default=False, const='__adhoc__',
help='explode script with adhoc in directory DIR'
' (default: `__adhoc__`)')
parser.add_argument(
'--extract', nargs='?', action=AdHocAction, type=str, metavar='DIR',
dest='adhoc_extract', default=False, const = '.',
help='extract files to directory DIR (default: `.`)')
parser.add_argument(
'--template', nargs='?', action=AdHocAction, type=str, metavar='NAME',
dest='adhoc_template', default=False, const = '-',
help='extract named template to standard output. default NAME is ``-``')
parser.add_argument(
'--eide', nargs='?', action=AdHocAction, type=str, metavar='COMM',
dest='adhoc_eide', default=False, const = '',
help='Emacs IDE template list (implies --template list).')
parser.add_argument(
'-h', '--help', action='store_true',
help="display this help message")
parser.add_argument(
'--ap-help', action='store_true',
help="internal help message")
context.get('_argparse_end', lambda _p, *_args: _p)(parser, context)
if not context.get('_argparse_have_sub_commands'):
# all options and arguments are known
# all non-option arguments are consumed by `_parameters.args`
parser.add_argument(
'args', nargs='*', metavar='arg',
#'args', nargs='+', metavar='arg',
#type=argparse.FileType('r'), default=sys.stdin,
help='a series of arguments')
_parameters = parser.parse_args(argv[1:])
else:
# (progn (forward-line 1) (snip-insert "py_f.args_split_range" t t "python") (insert "\n"))
def args_split_range(args):
next_range = []
for arg in args:
next_range.append(arg)
if not arg.startswith('-'):
break
if next_range and not next_range[0].startswith('-'):
next_range = []
return next_range, args[len(next_range):]
# for sub-commands with their own options: pre-parse to first
# non-option argument
_parameters = None
args = argv[1:]
while True:
next_range, args = args_split_range(args)
if not next_range and not _parameters is None:
break
_parameters, unknown_args = parser.parse_known_args(next_range, _parameters)
if unknown_args:
unknown_args.extend(args)
args = unknown_args
next_range = []
break
_parameters.args = args
# generate argparse help
if _parameters.ap_help:
parser.print_help()
return 0
# standard help
if _parameters.help:
help_ = re.sub('\n+[.][.] _END_OF_HELP.*(?s)', '', context['__doc__'])
sys.stdout.write(help_ + '\n')
return 0
context['_debug'] = _parameters.debug
if context['_debug'] > 0:
context['_verbose'] = True
context['_quiet'] = False
elif context['_debug'] < 0:
context['_verbose'] = (context['_debug'] == -1)
context['_quiet'] = not(context['_verbose'])
context['_debug'] = 0
_parameters.debug = context['_debug']
_parameters.verbose = context['_verbose']
_parameters.quiet = context['_quiet']
if context['_debug']:
cmd_line = argv
sys.stderr.write(sformat(
"{0}{3:^{1}} {4:<{2}s}: ]{5!s}[\n",
context.get('dbg_comm', '# '),
context.get('dbg_twid', 11),
context.get('dbg_fwid', 15),
':DBG:', 'cmd_line', cmd_line))
# at least use `quiet` to suppress the setdefaultencoding warning
setdefaultencoding(quiet=context['_quiet'] or _parameters.test)
# |:opt:| handle options
# adhoc: implode/setup/explode/extract
adhoc_get_opt = lambda opt: getattr(
_parameters, 'adhoc_' + opt, None)
adhoc_op = sum(((adhoc_get_opt(_opt) and 1) or 0
for _opt in AdHocAction.options))
if adhoc_op:
for _opt in AdHocAction.options:
setattr(_parameters, _opt, adhoc_get_opt(_opt))
adhoc_export = (
_parameters.setup
or _parameters.explode
or _parameters.extract)
file_ = context['__file__']
source = None
have_adhoc = 'AdHoc' in context
have_rt_adhoc = 'RtAdHoc' in context
# shall adhoc be imported
if _parameters.implode or not have_rt_adhoc:
# shall this file be compiled
adhoc_compile = not (have_rt_adhoc)
os_path = os.defpath
for pv in ('PATH', 'path'):
try:
os_path = os.environ[pv]
break
except KeyError:
pass
os_path = os_path.split(os.pathsep)
for path_dir in os_path:
if not path_dir:
continue
if path_dir not in sys.path:
sys.path.append(path_dir)
if not have_adhoc:
try:
import adhoc
context['AdHoc'] = adhoc.AdHoc
except ImportError:
adhoc_compile = False
try:
from rt_adhoc import RtAdHoc as Adhoc
context['AdHoc'] = AdHoc
except ImportError:
pass
else:
adhoc_compile = False
context['AdHoc'] = context['RtAdHoc']
AdHoc = context['AdHoc']
AdHoc.quiet = context['_quiet']
AdHoc.verbose = context['_verbose']
AdHoc.debug = context['_debug']
AdHoc.include_path.append(os.path.dirname(file_))
AdHoc.extra_templates = [
]
AdHoc.template_process_hooks = {
}
if _parameters.eide:
AdHoc.tt_ide = True
AdHoc.tt_comment = _parameters.adhoc_arg or ''
AdHoc.tt_prefix = '. (shell-command "'
AdHoc.tt_suffix = '")'
_parameters.template = True
_parameters.adhoc_arg = 'list'
if adhoc_compile:
ah = AdHoc()
source = ah.compileFile(file_)
else:
file_, source = AdHoc.std_source_param(file_)
# implode
if _parameters.implode:
# @:adhoc_enable:@
# if not context['_quiet']:
# map(sys.stderr.write,
# ["warning: ", os.path.basename(file_),
# " already imploded!\n"])
# @:adhoc_enable:@
AdHoc.write_source('-', source)
# explode
elif _parameters.setup or _parameters.explode:
_here = os.path.abspath('.')
_clean_dir = False
AdHoc.export_dir = _parameters.adhoc_arg
if _parameters.setup:
import tempfile
_clean_dir = True
AdHoc.export_dir = tempfile.mkdtemp('_setup', '__adhoc__')
try:
AdHoc.export(file_, source)
if _parameters.setup:
sq = lambda string: ''.join(("'", re.sub("'", """'\\''""", string), "'"))
os.chdir(AdHoc.export_dir)
os.system(sformat('{0} setup.py {1}', sq(sys.executable), sq(_parameters.adhoc_arg)))
finally:
if _clean_dir:
try:
os.chdir(_here)
except:
pass
import shutil
shutil.rmtree(AdHoc.export_dir)
# extract
elif _parameters.extract:
AdHoc.extract_dir = _parameters.adhoc_arg
AdHoc.extract(file_, source)
# template
elif _parameters.template:
template_name = _parameters.adhoc_arg
if not template_name:
template_name = '-'
if template_name == 'list':
sys.stdout.write(
'\n'.join(AdHoc.template_table(file_, source)) + '\n')
else:
template = AdHoc.get_named_template(
template_name, file_, source)
AdHoc.write_source('-', template)
# restore for subsequent calls to main
if not have_adhoc:
del(AdHoc)
return 0
# run doc tests
if _parameters.test:
import warnings
warnings.simplefilter('default')
import doctest
# for :file:`__init__.py`, :func:`_canonize_module_` does not register the module in `sys.modules`.
_module_name = context['__name__']
context.get('_canonize_module_', globals().get(
'_canonize_module_',
lambda *args: None))(context['__name__'], context['__name__'] == '__main__')
if context['__name__'] not in sys.modules:
sys.modules[context['__name__']] = sys.modules[_module_name]
try:
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
except NameError:
pass
context.get('_doctest_hook_', lambda *args, **kwargs: None)(context)
result = doctest.testmod(sys.modules[context['__name__']], verbose = context['_verbose'])
return result.failed
# |:opt:| handle options
final = False
ecode = 0
try:
try:
ecode = context['run'](_parameters)
except IOError:
(t, e, tb) = sys.exc_info()
del(tb)
# ignore SIGPIPE
import errno
if e.errno != errno.EPIPE:
raise
except SystemExit:
raise
except:
# |:info:| this is used, since module cgitb does not work so well ...
(t, e, tb) = sys.exc_info()
if not final or context['_debug']:
import traceback
printf(''.join(traceback.format_tb(tb)), file=sys.stderr, end='')
printf(sformat('{0}: {1}', t.__name__, e), file=sys.stderr)
del(tb)
ecode = 1
return ecode
if globals().get('_is_main_', (__name__ == '__main__')):
#sys.argv.insert(1, '--debug') # |:debug:|
result = main(sys.argv, globals())
sys.exit(result)
# |:here:|
# (progn (forward-line 1) (snip-insert "py.t.ide" t t "py") (insert "\n"))
#
# :ide-menu: Emacs IDE Main Menu - Buffer @BUFFER@
# . M-x `eIDE-menu' (eIDE-menu "z")
# :ide: CSCOPE ON
# . (cscope-minor-mode)
# :ide: CSCOPE OFF
# . (cscope-minor-mode (quote ( nil )))
# :ide: TAGS: forced update
# . (compile (concat "cd /home/ws/project/ws-rfid && make -k FORCED=1 tags"))
# :ide: TAGS: update
# . (compile (concat "cd /home/ws/project/ws-rfid && make -k tags"))
# :ide: +-#+
# . Utilities ()
# :ide: TOC: Generate TOC with py-toc.py
# . (progn (save-buffer) (compile (concat "py-toc.py ./" (file-name-nondirectory (buffer-file-name)) " ")))
# :ide: CMD: Fold region with line continuation
# . (shell-command-on-region (region-beginning) (region-end) "fold --spaces -width 79 | sed 's, $,,;1!s,^, ,;$!s,$,\\\\,'" nil nil nil t)
# :ide: CMD: Fold region and replace with line continuation
# . (shell-command-on-region (region-beginning) (region-end) "fold --spaces --width 79 | sed 's, $,,;1!s,^, ,;$!s,$,\\\\,'" t nil nil t)
# :ide: +-#+
# . Fold ()
# :ide: CMD: Remove 8 spaces and add `>>> ' to region
# . (shell-command-on-region (region-beginning) (region-end) "sed 's,^ ,,;/^[ ]*##/d;/^[ ]*#/{;s,^ *# *,,p;d;};/^[ ]*$/!s,^,>>> ,'" nil nil nil t)
# :ide: CMD: Remove 4 spaces and add `>>> ' to region
# . (shell-command-on-region (region-beginning) (region-end) "sed 's,^ ,,;/^[ ]*##/d;/^[ ]*#/{;s,^ *# *,,p;d;};/^[ ]*$/!s,^,>>> ,'" nil nil nil t)
# :ide: +-#+
# . Doctest ()
# :ide: LINT: Check 80 column width ignoring IDE Menus
# . (let ((args " | /srv/ftp/pub/check-80-col.sh -")) (compile (concat "sed 's,^\\(\\|. \\|.. \\|... \\)\\(:ide\\|[.] \\).*,,' " (buffer-file-name) " " args " | sed 's,^-," (buffer-file-name) ",'")))
# :ide: LINT: Check 80 column width
# . (let ((args "")) (compile (concat "/srv/ftp/pub/check-80-col.sh " (buffer-file-name) " " args)))
# :ide: +-#+
# . Lint Tools ()
# :ide: DELIM: @: SYM :@ @:fillme:@ adhoc tag
# . (symbol-tag-normalize-delimiter (cons (cons nil "@:") (cons ":@" nil)) t)
# :ide: +-#+
# . Delimiters ()
# :ide: COMPILE: Run with --ap-help
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --ap-help")))
# :ide: COMPILE: Run with --help
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --help")))
# :ide: COMPILE: Run with --test
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --test")))
# :ide: COMPILE: Run with --test --verbose
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --test --verbose")))
# :ide: COMPILE: Run with --debug
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --debug")))
# :ide: +-#+
# . Compile with standard arguments ()
# :ide: OCCUR-OUTLINE: Python Source Code
# . (x-symbol-tag-occur-outline "sec" '("|||:" ":|||") (cons (cons "^\\([ \t\r]*\\(def\\|class\\)[ ]+\\|[A-Za-z_]?\\)" nil) (cons nil "\\([ \t\r]*(\\|[ \t]*=\\)")))
# :ide: MENU-OUTLINE: Python Source Code
# . (x-eIDE-menu-outline "sec" '("|||:" ":|||") (cons (cons "^\\([ \t\r]*\\(def\\|class\\)[ ]+\\|[A-Za-z_]?\\)" nil) (cons nil "\\([ \t\r]*(\\|[ \t]*=\\)")))
# :ide: +-#+
# . Outline ()
# :ide: INFO: SQLAlchemy - SQL Expression Language - Reference
# . (let ((ref-buffer "*sqa-expr-ref*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/05/reference/sqlalchemy/expressions.html'") ref-buffer) (display-buffer ref-buffer t)))
# :ide: INFO: SQLAlchemy - SQL Expression Language - Tutorial
# . (let ((ref-buffer "*sqa-expr-tutor*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/05/sqlexpression.html'") ref-buffer) (display-buffer ref-buffer t)))
# :ide: INFO: SQLAlchemy - Query
# . (let ((ref-buffer "*sqa-query*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://www.sqlalchemy.org/docs/orm/query.html'") ref-buffer) (display-buffer ref-buffer t)))
# :ide: +-#+
# . SQLAlchemy Reference ()
# :ide: INFO: Python - argparse
# . (let ((ref-buffer "*python-argparse*")) (if (not (get-buffer ref-buffer)) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " 'http://docs.python.org/library/argparse.html'") ref-buffer) (display-buffer ref-buffer t)))
# :ide: INFO: Python Documentation
# . (let ((ref-buffer "*w3m*")) (if (get-buffer ref-buffer) (display-buffer ref-buffer t)) (other-window 1) (w3m-goto-url "http://docs.python.org/index.html" nil nil))
# :ide: INFO: Python Reference
# . (let* ((ref-buffer "*python-ref*") (local "/home/ws/project/ws-util/python/reference/PQR2.7.html") (url (or (and (file-exists-p local) local) "'http://rgruet.free.fr/PQR27/PQR2.7.html'"))) (unless (get-buffer ref-buffer) (get-buffer-create ref-buffer) (with-current-buffer ref-buffer (shell-command (concat "snc txt.py.reference 2>/dev/null") ref-buffer) (goto-char (point-min)) (if (eobp) (shell-command (concat "w3m -dump -cols " (number-to-string (1- (window-width))) " " url) ref-buffer)))) (display-buffer ref-buffer t))
# :ide: +-#+
# . Python Reference ()
# :ide: COMPILE: Run with --eide
# . (progn (save-buffer) (shell-command (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --eide") (concat "*templates: " (file-name-nondirectory (buffer-file-name)) "*")))
# :ide: COMPILE: Run with python3 --test
# . (progn (save-buffer) (compile (concat "python3 ./" (file-name-nondirectory (buffer-file-name)) " --test")))
# :ide: COMPILE: Run with python3 w/o args
# . (progn (save-buffer) (compile (concat "python3 ./" (file-name-nondirectory (buffer-file-name)) " ")))
# :ide: COMPILE: Run w/o args
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " ")))
# :ide: COMPILE: Run with --debug --force --replace 'user=Max Benutzer' --replace 'user_short=mb' --replace 'hostname_pfx=laptop-' --replace 'hostname=@hostname_pfx@@user_short@' ../README-document-snippets.txt
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --debug --force --replace 'user=Max Benutzer' --replace 'user_short=mb' --replace 'hostname_pfx=laptop-' --replace 'hostname=@hostname_pfx@@user_short@' ../README-document-snippets.txt")))
# :ide: COMPILE: Run with --force --replace 'user=Max Benutzer' --replace 'user_short=mb' --replace 'hostname_pfx=laptop-' --replace 'hostname=@hostname_pfx@@user_short@' ../README-document-snippets.txt
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --force --replace 'user=Max Benutzer' --replace 'user_short=mb' --replace 'hostname_pfx=laptop-' --replace 'hostname=@hostname_pfx@@user_short@' ../README-document-snippets.txt")))
# :ide: COMPILE: Run with --test
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --test")))
# :ide: COMPILE: Run with --debug=1 --force --config README-inst-tagideasy-station.rc --include README-stations.txt --format '{dir}/{base}-x.txt' '../../ws-admin/tagideasy/README-inst-tagideasy-station.src'
# . (progn (save-buffer) (compile (concat "python ./" (file-name-nondirectory (buffer-file-name)) " --debug=1 --force --config README-inst-tagideasy-station.rc --include README-stations.txt --format '{dir}/{base}-x.txt' '../../ws-admin/tagideasy/README-inst-tagideasy-station.src'")))
# :ide: +-#+
# . Compile ()
#
# Local Variables:
# mode: python
# comment-start: "#"
# comment-start-skip: "#+"
# comment-column: 0
# truncate-lines: t
# End: