AdHoc Standalone Python Script Generator

The AdHoc compiler can be used as a program (see Script Usage) as well as a module (see adhoc.AdHoc).

Since the AdHoc compiler itself is installed as a compiled AdHoc script, it serves as its own usage example.

After installation of the adhoc.py script, the full source can be obtained in directory __adhoc__, by executing:

adhoc.py --explode

Purpose

AdHoc provides python scripts with

  • template facilities
  • default file generation
  • standalone module inclusion

See also Use Cases.

AdHoc has been designed to provide an implode/explode cycle:

source_0       xsource_0
source_1 implode   explode xsource_1
... ——> script.py ——> ...
source_n       xsource_n

where xsource_i === source_i. I.e., diff source_i xsource_i does not produce any output.

Quickstart

module.py:

# -*- coding: utf-8 -*-
mvar = ‘value’

script.py:

# -*- coding: utf-8 -*-
# @:adhoc_run_time:@
import module # @:adhoc:@
print(‘mvar: ‘ + module.mvar)

Compilation:

adhoc.py --compile script.py >/tmp/script-compiled.py

Execution outside source directory:

cd /tmp && python script-compiled.py

shows:

mvar: value

Decompilation:

cd /tmp && \
mkdir -p __adhoc__ && \
adhoc.py --decompile <script-compiled.py >__adhoc__/script.py

Description

The AdHoc compiler/decompiler parses text for tagged lines and processes them as instructions.

The minimal parsed entity is a tagged line, which is any line containing a recognized AdHoc tag.

All AdHoc tags are enclosed in delimiters (default: @: and :@). E.g:

@:adhoc:@

Delimiters come in several flavors, namely line and section delimiters and a set of macro delimiters. By default, line and section delimiters are the same, but they can be defined separately.

Flags are tagged lines, which denote a single option or command. E.g.:

import module # @:adhoc:@
# @:adhoc_self:@ my_module_name

Sections are tagged line pairs, which delimit a block of text. The first tagged line opens the section, the second tagged line closes the section. E.g.:

# @:adhoc_enable:@
# disabled_command()
# @:adhoc_enable:@

Macros have their own delimiters (default: @|: and :|>). E.g.:

# @|:MACRO_NAME:|>

The implementation is realized as class adhoc.AdHoc which is mainly used as a namespace. The run-time part of adhoc.AdHoc – which handles module import and file export – is included verbatim as class RtAdHoc in the generated output.

Flags

@:adhoc_run_time:@:
 

The place where the AdHoc run-time code is added. This flag must be present in files, which use the @:adhoc:@ import feature. It is not needed for the enable/disable features.

This flag is ignored, if double commented. E.g.:

# # @:adhoc_run_time:@
@:adhoc:@ [force] [flat | full]:
 

Mark import line for run-time compilation.

If force is specified, the module is imported, even if it was imported before.

If flat is specified, the module is not recursively exported.

If full is specified, the module is recursively exported. (This parameter takes priority over flat).

If neither flat nor full are specified, adhoc.AdHoc.flat determines the export scope.

This flag is ignored, if the line is commented out. E.g.:

# import module # @:adhoc:@
@:adhoc_include:@ file_spec, ...:
 

Include files for unpacking. file_spec is one of

file:file is used for both input and output.
file from default-file:
 file is used for input and output. if file does not exist, default-file is used for input.
source-file as output-file:
 source-file is used for input. output-file is used for output. If source-file does not exist, output-file is used for input also.

This flag is ignored, if double commented. E.g.:

# # @:adhoc_include:@ file
@:adhoc_verbatim:@ [flags] file_spec, ...:
 

Include files for verbatim extraction. See adhoc_include for file_spec.

The files are included as @:adhoc_template_v:@ sections. file is used as export_file mark. If file is --, the template disposition becomes standard output.

Optional flags can be any combination of [+|-]NUM for indentation and # for commenting. E.g.:

# @:adhoc_verbatim:@ +4# my_file from /dev/null

my_file (or /dev/null) is read, commented and indented 4 spaces.

If the @:adhoc_verbatim:@ tag is already indented, the specified indentation is subtracted.

This flag is ignored, if double commented. E.g.:

# # @:adhoc_verbatim:@ file
@:adhoc_self:@ name ...:
 

Mark name(s) as currently compiling. This is useful, if __init__.py imports other module parts. E.g:

import pyjsmo # @:adhoc:@

where pyjsmo/__init__.py contains:

# @:adhoc_self:@ pyjsmo
from pyjsmo.base import * # @:adhoc:@
@:adhoc_compiled:@:
 

If present, no compilation is done on this file. This flag is added by the compiler to the run-time version.

Sections

@:adhoc_enable:@:
 

Leading comment char and exactly one space are removed from lines in these sections.

@:adhoc_disable:@:
 

A comment char and exactly one space are added to non-blank lines in these sections.

@:adhoc_template:@ -mark | export_file:
 

If mark starts with -, the output disposition is standard output and the template is ignored, when exporting.

Otherwise, the template is written to output_file during export.

All template parts with the same mark/export_file are concatenated to a single string.

@:adhoc_template_v:@ export_file:
 

Variation of @:adhoc_template:@. Automatically generated by @:adhoc_verbatim:@.

@:adhoc_uncomment:@:
 

Treated like @:adhoc_enable:@ before template output.

@:adhoc_indent:@ [+|-]NUM:
 

Add or remove indentation before template output.

@:adhoc_import:@:
 

Imported files are marked as such by the compiler. There is no effect during compilation.

@:adhoc_unpack:@:
 

Included files are marked as such by the compiler. There is no effect during compilation.

@:adhoc_remove:@:
 

Added sections are marked as such by the compiler. Removal is done when exporting.

Before compilation, existing @:adhoc_remove:@ tags are renamed to @:adhoc_remove_:@.

After automatically added @:adhoc_remove:@ sections have been removed during export, remaining @:adhoc_remove_:@ tags are renamed to @:adhoc_remove:@ again.

Note

Think twice, before removing material from original sources at compile time. It will violate the condition xsource_i === source_i.

@:adhoc_run_time_engine:@:
 

The run-time class RtAdHoc is enclosed in this special template section.

It is exported as rt_adhoc.py during export.

Macros

Macros are defined programmatically:

AdHoc.macros[MACRO_NAME] = EXPANSION_STRING

A macro is invoked by enclosing a MACRO_NAME in adhoc.AdHoc.macro_call_delimiters. (Default: @|:, :|>).

@|:MACRO_NAME:|>:
 Macro call.

Internal

@:adhoc_run_time_class:@:
 Marks the beginning of the run-time class. This is only recognized in the AdHoc programm/module.
@:adhoc_run_time_section:@:
 All sections are concatenated and used as run-time code. This is only recognized in the AdHoc programm/module.

In order to preserve the xsource_i === source_i bijective condition, macros are expanded/collapsed with special macro definition sections. (See adhoc.AdHoc.macro_xdef_delimiters; Default: <|:, :|@).

<|:adhoc_macro_call:|@:
 Macro call section.
<|:adhoc_macro_expansion:|@:
 Macro expansion section.

Use Cases

The initial incentive for the adhoc compiler was to have a means for including development libraries that are not ready for PyPI (and maybe never will). (See Module Imports).

The problem with these libraries is that they are not available on all systems and may not be worth the effort of a full-blown distutils package.

If the API is heavily in flux, it is also nice to be able to take an arbitrary stable snapshot without version fiddling and carry everything around in a self-contained single file script. This eliminates the need to follow API changes in support libraries immediately.

Creating a Python script instead of an archive eliminates the installation step.

Including the importer/extractor as verbatim code eliminates the need for a run-time system to be installed. (See Generic AdHoc Initialization).

Modifications of the main script can be made trivially.

The export mechanism allows arbitrary modifications of the main script and all adhoc’ed imports.

The adhoc.py compiler script is only needed, if an exported script should be compiled again.

Non-Module Included Files and Template Extraction are logical expansions of the basic concept.

Note

Self-referential stuff gets pretty hilarious after a while ... The script for generating the use case documentation has some two and a half layers of template tagging :)

Generic AdHoc Initialization

If only automatic import and unpacking features are used, the standard initialization with a @:adhoc_run_time:@ tag is sufficient. This includes the export, extract and template features, if only used in the compiled script.

However, it is convenient that the uncompiled, compiled and exported versions of a script behave identically (especially for templates). That is the purpose of this generic initialization example.

The use case documentation generator scripts contain an example main() function, which compiles/uncompiles the script on demand.

A more complete example can be found in the command line argument evaluation part of the main() function in namespace_dict.py

The most complex example is available in the command line argument evaluation part of the main() function in adhoc.py.

Overview

The entire initialization code looks like this:

# @:adhoc_run_time:@

@:adhoc_disable:@
import os
import sys
os_path = os.defpath
if 'PATH' in os.environ:
    os_path = os.environ['PATH']
sys_path = sys.path
sys.path.extend(os_path.split(os.pathsep))
try:
    import adhoc
    from adhoc import AdHoc as RtAdHoc
except ImportError:
    try:
        import rt_adhoc
        from rt_adhoc import RtAdHoc
    except ImportError:
        pass
sys.path = sys_path
@:adhoc_disable:@

Uncompiled Script

The script starts with the AdHoc run-time declaration

# @:adhoc_run_time:@

The uncompiled script uses modules adhoc or rt_adhoc for class RtAdHoc.

Add executable search path to Python module search path:

# @:adhoc_disable:@
import os
import sys
os_path = os.defpath
if 'PATH' in os.environ:
    os_path = os.environ['PATH']
sys_path = sys.path
sys.path.extend(os_path.split(os.pathsep))

Import adhoc and use class adhoc.AdHoc as RtAdHoc:

try:
    import adhoc
    from adhoc import AdHoc as RtAdHoc

Use exported rt_adhoc module, if adhoc is not available:

except ImportError:
    try:
        import rt_adhoc
        from rt_adhoc import RtAdHoc

Let the script continue, even if RtAdHoc is not available:

except ImportError:
    pass

Restore the standard module search path:

sys.path = sys_path
# @:adhoc_disable:@

From here on, RtAdHoc can be used for both the uncompiled and compiled version of the script.

Compiled Script

After adhoc compilation, the run-time class is added and the script is modified to:

class RtAdHoc (object):
    ...

Since RtAdHoc is incorporated verbatim, there is no need to import adhoc or rt_adhoc anymore:

# @:adhoc_disable:@
# import os
# import sys
# os_path = os.defpath
# if 'PATH' in os.environ:
#     os_path = os.environ['PATH']
# sys_path = sys.path
# sys.path.extend(os_path.split(os.pathsep))
# try:
#     import adhoc
#     from adhoc import AdHoc as RtAdHoc
# except ImportError:
#     try:
#         import rt_adhoc
#         from rt_adhoc import RtAdHoc
#     except ImportError:
#         pass
# sys.path = sys_path
# @:adhoc_disable:@

The rest of the script is unmodified.

Template Extraction

Templates are useful, if some code snippet is to be executed and should also be available to initialize, e.g., RC files.

The following Python script defines a template ~/.uc00.rc, which is extracted, if it does not already exist.

The script starts with Generic AdHoc Initialization:

# @:adhoc_run_time:@
# @:adhoc_disable:@
# Get RtAdHoc from adhoc or rt_adhoc
import os
import sys
os_path = os.defpath
if 'PATH' in os.environ:
    os_path = os.environ['PATH']
sys_path = sys.path
sys.path.extend(os_path.split(os.pathsep))
try:
    import adhoc
    from adhoc import AdHoc as RtAdHoc
except ImportError:
    try:
        import rt_adhoc
        from rt_adhoc import RtAdHoc
    except ImportError:
        pass
sys.path = sys_path
# @:adhoc_disable:@

Setup of some default values, enclosed in a template declaration:

rc_file_name = '~/.uc00.rc'
# @:adhoc_template:@ ~/.uc00.rc
# -*- coding: utf-8 -*-
default_value = 'default'
another_value = 'other'
# @:adhoc_template:@

Template extraction makes sure, that the file ~/.uc00.rc exists, if the user’s home directory is writable:

RtAdHoc.quiet = True
RtAdHoc.extract_templates(__file__)

Read ~/.uc00.rc, if available, and define variables:

rc_file = os.path.expanduser(rc_file_name)
try:
    rc_source = RtAdHoc.read_source(rc_file, decode=False)
    exec(rc_source, globals(), locals())
except IOError:
    pass

print('default_value: ' + default_value)
print('another_value: ' + another_value)

Included Files

Included files are optionally zipped and base64-encoded. They can be automatically unpacked, or unpacked via the adhoc.AdHoc.extract() and adhoc.AdHoc.get_named_template() mechanisms.

The following Python script include the files included1 and included2. included1 is automatically unpacked, if it does not already exist, whereas included2 is only available for explicit extraction.

Uncompiled Script

The script starts with Generic AdHoc Initialization:

# @:adhoc_run_time:@
# @:adhoc_disable:@
# Get RtAdHoc from adhoc or rt_adhoc
import os
import sys
os_path = os.defpath
if 'PATH' in os.environ:
    os_path = os.environ['PATH']
sys_path = sys.path
sys.path.extend(os_path.split(os.pathsep))
try:
    import adhoc
    from adhoc import AdHoc as RtAdHoc
except ImportError:
    try:
        import rt_adhoc
        from rt_adhoc import RtAdHoc
    except ImportError:
        pass
sys.path = sys_path
# @:adhoc_disable:@

include1 is marked for inclusion at compile time. Since it is supposed to exist anyway, no special care is taken to extract it in the uncompiled script:

# @:adhoc_include:@ include1

include2 is marked for inclusion at compile time:

if False:
    pass
    # @:adhoc_include:@ include2

There is actually nothing to extract in the uncompiled script:

RtAdHoc.quiet = True
RtAdHoc.extract(__file__)

Compiled Script

include1 is automatically extracted in the compiled script:

# @:adhoc_include:@ include1
# @:adhoc_unpack:@ !include1
RtAdHoc.unpack_(None, file_='include1',
    mtime='2013-08-24T11:02:01.078186', mode=int("100644", 8),
    zipped=True, flat=None, source64=
    'H4sIAIl2GFIC/1NW0NXSVUjOT8nMS7dSyEksycwzBAlxJSYlKzz59ocrLTMnRyGzRKG0'
    'QCFRISezpCQnVUFPT48LAJnBlS85AAAA')
# @:adhoc_unpack:@

The if False before include2 prevents automatic extraction:

if False:
    pass
    # @:adhoc_include:@ include2
    # @:adhoc_unpack:@ !include2
    RtAdHoc.unpack_(None, file_='include2',
        mtime='2013-08-24T11:02:01.078186', mode=int("100644", 8),
        zipped=True, flat=None, source64=
        'H4sIAIl2GFIC/1NW0NXSVUjOT8nMS7dSKC1J07UAiXAlJiUrHF5yeNvhPVxpmTk5'
        'CpklCqUFCokKOZklJTmpCnp6elwAUul2+TsAAAA=')
    # @:adhoc_unpack:@

In the compiled script, include2 will now also be extracted, since adhoc.AdHoc.extract() finds all sections tagged with adhoc_unpack:

RtAdHoc.quiet = True
RtAdHoc.extract(__file__)

Module Imports

Imported modules are optionally zipped and base64-encoded. They are automatically unpacked internally and set up as modules in sys.modules as required.

They can also be unpacked via the adhoc.AdHoc.extract() and adhoc.AdHoc.get_named_template() mechanisms.

The following Python script imports the module adhoc_test.sub. This also triggers the import of adhoc_test, which is therefore also included.

Import compilation is recursive. I.e., if a module contains its own adhoc tags, they are also processed.

Note

When exported, modules are not recreated at the original locations, but locally below the export directory.

Uncompiled Script

The script starts with Generic AdHoc Initialization:

# @:adhoc_run_time:@

# @:adhoc_disable:@
# Get RtAdHoc from adhoc or rt_adhoc
import os
import sys
os_path = os.defpath
if 'PATH' in os.environ:
    os_path = os.environ['PATH']
sys_path = sys.path
sys.path.extend(os_path.split(os.pathsep))
try:
    import adhoc
    from adhoc import AdHoc as RtAdHoc
except ImportError:
    try:
        import rt_adhoc
        from rt_adhoc import RtAdHoc
    except ImportError:
        pass
sys.path = sys_path
# @:adhoc_disable:@

import adhoc_test.sub is marked for inclusion at compile time:

import adhoc_test.sub # @:adhoc:@ force

Expected output is adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED: True:

print('adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED: '
      + str(adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED))

Expected output is adhoc_test.ADHOC_TEST_IMPORTED: True:

print('adhoc_test.ADHOC_TEST_IMPORTED: '
      + str(adhoc_test.ADHOC_TEST_IMPORTED))

Setup use_case_003_export as export directory:

RtAdHoc.quiet = True
RtAdHoc.export_dir = 'use_case_003_export'
RtAdHoc.export(__file__)

Show export results:

if os.path.exists(RtAdHoc.export_dir):
    for dir_, subdirs, files in os.walk(RtAdHoc.export_dir):
        for file_ in sorted(files):
            map(sys.stdout.write, (os.path.join(dir_, file_), '\n'))

The uncompiled script effectively copies itself into use_case_003_export, but does not create the adhoc_test module:

use_case_003_export/use_case_003_import_.py

Compiled Script

Module adhoc_test is prepared as module through adhoc.AdHoc.import_() as requirement before module adhoc_test.sub in the compiled script. The original import statement then finds the pre-imported versions:

# @:adhoc_import:@ !adhoc_test
RtAdHoc.import_('adhoc_test', file_='adhoc_test/__init__.py',
    mtime='2012-09-18T14:26:21.150587', mode=int("100644", 8),
    zipped=True, flat=None, source64=
    'H4sIAIl2GFIC/1NW0NXSVUjOT8nMS7dSKC1J07UAiXBxObp4+DvHh7gGh8R7+gb4B4W4'
    'uijYKoQUlaZyAQBLQbhtNAAAAA==')
# @:adhoc_import:@
# @:adhoc_import:@ !adhoc_test.sub
RtAdHoc.import_('adhoc_test.sub', file_='adhoc_test/sub/__init__.py',
    mtime='2012-09-18T14:26:21.150587', mode=int("100644", 8),
    zipped=True, flat=None, source64=
    'H4sIAIl2GFIC/1NW0NXSVUjOT8nMS7dSKC1J07UAiXBxObp4+DvHh7gGh8QHhzrFe/oG'
    '+AeFuLoo2CqEFJWmcgEAQobQsjgAAAA=')
# @:adhoc_import:@
import adhoc_test.sub # @:adhoc:@ force

Expected output is adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED: True:

print('adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED: '
      + str(adhoc_test.sub.ADHOC_TEST_SUB_IMPORTED))

Expected output is adhoc_test.ADHOC_TEST_IMPORTED: True:

print('adhoc_test.ADHOC_TEST_IMPORTED: '
      + str(adhoc_test.ADHOC_TEST_IMPORTED))

Setup use_case_003_export as export directory:

RtAdHoc.quiet = True
RtAdHoc.export_dir = 'use_case_003_export'
RtAdHoc.export(__file__)

Show export results:

if os.path.exists(RtAdHoc.export_dir):
    for dir_, subdirs, files in os.walk(RtAdHoc.export_dir):
        for file_ in sorted(files):
            map(sys.stdout.write, (os.path.join(dir_, file_), '\n'))

Besides the original version of itself, the compiled script also recreates adhoc_test and adhoc_test.sub in the export directory:

use_case_003_export/use_case_003_import_.py
use_case_003_export/adhoc_test/__init__.py
use_case_003_export/adhoc_test/sub/__init__.py

Nested Templates

Since AdHoc sections are defined with the same tag denoting start and end, it may not be obvious how nested templates can be realized.

There are several different ways to achieve section nesting:

Alternate Tag Symbols

Consider some detailed documentation:

# @:adhoc_uncomment:@
# @:adhoc_template:@ -doc
# Documentation
# =============
#
# Summary
#
# @:adhoc_x_full_doc:@ -details
# Details
# -------
#
# Lengthy explanation ...
#
# @:adhoc_x_full_doc:@
# Conclusion
# ----------
#
# Good!
#
# @:adhoc_x_full_doc:@
# Because ...
#
# @:adhoc_x_full_doc:@
# @:adhoc_template:@
# @:adhoc_uncomment:@

The raw template:

template_raw = RtAdHoc.get_named_template('-doc', __file__)

is easily split into parts of different scope:

full_doc_tag_sym = 'adhoc_x_full_doc'
full_doc_tag = RtAdHoc.section_tag(full_doc_tag_sym)

by removing all tagged detail sections:

short_doc = RtAdHoc.remove_sections(template_raw, full_doc_tag_sym)

providing for a short summary:

Documentation
=============

Summary

Conclusion
----------

Good!

by extracting sub-templates:

details = RtAdHoc.get_named_template('-details', None, template_raw, full_doc_tag)

providing for a details higlight:

Details
-------

Lengthy explanation ...

and by removing sub-template tag lines:

full_doc = RtAdHoc.section_tag_remove(template_raw, full_doc_tag_sym)

providing the full documentation (full_doc):

Documentation
=============

Summary

Details
-------

Lengthy explanation ...

Conclusion
----------

Good!

Because ...

Alternate Tag Delimiters

The same documentation tagged with different tag delimiters:

# @:adhoc_uncomment:@
# @:adhoc_template:@ -doc
# Documentation
# =============
#
# Summary
#
# @:adhoc_template:> -details
# Details
# -------
#
# Lengthy explanation ...
#
# @:adhoc_template:>
# Conclusion
# ----------
#
# Good!
#
# @:adhoc_template:>
# Because ...
#
# @:adhoc_template:>
# @:adhoc_template:@
# @:adhoc_uncomment:@

After getting the raw template:

template_raw = RtAdHoc.get_named_template('-doc', __file__)

the delimiters are changed for the documentation detail sections:

full_doc_delimiters = ('@:', ':>')
state = RtAdHoc.set_delimiters(full_doc_delimiters)

and the same parts as with Alternate Tag Symbols are generated:

short_doc = RtAdHoc.remove_sections(template_raw, 'adhoc_template')
details = RtAdHoc.get_named_template('-details', None, template_raw)
full_doc = RtAdHoc.section_tag_remove(template_raw, 'adhoc_template')

It is good practice to restore the previous delimiter set:

RtAdHoc.reset_delimiters(state)

AdHoc Script

adhoc.py - Python ad hoc compiler.

usage: adhoc.py [OPTIONS] [file ...]
or import adhoc

Options

-c, –compile compile file(s) or standard input into output file (default: standard output).
-d, –decompile decompile file(s) or standard input into output directory (default __adhoc__).
-o, –output OUT output file for –compile/output directory for –decompile.
-q, –quiet suppress warnings
-v, –verbose verbose test output
–debug[=NUM] show debug information
-h, –help display this help message
–documentation display module documentation.
–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__)
–implode implode script with adhoc
–install install adhoc.py script
-t, –test run doc tests

adhoc.py is compatible with Python 2.4+ and Python 3. (For Python <2.6 the packages stringformat and argparse are needed and included.)

Script Examples

Templates

Sections marked by @:adhoc_template:@ can be retrieved as templates on standard output.

Additionally, all other files compiled into an adhoc file with one of

@:adhoc:@ ==> @:adhoc_import:@
@:adhoc_verbatim:@ ==> @:adhoc_template_v:@
@:adhoc_include:@ ==> @:adhoc_unpack:@

are accessible as templates.

python adhoc.py --template list provides a list of templates:

>>> ign = main('adhoc.py --template list'.split())
================================================= ================================ ================
                     Command                                  Template                   Type
================================================= ================================ ================
adhoc.py --template adhoc_test                    # !adhoc_test                    adhoc_import
adhoc.py --template adhoc_test.sub                # !adhoc_test.sub                adhoc_import
adhoc.py --template argparse_local                # !argparse_local                adhoc_import
adhoc.py --template namespace_dict                # !namespace_dict                adhoc_import
adhoc.py --template stringformat_local            # !stringformat_local            adhoc_import
adhoc.py --template use_case_000_                 # !use_case_000_                 adhoc_import
adhoc.py --template use_case_001_templates_       # !use_case_001_templates_       adhoc_import
adhoc.py --template use_case_002_include_         # !use_case_002_include_         adhoc_import
adhoc.py --template use_case_003_import_          # !use_case_003_import_          adhoc_import
adhoc.py --template use_case_005_nested_          # !use_case_005_nested_          adhoc_import
adhoc.py --template docutils.conf                 # docutils.conf                  adhoc_template_v
adhoc.py --template                               # -                              adhoc_template
adhoc.py --template README.txt                    # README.txt                     adhoc_template
adhoc.py --template adhoc_init                    # -adhoc_init                    adhoc_template
adhoc.py --template catch-stdout                  # -catch-stdout                  adhoc_template
adhoc.py --template col-param-closure             # -col-param-closure             adhoc_template
adhoc.py --template doc/USE_CASES.txt             # doc/USE_CASES.txt              adhoc_template
adhoc.py --template doc/index.rst                 # doc/index.rst                  adhoc_template
adhoc.py --template max-width-class               # -max-width-class               adhoc_template
adhoc.py --template rst-to-ascii                  # -rst-to-ascii                  adhoc_template
adhoc.py --template test                          # -test                          adhoc_template
adhoc.py --template MANIFEST.in                   # !MANIFEST.in                   adhoc_unpack
adhoc.py --template Makefile                      # !Makefile                      adhoc_unpack
adhoc.py --template README.css                    # !README.css                    adhoc_unpack
adhoc.py --template doc/Makefile                  # !doc/Makefile                  adhoc_unpack
adhoc.py --template doc/_static/adhoc-logo-32.ico # !doc/_static/adhoc-logo-32.ico adhoc_unpack
adhoc.py --template doc/adhoc-logo.svg            # !doc/adhoc-logo.svg            adhoc_unpack
adhoc.py --template doc/conf.py                   # !doc/conf.py                   adhoc_unpack
adhoc.py --template doc/make.bat                  # !doc/make.bat                  adhoc_unpack
adhoc.py --template doc/z-massage-index.sh        # !doc/z-massage-index.sh        adhoc_unpack
adhoc.py --template setup.py                      # !setup.py                      adhoc_unpack
================================================= ================================ ================

python adhoc.py --template prints the standard template - (closing delimiter replaced by ellipsis):

>>> ign = main('./adhoc.py --template'.split()) 
# @:adhoc_disable... allow modification of exploded sources in original place
sys.path.append('__adhoc__')
# @:adhoc_disable...

# @:adhoc_run_time... The run-time class goes here
# @:adhoc_run_time_engine... settings enabled at run-time
# @:adhoc_enable...
# RtAdHoc.flat = False
# @:adhoc_enable...
# @:adhoc_run_time_engine...

#import adhoc                                               # @:adhoc...

python adhoc.py --template test prints the template named -test. the leading - signifies disposition to standard output:

>>> ign = main('./adhoc.py --template test'.split())
Test template.

Extract

The default destination for extracting files is the current working directory.

Files extracted consist of

  • packed files generated by @:adhoc_include:@
  • templates generated by @:adhoc_verbatim:@
  • templates with a file destination other than standard output

python adhoc.py --extract __adhoc_extract__ unpacks the following files into directory __adhoc_extract__:

>>> import shutil
>>> ign = main('./adhoc.py --extract __adhoc_extract__'.split())
>>> file_list = []
>>> for dir, subdirs, files in os.walk('__adhoc_extract__'):
...     file_list.extend([os.path.join(dir, file_) for file_ in files])
>>> for file_ in sorted(file_list):
...     printf(file_)
__adhoc_extract__/MANIFEST.in
__adhoc_extract__/Makefile
__adhoc_extract__/README.css
__adhoc_extract__/README.txt
__adhoc_extract__/doc/Makefile
__adhoc_extract__/doc/USE_CASES.txt
__adhoc_extract__/doc/_static/adhoc-logo-32.ico
__adhoc_extract__/doc/adhoc-logo.svg
__adhoc_extract__/doc/conf.py
__adhoc_extract__/doc/index.rst
__adhoc_extract__/doc/make.bat
__adhoc_extract__/doc/z-massage-index.sh
__adhoc_extract__/docutils.conf
__adhoc_extract__/setup.py
__adhoc_extract__/use_case_000_.py
__adhoc_extract__/use_case_001_templates_.py
__adhoc_extract__/use_case_002_include_.py
__adhoc_extract__/use_case_003_import_.py
__adhoc_extract__/use_case_005_nested_.py
>>> shutil.rmtree('__adhoc_extract__')

Export

The default destination for exporting files is the subdirectory __adhoc__.

Files exported consist of

  • imported modules generated by @:adhoc:@
  • all files covered in section Extract

python adhoc.py --explode __adhoc_explode__ unpacks the following files into directory __adhoc_explode__:

>>> import shutil
>>> ign = main('./adhoc.py --explode __adhoc_explode__'.split())
>>> file_list = []
>>> for dir, subdirs, files in os.walk('__adhoc_explode__'):
...     file_list.extend([os.path.join(dir, file_) for file_ in files])
>>> for file_ in sorted(file_list):
...     printf(file_)
__adhoc_explode__/MANIFEST.in
__adhoc_explode__/Makefile
__adhoc_explode__/README.css
__adhoc_explode__/README.txt
__adhoc_explode__/adhoc.py
__adhoc_explode__/adhoc_test/__init__.py
__adhoc_explode__/adhoc_test/sub/__init__.py
__adhoc_explode__/argparse_local.py
__adhoc_explode__/doc/Makefile
__adhoc_explode__/doc/USE_CASES.txt
__adhoc_explode__/doc/_static/adhoc-logo-32.ico
__adhoc_explode__/doc/adhoc-logo.svg
__adhoc_explode__/doc/conf.py
__adhoc_explode__/doc/index.rst
__adhoc_explode__/doc/make.bat
__adhoc_explode__/doc/z-massage-index.sh
__adhoc_explode__/docutils.conf
__adhoc_explode__/namespace_dict.py
__adhoc_explode__/rt_adhoc.py
__adhoc_explode__/setup.py
__adhoc_explode__/stringformat_local.py
__adhoc_explode__/use_case_000_.py
__adhoc_explode__/use_case_001_templates_.py
__adhoc_explode__/use_case_002_include_.py
__adhoc_explode__/use_case_003_import_.py
__adhoc_explode__/use_case_005_nested_.py
>>> shutil.rmtree('__adhoc_explode__')

File Permissions

  • File mode is restored.

  • File ownership is not restored.

  • File modification times are restored.

    Since only naive datetimes are recorded, this only works correctly within the same timezone.

AdHoc Module

class adhoc.AdHoc[source]

Bases: object

AdHoc is mainly used as a namespace, which is partially included verbatim as RtAdHoc in the generated output.

It is only instantiated for compiling adhoc output (compileFile(), compile()).

Attributes

The following class attrbutes determine the operation of AdHoc:

Run-time class attributes can be set like this:

# @:adhoc_run_time:@
# @:adhoc_enable:@
# RtAdHoc.flat = False
# RtAdHoc.frozen = True
# @:adhoc_enable:@

or like this:

# @:adhoc_run_time:@
if ‘RtAdHoc’ in globals():
RtAdHoc.flat = False
RtAdHoc.frozen = True

Low-Level Functions

adhoc_tag() constructs a delimited tag or tag regular expression:

>>> adhoc_tag = AdHoc.adhoc_tag
>>> delimiters = ('<:', ':>')
>>> tag_sym = 'my_tag'
>>> adhoc_tag(tag_sym, delimiters)
'<:my_tag:>'
>>> tag_rx = 'my_[^:]+'
>>> adhoc_tag(tag_rx, delimiters, is_re=True)
'\\<\\:my_[^:]+\\:\\>'

tag_split() splits a string into tagged line parts and untagged parts.

adhoc_parse_line() splits a tagged line into a tag symbol and additional arguments:

>>> adhoc_parse_line = AdHoc.adhoc_parse_line
>>> tagged_line = 'anything # <:my_tag:>  additonal arguments # end comment'
>>> adhoc_parse_line(tagged_line, tag_sym, delimiters)
('my_tag', 'additonal arguments # end comment')
>>> adhoc_parse_line(tagged_line, tag_rx, delimiters, is_re=True)
('my_tag', 'additonal arguments # end comment')
>>> adhoc_parse_line(tagged_line, tag_rx, delimiters, is_re=True, strip_comment=True)
('my_tag', 'additonal arguments')

Low-Level Convenience Functions

Tag Generation

line_tag(), section_tag()

>>> class ah(AdHoc):
...     line_delimiters = ('>:', ':<')
...     section_delimiters = ('<:', ':>')
>>> ah.line_tag('tag-symbol')
'>:tag-symbol:<'
>>> ah.line_tag('tag.?rx', True)
'\\>\\:tag.?rx\\:\\<'
>>> ah.section_tag('tag-symbol')
'<:tag-symbol:>'
>>> ah.section_tag('tag.?rx', True)
'\\<\\:tag.?rx\\:\\>'

Tagged Line/Section Retrieval

tag_lines(), tag_partition(), tag_sections()

>>> source = AH_CHECK_SOURCE
>>> line_tag = ah.line_tag('cmd')
>>> tagged_lines = ah.tag_lines(source, line_tag)
>>> adhoc_dump_list(tagged_lines, 40)
#   :DBG:   elt[0]                 : ]'# >:cmd:< arg0 arg1 # comment\n'[
#   :DBG:   elt[1]                 : ]'# >:cmd:< arg2 arg3 # comment\n'[
>>> is_re = True
>>> section_tag_rx = ah.section_tag('tag.?', is_re=is_re)
>>> body, sections = ah.tag_partition(source, section_tag_rx, is_re=is_re)
>>> adhoc_dump_list(body, 40)
#   :DBG:   elt[0]                 : ]'not in section\n# >:cmd:< arg0 arg1 #  ...'[
#   :DBG:   elt[1]                 : ]'not in section\n'[
#   :DBG:   elt[2]                 : ]'not in section\n'[
>>> adhoc_dump_list(sections, 40)
#   :DBG:   elt[0]                 : ]'in section\n# >:cmd:< arg2 arg3 # comm ...'[
#   :DBG:   elt[1]                 : ]'in section\nin section\n'[
>>> body, sections = ah.tag_partition(source, section_tag_rx, is_re=is_re, headline=True)
>>> adhoc_dump_sections(sections, 40)
#   :DBG:   section[0]             : ]['# <:tag:> on\n', 'in section\n# >:cmd:< arg2 arg3 # comm ...'][
#   :DBG:   section[1]             : ]['# <:tag2:> on\n', 'in section\nin section\n'][
>>> sections = ah.tag_sections(source, section_tag_rx, is_re=is_re, headline=True)
>>> adhoc_dump_sections(sections, 40)
#   :DBG:   section[0]             : ]['# <:tag:> on\n', 'in section\n# >:cmd:< arg2 arg3 # comm ...'][
#   :DBG:   section[1]             : ]['# <:tag2:> on\n', 'in section\nin section\n'][

Tagged Line Parsing

>>> strclean(ah.line_tag_parse(tagged_lines[0], 'cmd'))
('cmd', 'arg0 arg1 # comment')
>>> strclean(ah.line_tag_strip(tagged_lines[0], 'cmd', strip_comment=True))
'arg0 arg1'
>>> strclean(ah.section_tag_parse(sections[1][0], 'tag.?', is_re=True))
('tag2', 'on')
>>> strclean(ah.section_tag_strip(sections[1][0], 'tag.?', is_re=True))
'on'

Tagged Line/Section Transformations

IO Functions

Run-Time Unpack/Import Interface

Export Tools

Extract Interface

Export Interface

  • export__(), export_(), export()

Dump Interface (Import/Unpack Substitute)

  • dump__(), dump_(), dump_file()

Macro Interface

Naive macro expansion would violate the condition xsource_i === source_i.

Here is a simple macro system which preserves the bijectivity condition. It is quite useful for conditional templating. (See Use Cases generator scripts).

Limitations

  • Macro expansions are not prefixed with the current indentation
  • Macros cannot be nested

Attributes

  • macro_call_delimiters

    Delimiters for macros, e.g.: @|:MACRO_NAME:|>

  • macro_xdef_delimiters

    Delimiters for macro expansion, e.g.:

    # <|:adhoc_macro_call:|@
    # @|:MACRO_NAME:|>
    # <|:adhoc_macro_call:|@
    # <|:adhoc_macro_expansion:|@
    The macro definition ...
    The macro definition ...
    # <|:adhoc_macro_expansion:|@
  • macros

    Macro definitions.

Methods

Template Interface

Template Extraction (uncompiled)

  • Expand and activate macros for uncompiled source
  • Activate macros on compiled source

Compile

  • Expand macros before compilation

Export

  • Collapse macros on export of compiled source.

Compilation Attributes

Compilation Interface

  • setup_tags()
  • strquote()
  • adhoc_run_time_sections_from_string()
  • adhoc_run_time_section_from_file()
  • adhoc_get_run_time_section()
  • prepare_run_time_section()
  • verbatim_()
  • include_()
  • encode_module_()
  • compile_()

User API

classmethod activate_macros(source, macro_call_dlm=None, macro_xdef_dlm=None)[source]
classmethod adhoc_parse_line(tagged_line, symbol_or_re=None, delimiters=None, is_re=False, strip_comment=None)[source]

Parse a tagged line into tag-symbol and argument parts.

Returns:

a tuple (tag-symbol, tag-arguments).

Parameters:
  • tagged_line – string to be parsed.
  • symbol_or_re – symbol string or regular expresssion to be parsed, default is any sequence of characters except the first character of the suffix delimiter.
  • delimiters – tuple of delimiter strings (prefix, suffix). Default is line_delimiters.
  • strip_comment – If True, remove trailing # comment from arguments. Default: False.
>>> tagged_line = ' # @:' 'adhoc_test' ':@   arg1 arg2  # comment'
>>> AdHoc.adhoc_parse_line(tagged_line)
('adhoc_test', 'arg1 arg2  # comment')
>>> AdHoc.adhoc_parse_line(tagged_line, 'adhoc_.*', is_re=True)
('adhoc_test', 'arg1 arg2  # comment')
>>> AdHoc.adhoc_parse_line(tagged_line, strip_comment=True)
('adhoc_test', 'arg1 arg2')
>>> AdHoc.adhoc_parse_line(tagged_line.replace('@', '<'))
('', '# <:adhoc_test:<   arg1 arg2  # comment')
>>> AdHoc.adhoc_parse_line(tagged_line.replace('@', '|'), delimiters=('|:', ':|'))
('adhoc_test', 'arg1 arg2  # comment')
static adhoc_tag(symbol_or_re, delimiters, is_re=False)[source]

Make a tag from symbol_or_re and delimiters.

Parameters:
  • symbol_or_re – symbol string or regular expresssion.
  • delimiters – tuple of delimiter strings (prefix, suffix).
  • is_re – if True, escape the delimiters for regular expressions.
static check_coding(source)[source]

Determine coding for source.

Returns:coding type for string.
Parameters:source – source string/unicode.

If the source string contains a coding specification within the first two lines, the specified coding is used, otherwise, UTF-8 is returned.

classmethod check_xfile(file_, xdir=None)[source]

Prepare extraction of a file.

Returns:

None, if the file already exists. Otherwise, the file directory is created and the absolute path name of the file is returned.

Parameters:
  • file – filename.
  • xdir – extraction directory. If it is None, extract_dir is used.

If file_ is None, empty or -, the filename - is returned.

If file_ starts with a slash /, xdir is ignored, otherwise, xdir is prepended to file_.

classmethod col_param_closure()[source]

Closure for setting up maximum width, padding and separator for table columns.

Returns:a setter and a getter function for calculating the maximum width of a list of strings (e.g. a table column).
>>> set_, get_ = AdHoc.col_param_closure()
>>> i = set_("string")
>>> get_()
[6, '      ', '======']
>>> i = set_("str")
>>> get_()
[6, '      ', '======']
>>> i = set_("longer string")
>>> get_()
[13, '             ', '=============']
>>> table_in = """\
... Column1 Column2
... some text text
... some-more-text text text
... something text
... less"""

A splitter and column parameters depending on column count:

>>> col_count = 2
>>> splitter = lambda line: line.split(' ', col_count-1)
>>> col_params = [AdHoc.col_param_closure() for i in range(col_count)]

Generic table processor:

>>> process_cols = lambda cols: [
...     col_params[indx][0](col) for indx, col in enumerate(cols)]
>>> table = [process_cols(cols) for cols in
...          [splitter(line) for line in table_in.splitlines()]]

Generic table output parameters/functions:

>>> mws = [cp[1]()[0] for cp in col_params]
>>> sep = ' '.join([cp[1]()[2] for cp in col_params])
>>> paddings = [cp[1]()[1] for cp in col_params]
>>> pad_cols_c = lambda cols: [
...     (((paddings[indx] is None) and (col))
...      or ((paddings[indx][:int((mws[indx]-len(col))/2)]
...           + col + paddings[indx])[:mws[indx]]))
...     for indx, col in enumerate(cols)]
>>> pad_cols = lambda cols: [
...     (((paddings[indx] is None) and (col))
...      or ((col + paddings[indx])[:mws[indx]]))
...     for indx, col in enumerate(cols)]

Generic table output generator:

>>> output = []
>>> if table:
...     output.append(sep)
...     output.append(' '.join(pad_cols_c(table.pop(0))).rstrip())
...     if table: output.append(sep)
...     output.extend([' '.join(pad_cols(cols)).rstrip()
...                    for cols in table])
...     output.append(sep)
>>> i = sys.stdout.write("\n".join(output))
============== =========
   Column1      Column2
============== =========
some           text text
some-more-text text text
something      text
less
============== =========
classmethod collapse_macros(source, macro_xdef_dlm=None)[source]
compile(string, name=None, for_=None, zipped=True, forced=None)[source]

Compile a string into adhoc output.

compileFile(file_name, for_=None, zipped=True, forced=None)[source]

Compile a file into adhoc output.

Since a module that has RtAdHoc defined is already adhoc’ed, the run-time RtAdHoc method returns the file source as is.

compile_(string, name=None, for_=None, zipped=True, forced=None)[source]

Entry point for compilation.

Returns:

string with fully compiled adhoc source. Includes run-time class, imports, packed includes, verbatim includes, enabled/disabled sections.

Parameters:
  • string – input string, with @:adhoc:@ flags.
  • name – for messages.
  • forRtAdHoc method call.
  • zipped – if True, gzip included files.

Note

for @:adhoc:@, commented lines, e.g. # import module # @:adhoc:@, are ignored.

debug = False

If True, display debug messages.

classmethod decode_source(source)[source]

Decode source to unicode.

Parameters:source – source string (may already be unicode).

If the source string contains a coding specification within the first two lines, the specified coding is used, otherwise, UTF-8 is applied.

classmethod disable_sections(string, symbol_or_re, is_re=False)[source]
>>> section = """\
... prefix
...   @:adhoc_disable_check:@
...   line 1
...     line 2
...
...   line 3
...   @:adhoc_disable_check:@
...   suffix\
... """
>>> printf(AdHoc.disable_sections(section, "adhoc_disable_check"))
prefix
  @:adhoc_disable_check:@
  # line 1
  #   line 2

  # line 3
  @:adhoc_disable_check:@
  suffix
classmethod disable_transform(section, headline=None)[source]

Disable section transform callback.

classmethod enable_sections(string, symbol_or_re, is_re=False)[source]
>>> section = """\
... # prefix
...   # @:adhoc_enable_check:@
...   #line 1
...   #  line 2
...   #
...   # line 3
...   # @:adhoc_enable_check:@
...   # suffix\
... """
>>> printf(AdHoc.enable_sections(section, "adhoc_enable_check"))
# prefix
  # @:adhoc_enable_check:@
  line 1
   line 2

  line 3
  # @:adhoc_enable_check:@
  # suffix
classmethod encode_source(source)[source]

Encode source from unicode.

Parameters:source – source string (may already be encoded).

If the source string contains a coding specification within the first two lines, the specified coding is used, otherwise, UTF-8 is applied.

classmethod expand_macros(source, macro_call_dlm=None, macro_xdef_dlm=None)[source]
>>> AdHoc.macros['uc_descr_end'] = (
...     '# o:' 'adhoc_template:>\n'
...     '# <:' 'adhoc_uncomment:>\n'
...     )
>>> macro_source = '# ' + AdHoc.adhoc_tag('uc_descr_end', AdHoc.macro_call_delimiters) + '\n'
>>> ign = sys.stdout.write(macro_source) 
# @|:uc_descr_end...:|>
>>> ign = sys.stdout.write(AdHoc.expand_macros(macro_source)) 
# <|:adhoc_macro_call...:|@
# @|:uc_descr_end...:|>
# <|:adhoc_macro_call...:|@
# <|:adhoc_macro_expansion...:|@
# o:adhoc_template...:>
# <:adhoc_uncomment...:>
# <|:adhoc_macro_expansion...:|@
export_dir = '__adhoc__'

Export directory (for export(), --explode).

classmethod export_source(string, no_remove=False, no_disable=False)[source]
check for @:adhoc_remove:@ sections and remove them!
check for @:adhoc_import:@ sections and remove them!
check for @:adhoc_unpack:@ sections and remove them!
check for @:adhoc_template_v:@ sections and remove them!
check for @:adhoc_disable:@ sections and enable them!
check for @:adhoc_enable:@ sections and disable them!
check for @:adhoc_remove_:@ section markers and rename them!
extra_templates = []

List of additional templates:

[(name, type), ...]
classmethod extract(file_=None, source=None)[source]

Unpack all adhoc’ed files in @:adhoc_unpack:@ sections and extract all templates.

extract_dir = '.'

Export directory (for extract(), --extract).

classmethod extract_templates(file_=None, source=None, tag=None, is_re=False, ignore_mark=False, export=False)[source]

Extract template.

# @:adhoc_template_check:@ -mark A template ... # @:adhoc_template_check:@

# @:adhoc_template_check:@ -other Another interleaved # @:adhoc_template_check:@

# @:adhoc_template_check:@ -mark continued # @:adhoc_template_check:@

>>> AdHoc.extract_templates(
...     tag=AdHoc.section_tag("adhoc_template_check"))
        A template ...
        continued
        Another interleaved
>>> rt_section = AdHoc.get_templates(
...     __file__, None,
...     tag=AdHoc.section_tag("adhoc_run_time_section"),
...     ignore_mark=True)
>>> rt_section = ''.join(rt_section.values())
flat = True

If True, do not export files recursively.

forced = False

If True, allow duplicate imports.

frozen = False

If True, do not attempt to load modules from external sources (|:todo:| not implemented).

classmethod get_named_template(name=None, file_=None, source=None, tag=None, is_re=False, ignore_mark=False)[source]

Extract templates matching section tag and name.

Parameters:
  • name – Template name. If None, standard output name - is used.
  • tag – If None, adhoc_template(_v)? is used.
  • ignore_mark – If True, all templates are mapped to standard output name -.

If a named template cannot be found and name does not start with -, the template name -name is tried.

>>> ign = main("adhoc.py --template adhoc_test.sub".split())
# -*- coding: utf-8 -*-

ADHOC_TEST_SUB_IMPORTED = True
classmethod get_templates(file_=None, source=None, tag=None, is_re=False, ignore_mark=False, all_=False)[source]

Extract templates matching section tag.

Parameters:
  • ignore_mark – If True, all templates are mapped to standard output name -.
  • tag – If None, adhoc_template is used.
classmethod has_expanded_macros(source, macro_xdef_dlm=None)[source]
classmethod import_(mod_name=None, file_=None, mtime=None, mode=None, zipped=True, flat=None, source64=None)[source]

Import adhoc’ed module.

classmethod inc_delimiters()[source]

Duplicate outer delimiter characters.

Returns:saved delimiter state suitable for reset_delimiters().

E.g.:

"@:", ":@" => "@@:", ":@@"

See set_delimiters() for doctest example.

include_(string, name=None, zipped=True, flat=None)[source]

Entry point for inclusion.

Returns:

string with packed included files.

Parameters:
  • string – input string, with @:adhoc_include:@ flags.
  • name – ignored. (API compatibility with AdHoc.compile_()).
  • zipped – if True, gzip included files.

Note

double commented flags, e.g. ## @:adhoc_include:@, are ignored.

>>> section = """\
... some
... @:""" """adhoc_include:@ Makefile
... text\
... """
>>> adhoc = AdHoc()
>>> source = adhoc.include_(section)
>>> printf(source) 
some
@:adhoc_include... Makefile
# @:adhoc_unpack...
RtAdHoc.unpack_(None, file_='Makefile',
    mtime='...', mode=...,
    zipped=True, flat=None, source64=
...
# @:adhoc_unpack...
text
include_path = []

Search path for include files. Only relevant during compilation.

classmethod indent_sections(string, symbol_or_re, is_re=False)[source]
>>> section = """\
... # prefix
...   # @:adhoc_indent_check:@ +4
...   #line 1
...   #  line 2
...   #
...   # line 3
...   # @:adhoc_indent_check:@
...   # suffix\
... """
>>> printf(AdHoc.indent_sections(section, "adhoc_indent_check"))
# prefix
  # @:adhoc_indent_check:@ +4
      #line 1
      #  line 2
      #
      # line 3
      # @:adhoc_indent_check:@
  # suffix
>>> printf(AdHoc.indent_sections(section.replace("+4", "-1"),
...        "adhoc_indent_check"))
# prefix
  # @:adhoc_indent_check:@ -1
 #line 1
 #  line 2
 #
 # line 3
  # @:adhoc_indent_check:@
  # suffix
line_delimiters = ('@:', ':@')

Tag delimiters for lines.

classmethod line_tag(symbol_or_re, is_re=False)[source]

Make a line tag from symbol or regular expression.

Returns:

unicode string.

Parameters:
  • symbol_or_re – symbol string or regular expresssion.
  • is_re – if True, escape the delimiters for regular expressions.
classmethod line_tag_parse(tagged_line, symbol_or_re=None, is_re=False, strip_comment=None)[source]

Parse a line tag line into tag-symbol and argument parts.

Returns:a tuple (tag-symbol, tag-arguments).

See adhoc_parse_line().

classmethod line_tag_remove(string, symbol_or_re, is_re=False, delimiters=None)[source]

Remove tagged lines.

Default tag delimiters are line_delimiters.

>>> tpl = AdHoc.get_named_template("col-param-closure")
classmethod line_tag_rename(string, symbol_or_re, renamed, is_re=False, delimiters=None)[source]

Rename tag-symbol.

Default tag delimiters are line_delimiters.

>>> tpl = AdHoc.get_named_template("col-param-closure")
classmethod line_tag_strip(tagged_line, symbol_or_re=None, is_re=False, strip_comment=None)[source]

Remove tag and optionally comment from line tag line.

Returns:tag arguments.

See adhoc_parse_line().

macro_call_delimiters = ('@|:', ':|>')

Macro delimiters

macro_xdef_delimiters = ('<|:', ':|@')

Macro expansion delimiters

macros = {}

Macros

classmethod module_setup(module=None, file_=None, mtime=None, source=None, mode=None)[source]

Setup module for AdHoc. |:todo:| various modes are possible: - always use newest version (development) (currently implemented) - always use adhoc’ed version (freeze) (not implemented)

classmethod pack_file(source, zipped=True)[source]

Optionally gzip a file and base64-encode it.

Returns:

base64-encoded unicode string.

Parameters:
  • source – string to be packed.
  • zipped – if True, gzip source before base64-encoding. (Default: True).
quiet = False

If True, suppress warnings.

classmethod read_source(file_, decode=True)[source]

Read source from file.

Returns:unicode string.
Parameters:file – If None, empty or -, sys.stdin is used, otherwise the file is read from file_ and decoded with decode_source().
classmethod remove_sections(string, symbol_or_re, is_re=False)[source]

Remove sections.

classmethod reset_delimiters(delimiter_state)[source]

Reset line/section delimiters from saved state.

Parameters:delimiter_state – delimiter state as returned by set_delimiters().
section_delimiters = ('@:', ':@')

Tag delimiters for sections.

classmethod section_tag(symbol_or_re, is_re=False)[source]

Make a section tag from symbol or regular expression.

Returns:

unicode string.

Parameters:
  • symbol_or_re – symbol string or regular expresssion.
  • is_re – if True, escape the delimiters for regular expressions.
classmethod section_tag_parse(tagged_line, symbol_or_re=None, is_re=False, strip_comment=None)[source]

Parse a section tag line into tag-symbol and argument parts.

Returns:a tuple (tag-symbol, tag-arguments).

See adhoc_parse_line().

classmethod section_tag_remove(string, symbol_or_re, is_re=False)[source]

Remove lines tagged with section_delimiters.

>>> tpl = AdHoc.get_named_template("col-param-closure")
>>> res = AdHoc.section_tag_remove(tpl, "adhoc_run_time_section")
>>> res = '\n'.join(res.splitlines()[:4])
>>> printf(str(res)) 
    @classmethod
    def col_param_closure(cls):...
        ...Closure for setting up maximum width, padding and separator
        for table columns.
classmethod section_tag_rename(string, symbol_or_re, renamed, is_re=False)[source]

Rename tag-symbol of lines tagged with section_delimiters.

>>> tpl = AdHoc.get_named_template("col-param-closure")
>>> res = AdHoc.section_tag_rename(tpl, "adhoc_run_time_section", "should_be_kept")
>>> res = '\n'.join(res.splitlines()[:4])
>>> printf(str(res)) 
    # @:should_be_kept:@ on
    @classmethod
    def col_param_closure(cls):...
        # @:should_be_kept:@ off
classmethod section_tag_strip(tagged_line, symbol_or_re=None, is_re=False, strip_comment=None)[source]

Remove tag and optionally comment from section tag line.

Returns:tag arguments.

See adhoc_parse_line().

classmethod set_delimiters(line_delimiters=None, section_delimiters=None)[source]

Set line/section delimiters.

Returns:

saved delimiter state suitable for reset_delimiters().

Parameters:
  • line_delimiters – the line delimiters. If None, line delimiters are not changed.
  • section_delimiters – the section delimiters. If None, line_delimiters is used.

If both line_delimiters and section_delimiters are None, the delimiter state is returned without any modification to the current delimiters.

>>> AdHoc.set_delimiters()
(('@:', ':@'), ('@:', ':@'))
>>> sv = AdHoc.inc_delimiters()
>>> sv
(('@:', ':@'), ('@:', ':@'))
>>> AdHoc.set_delimiters()
(('@@:', ':@@'), ('@@:', ':@@'))
>>> AdHoc.reset_delimiters(sv)
>>> AdHoc.set_delimiters()
(('@:', ':@'), ('@:', ':@'))
>>> AdHoc.set_delimiters(('<:', ':>'))
(('@:', ':@'), ('@:', ':@'))
>>> AdHoc.set_delimiters()
(('<:', ':>'), ('<:', ':>'))
>>> AdHoc.reset_delimiters(sv)
>>> AdHoc.set_delimiters()
(('@:', ':@'), ('@:', ':@'))
classmethod std_source_param(file_=None, source=None)[source]

Setup standard source parameters.

Returns:

tuple ( file_, source )

Parameters:
  • file – If None, __file__ is used. If it ends with .pyc, it is transformed to .py.
  • source – If None, the result of read_source() is used.
classmethod std_template_param(file_=None, source=None, tag=None, is_re=False, all_=False)[source]

Setup standard template parameters.

Parameters:tag – If None, section tag adhoc_template(_v)? is used.

See std_source_param() for file_ and source.

classmethod strptime(date_string, format_)[source]

Python 2.4 compatible

classmethod tag_lines(string, tag, is_re=False)[source]

Get lines matching tag.

Returns:list of tag lines.

See tag_split().

classmethod tag_partition(string, tag, is_re=False, headline=False)[source]

Split the string into body parts and sections.

If headline is True, the starting tag line is included for sections.

classmethod tag_sections(string, tag, is_re=False, headline=False)[source]

Split the string into sections.

If headline is True, the starting tag line is included.

See tag_partition().

classmethod tag_split(string, tag, is_re=False)[source]

Split string with tag line.

Returns:a list of tuples with a flag and a section:
[(is_tag, section), ... ]

Example

>>> source = AH_CHECK_SOURCE
>>> printf(str(source), end='')
not in section
# >:cmd:< arg0 arg1 # comment
# <:tag:> on
in section
# >:cmd:< arg2 arg3 # comment
in section
# <:tag:> off
not in section
# <:tag2:> on
in section
in section
# <:tag2:> off
not in section

Split on literal tag

>>> is_re = False
>>> tag = AdHoc.adhoc_tag('tag', ('<:', ':>'), is_re)
>>> parts = AdHoc.tag_split(source, tag, is_re)
>>> adhoc_dump_sections(parts, 40)
#   :DBG:   section[0]             : ][False, 'not in section\n# >:cmd:< arg0 arg1 #  ...'][
#   :DBG:   section[1]             : ][True, '# <:tag:> on\n'][
#   :DBG:   section[2]             : ][False, 'in section\n# >:cmd:< arg2 arg3 # comm ...'][
#   :DBG:   section[3]             : ][True, '# <:tag:> off\n'][
#   :DBG:   section[4]             : ][False, 'not in section\n# <:tag2:> on\nin secti ...'][

Split on tag regexp

>>> is_re = True
>>> tag = AdHoc.adhoc_tag('tag.?', ('<:', ':>'), is_re)
>>> parts = AdHoc.tag_split(source, tag, is_re)
>>> adhoc_dump_sections(parts, 40)
#   :DBG:   section[0]             : ][False, 'not in section\n# >:cmd:< arg0 arg1 #  ...'][
#   :DBG:   section[1]             : ][True, '# <:tag:> on\n'][
#   :DBG:   section[2]             : ][False, 'in section\n# >:cmd:< arg2 arg3 # comm ...'][
#   :DBG:   section[3]             : ][True, '# <:tag:> off\n'][
#   :DBG:   section[4]             : ][False, 'not in section\n'][
#   :DBG:   section[5]             : ][True, '# <:tag2:> on\n'][
#   :DBG:   section[6]             : ][False, 'in section\nin section\n'][
#   :DBG:   section[7]             : ][True, '# <:tag2:> off\n'][
#   :DBG:   section[8]             : ][False, 'not in section\n'][

Assemble section

>>> section = []
>>> in_section = False
>>> for part in parts:
...     if part[0]:
...         in_section = not in_section
...         continue
...     if in_section:
...         section.append(part[1])
>>> section = ''.join(section)
>>> printf(str(section), end='')
in section
# >:cmd:< arg2 arg3 # comment
in section
in section
in section
classmethod template_list(file_=None, source=None, tag=None, is_re=False, all_=False)[source]

Sorted list of templates.

See std_template_param() for file_, source, tag, is_re.

>>> for tpl in AdHoc.template_list():
...     printf(tpl)
-
README.txt
-adhoc_init
-catch-stdout
-col-param-closure
doc/USE_CASES.txt
doc/index.rst
-max-width-class
-rst-to-ascii
-test
>>> for tpl in AdHoc.template_list(all_=True):
...     printf(strclean(tpl))
('-', 'adhoc_template')
('README.txt', 'adhoc_template')
('-adhoc_init', 'adhoc_template')
('-catch-stdout', 'adhoc_template')
('-col-param-closure', 'adhoc_template')
('doc/USE_CASES.txt', 'adhoc_template')
('doc/index.rst', 'adhoc_template')
('-max-width-class', 'adhoc_template')
('-rst-to-ascii', 'adhoc_template')
('-test', 'adhoc_template')
template_process_hooks = {}

Dictionary of template-name, hook-function items.

If the name of a template section matches an item in this dictionary, the hook-function is called:

section = hook-function(cls, section, tag, template_name)
classmethod template_table(file_=None, source=None, tag=None, is_re=False)[source]

Table of template commands.

See std_template_param() for file_, source, tag, is_re.

classmethod transform_lines(transform, string, symbol_or_re, is_re=False, delimiters=None)[source]

Split string into line tag lines and other sections; call transform callback on each tagged line.

Returns:transformed string.
Parameters:transform – callback which receives argument tagged-line.
classmethod transform_sections(transform, string, symbol_or_re, is_re=False)[source]

Split string into sections and call transform callback on each section.

Returns:transformed string.
Parameters:transform – callback which receives and returns arguments section, headline.
uc_type

alias of unicode

classmethod unpack(file_=None, source=None)[source]

Unpack all adhoc’ed files in @:adhoc_unpack:@ sections.

classmethod unpack_(mod_name=None, file_=None, mtime=None, mode=None, zipped=True, flat=None, source64=None)[source]

Unpack adhoc’ed file, if it does not exist.

classmethod unpack_file(source64, zipped=True, decode=True)[source]

Base64-decode a file and optionally ungzip it.

Returns:

unicode string if decode is True.

Parameters:
  • source64 – base64 encoded unicode string to be unpacked.
  • zipped – if True, ungzip source after base64-decoding. (Default: True).
verbatim_(string, name=None)[source]

Entry point for verbatim inclusion.

Returns:

string with verbatim included files.

Parameters:
  • string – input string, with @:adhoc_verbatim:@ flags.
  • name – ignored. (API compatibility with AdHoc.compile_()).

Note

double commented flags, e.g. ## @:adhoc_verbatim:@, are ignored.

>>> section = """\
... some
...     @:""" """adhoc_verbatim:@ {flags} my_verbatim{from_}
... text\
... """
>>> adhoc = AdHoc()

Non-existent File

>>> sv_quiet = AdHoc.quiet
>>> AdHoc.quiet = True
>>> source = adhoc.verbatim_(sformat(section, flags="-2#", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... -2# my_verbatim
text
>>> AdHoc.quiet = sv_quiet

Empty File

>>> source = adhoc.verbatim_(sformat(section, flags="", from_=" from /dev/null"))
>>> printf(source) 
some
    @:adhoc_verbatim...  my_verbatim from /dev/null
    # @:adhoc_remove...
    # @:adhoc_indent... -4
    # @:adhoc_template_v... my_verbatim
    # @:adhoc_template_v...
    # @:adhoc_indent...
    # @:adhoc_remove...
text

Empty file, with negative indent, commented

>>> source = adhoc.verbatim_(sformat(section, flags="-2#", from_=" from /dev/null"))
>>> printf(source) 
some
    @:adhoc_verbatim... -2# my_verbatim from /dev/null
  # @:adhoc_remove...
  # @:adhoc_uncomment...
  # @:adhoc_indent... -2
  # @:adhoc_template_v... my_verbatim
  # @:adhoc_template_v...
  # @:adhoc_indent...
  # @:adhoc_uncomment...
  # @:adhoc_remove...
text

Empty file, with overflowing negative indent, commented

>>> source = adhoc.verbatim_(sformat(section, flags="-8#", from_=" from /dev/null"))
>>> printf(source) 
some
    @:adhoc_verbatim... -8# my_verbatim from /dev/null
# @:adhoc_remove...
# @:adhoc_uncomment...
# @:adhoc_template_v... my_verbatim
# @:adhoc_template_v...
# @:adhoc_uncomment...
# @:adhoc_remove...
text

Existing file, without newline at end of file, commented.

>>> mvf = open("my_verbatim", "w")
>>> ign = mvf.write("no end of line")
>>> mvf.close()
>>> source = adhoc.verbatim_(sformat(section, flags="-4#", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... -4# my_verbatim
# @:adhoc_remove...
# @:adhoc_uncomment...
# @:adhoc_template_v... my_verbatim
# no end of line
# @:adhoc_template_v...
# @:adhoc_uncomment...
# @:adhoc_remove...
text

Existing file, with extra newline at end of file, commented.

>>> mvf = open("my_verbatim", "w")
>>> ign = mvf.write("extra end of line\n\n")
>>> mvf.close()
>>> source = adhoc.verbatim_(sformat(section, flags="-4#", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... -4# my_verbatim
# @:adhoc_remove...
# @:adhoc_uncomment...
# @:adhoc_template_v... my_verbatim
# extra end of line

# @:adhoc_template_v...
# @:adhoc_uncomment...
# @:adhoc_remove...
text

Existing file, without newline at end of file, not commented.

>>> mvf = open("my_verbatim", "w")
>>> ign = mvf.write("no end of line")
>>> mvf.close()
>>> source = adhoc.verbatim_(sformat(section, flags="-4", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... -4 my_verbatim
# @:adhoc_remove...
# @:adhoc_template_v... my_verbatim
no end of line
# @:adhoc_template_v...
# @:adhoc_remove...
text

Existing file, with extra newline at end of file, not commented.

>>> mvf = open("my_verbatim", "w")
>>> ign = mvf.write("extra end of line\n\n")
>>> mvf.close()
>>> source = adhoc.verbatim_(sformat(section, flags="", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... my_verbatim
    # @:adhoc_remove...
    # @:adhoc_indent:@ -4
    # @:adhoc_template_v... my_verbatim
    extra end of line

    # @:adhoc_template_v...
    # @:adhoc_indent:@
    # @:adhoc_remove...
text

Existing file, but override with source /dev/null.

>>> source = adhoc.verbatim_(sformat(section, flags="/dev/null as", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... /dev/null as my_verbatim
    # @:adhoc_remove...
    # @:adhoc_indent... -4
    # @:adhoc_template_v... my_verbatim
    # @:adhoc_template_v...
    # @:adhoc_indent...
    # @:adhoc_remove...
text

Existing file, override with non-existing source /not-here/.

>>> if os.path.exists("not-here"):
...     os.unlink("not-here")
>>> source = adhoc.verbatim_(sformat(section, flags="not-here as", from_=""))
>>> printf(source) 
some
    @:adhoc_verbatim... not-here as my_verbatim
    # @:adhoc_remove...
    # @:adhoc_indent... -4
    # @:adhoc_template_v... my_verbatim
    extra end of line

    # @:adhoc_template_v...
    # @:adhoc_indent...
    # @:adhoc_remove...
text
>>> os.unlink("my_verbatim")
verbose = False

If True, display messages.

classmethod write_source(file_, source, mtime=None, mode=None)[source]

Write source to file.

Parameters:file – If None, empty or -, sys.stdout is used, otherwise the file is written to file_ after encoding with encode_source().
adhoc.adhoc_check_module_setup()[source]
>>> state = catch_stdout()
>>> adhoc_check_module_setup()
>>> contents = restore_stdout(state)
>>> contents = re.sub('(mtime.*\])[^[]*(\[)', r'\1\2', contents)
>>> contents = re.sub(' at 0x([0-9a-f]+)', '', contents)
>>> contents = re.sub(r'adhoc\.pyc', 'adhoc.py', contents)
>>> contents = '\n'.join([l.strip() for l in contents.splitlines()])
>>> printf(contents, end='') 
# --------------------------------------------------
# |||:CHP:||| adhoc_check_module_setup
# --------------------------------------------------
# -----------------------------------
# ||:SEC:|| no:module:found
# -----------------------------------
#   :DBG:   module                 : ]['__adhoc__', '__doc__', '__name__'...][
# ------------------------------
#   :DBG:   __adhoc__              : ]...
#   :DBG:   __doc__                : ]None[
...
# --------------------
#  |:INF:|  no:module:found.__adhoc__
# --------------------
#   :DBG:   __adhoc__              : ]...
# ------------------------------
#   :DBG:   __module__             : ]<module 'no:module:found' (built-in)>[
#   :DBG:   mode                   : ]...[
#   :DBG:   mtime                  : ][
# -----------------------------------
# ||:SEC:|| adhoc_test.sub
# -----------------------------------
#   :DBG:   module                 : ]['ADHOC_TEST_SUB_IMPORTED',...
# ------------------------------
#   :DBG:   ADHOC_TEST_SUB_IMPORTED: ]True[
#   :DBG:   __adhoc__              : ]...
...
#   :DBG:   __doc__                : ]None[
#   :DBG:   __file__               : ]...adhoc_test/sub/__init__.py...[
...
# --------------------
#  |:INF:|  adhoc_test.sub.__adhoc__
# --------------------
#   :DBG:   __adhoc__              : ]...
# ------------------------------
#   :DBG:   __module__             : ]<module 'adhoc_test.sub' from...
...
#   :DBG:   source                 : ]...# -*- coding: utf-8 -*-\n\nADHOC_TEST_SUB_IMPORTED = True\n...[
# -----------------------------------
# ||:SEC:|| adhoc
# -----------------------------------
#   :DBG:   adhoc                  : ]...
# ------------------------------
#   :DBG:   AH_CHECK_SOURCE          : ]...
...
#   :DBG:   AdHoc                    : ]<class 'adhoc.AdHoc'>[
#   :DBG:   AdHocError               : ]...adhoc.AdHocError...[
...
#   :DBG:   RST_HEADER               : ]...
...
#   :DBG:   __adhoc__                : ]...
...
#   :DBG:   __file__                 : ].../adhoc.py...[
#   :DBG:   __name__                 : ]adhoc[
...
#   :DBG:   _nativestr               : ]<function _nativestr>[
#   :DBG:   _quiet                   : ]False[
#   :DBG:   _uc                      : ]<function ...>[
#   :DBG:   _utf8str                 : ]<function _utf8str>[
#   :DBG:   _verbose                 : ]False[
#   :DBG:   adhoc_check_encode_module: ]<function adhoc_check_encode_module>[
#   :DBG:   adhoc_check_module_setup : ]<function adhoc_check_module_setup>[
#   :DBG:   adhoc_check_modules      : ]<function adhoc_check_modules>[
#   :DBG:   adhoc_check_packing      : ]<function adhoc_check_packing>[
#   :DBG:   adhoc_dump_list          : ]<function adhoc_dump_list>[
#   :DBG:   adhoc_dump_sections      : ]<function adhoc_dump_sections>[
#   :DBG:   adhoc_rst_to_ascii       : ]<function adhoc_rst_to_ascii>[
#   :DBG:   adhoc_run_time_module    : ]<function adhoc_run_time_module>[
#   :DBG:   adhoc_test               : ]<module 'adhoc_test' from '...adhoc_test/__init__.py...'>[
#   :DBG:   base64                   : ]<module 'base64' from '.../base64.py...'>[
#   :DBG:   catch_stdout             : ]<function catch_stdout>[
#   :DBG:   compile_                 : ]<function compile_>[
#   :DBG:   dbg_comm                 : ]# [
#   :DBG:   dbg_fwid                 : ]23[
#   :DBG:   dbg_twid                 : ]9[
#   :DBG:   dict_dump                : ]<function dict_dump>[
#   :DBG:   ditems                   : ]<function <lambda>>[
#   :DBG:   dkeys                    : ]<function <lambda>>[
#   :DBG:   doc_index_rst_tag_symbols: ]('adhoc_index_only',)[
#   :DBG:   dump_attr                : ]<function dump_attr>[
#   :DBG:   dvalues                  : ]<function <lambda>>[
#   :DBG:   file_encoding_is_clean   : ]True[
#   :DBG:   get_readme               : ]<function get_readme>[
#   :DBG:   get_use_cases            : ]<function get_use_cases>[
#   :DBG:   hl                       : ]<function hl>[
#   :DBG:   hl_lvl                   : ]<function hl_lvl>[
#   :DBG:   hlc                      : ]<function hlc>[
#   :DBG:   hlcr                     : ]<function hlcr>[
#   :DBG:   hlr                      : ]<function hlssr>[
#   :DBG:   hls                      : ]<function hls>[
#   :DBG:   hlsr                     : ]<function hlsr>[
#   :DBG:   hlss                     : ]<function hlss>[
#   :DBG:   hlssr                    : ]<function hlssr>[
#   :DBG:   inc_template_marker      : ]<function inc_template_marker>[
#   :DBG:   isstring                 : ]<function isstring>[
#   :DBG:   main                     : ]<function main>[
#   :DBG:   mw_                      : ]<class 'adhoc.mw_'>[
#   :DBG:   mwg_                     : ]<class 'adhoc.mwg_'>[
#   :DBG:   namespace_dict           : ]<module 'namespace_dict' from '...namespace_dict.py...'>[
#   :DBG:   nativestr                : ]<function nativestr>[
#   :DBG:   os                       : ]<module 'os' from '.../os.py...'>[
#   :DBG:   printe                   : ]<function printe>[
#   :DBG:   printf                   : ]<...function print...>[
#   :DBG:   re                       : ]<module 're' from '.../re.py...'>[
#   :DBG:   restore_stdout           : ]<function restore_stdout>[
#   :DBG:   rst_to_ascii             : ]<function rst_to_ascii>[
#   :DBG:   run                      : ]<function run>[
#   :DBG:   setdefaultencoding       : ]<function setdefaultencoding>[
#   :DBG:   sformat                  : ]<function sformat>[
...
#   :DBG:   sys                      : ]<module 'sys' (built-in)>[
#   :DBG:   tpl_hook_doc_index_rst   : ]<function tpl_hook_doc_index_rst>[
#   :DBG:   tpl_hook_readme          : ]<function tpl_hook_readme>[
#   :DBG:   uc                       : ]<function uc>[
#   :DBG:   uc_type                  : ]<...>[
#   :DBG:   urllib                   : ]<module 'urllib' from '.../urllib...'>[
#   :DBG:   utf8str                  : ]<function utf8str>[
# --------------------
#  |:INF:|  adhoc.__adhoc__
# --------------------
#   :DBG:   __adhoc__              : ]...
# ------------------------------
#   :DBG:   __module__             : ]<module 'adhoc' from '.../adhoc.py...'>[
#   :DBG:   mode                   : ]...[
#   :DBG:   mtime                  : ][
#   :DBG:   source                 : ]#!...python...\n# -*- coding: utf-8 -*-\n# Copyright (C)...
...
adhoc.adhoc_check_packing()[source]
>>> source = AdHoc.read_source(__file__)
>>> AdHoc.write_source('write-check', source)
>>> rsource = AdHoc.read_source('write-check')
>>> os.unlink('write-check')
>>> (source == rsource)
True
>>> psource = AdHoc.pack_file(source, zipped=False)
>>> usource = AdHoc.unpack_file(psource, zipped=False)
>>> (source == usource)
True
>>> psource = AdHoc.pack_file(source, zipped=True)
>>> usource = AdHoc.unpack_file(psource, zipped=True)
>>> (source == usource)
True
adhoc.adhoc_rst_to_ascii(string)[source]

Transform ReST documentation to ASCII.

adhoc.catch_stdout()[source]

Install a string IO as sys.stdout.

Returns:a state variable that is needed by restore_stdout() to retrieve the output as string.
adhoc.compile_(files=None)[source]

Compile files or standard input.

adhoc.dict_dump(dict_, wid=0, trunc=0, commstr=None, tag=None, out=None)[source]

Dump a dictionary.

adhoc.restore_stdout(state)[source]

Restore capturing sys.stdout and get captured output.

Returns:captured output as string.
Parameters:state – state variable obtained from catch_stdout().
adhoc.rst_to_ascii(string, header_footer=False)[source]

Convert ReST documentation to ASCII.

adhoc.run(parameters, pass_opts)[source]

Application runner, when called as __main__.

adhoc.strclean(value)[source]

Make a copy of any structure with all strings converted to native strings.

strclean() is good for __str__() methods.

It is needed for doctest output that should be compatible with both python2 and python3.

The output structure is not necessarily an exact copy of the input structure, since objects providing iterator or item interfaces are only copied through those!

NameSpace/NameSpaceDict

namespace_dict.py - dictionary based namespace

usage: namespace_dict.py [OPTIONS]
or import namespace_dict

Options

--template extract minimized version of NameSpaceNS
-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.
--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__)
--implode implode script with adhoc
-t, --test run doc tests

Description

The namespace functions are wrapped in class NameSpaceNS, which itself serves as a namespace container.

The namespace class generator NameSpaceNS.namespace() is exported as NameSpaceMeta.

A namespace class inheriting from object, without dict interface is defined as NameSpace.

A namespace class inheriting from object, with complete dict interface is defined as NameSpaceDict.

The –template option

This implementation is compatible with Python 2.4+ and Python 3.

Examples

>>> ns = NameSpace()
>>> ns.attrib = 'value'
>>> ns.attrib2 = 'value2'
>>> printf(str(vars(ns)))
{'attrib2': 'value2', 'attrib': 'value'}

While a normal dict has special attributes

>>> dict().__setattr__ 
<method-wrapper ...>

the namespace dict special attributes are hidden:

>>> ns.__setattr__ 
Traceback (most recent call last):
...
AttributeError: 'namespace_' object has no attribute '__setattr__'

The only special attributes supported are

  • __dict__ to access the namespace dictionary

    This allows access to the dictionary via vars():

    >>> vars(ns)['another'] = 'entry'
    >>> printf(str(vars(ns)))
    {'attrib2': 'value2', 'attrib': 'value', 'another': 'entry'}
    
  • _property_ to access the namespace class object

    >>> ns._property_.__class__.__name__
    'NameSpace'
    
    >>> ns._property_.__class__.__base__.__name__
    'namespace_'
    
  • __class__ to access the namespace closure class

    >>> ns.__class__.__name__
    'namespace_'
    
    >>> ns.__class__.__base__.__name__
    'object'
    

Module Members

class namespace_dict.NameSpace(*args, **kwargs)[source]

Bases: namespace_dict.namespace_

Namespace class inheriting from object, without dict interface.

Defined as: class NameSpace(NameSpaceMeta()):

class namespace_dict.NameSpaceDict(*args, **kwargs)[source]

Bases: namespace_dict.namespace_

Namespace class inheriting from object, with complete dict interface.

Defined as: class NameSpace(NameSpaceMeta(expose_dict=2)):

namespace_dict.NameSpaceMeta = <bound method type.namespace of <class 'namespace_dict.NameSpaceNS'>>

Namespace (meta-) class generator.

NameSpaceMeta(for_=object, expose_dict=0)

class namespace_dict.NameSpaceNS[source]

Bases: object

Class based namespace for dict based namespace.

The dictonary interface of the namespace dict can be exposed on 3 levels:

  1. expose_dict=0: No dict interface
  2. expose_dict=1: dict interface for namespace object
  3. expose_dict=2: dict interface for namespace class object
classmethod namespace(nsc, for_=<type 'object'>, expose_dict=0)[source]

Namespace (meta-) class generator.

classmethod namespace_closure(nsc, expose_dict)[source]

Namespace closure.

classmethod property_(nsc, obj, expose_dict)[source]

Property instance generator.

static property_closure(obj, expose_dict)[source]

Namespace class object property closure.