<commit_before>"""
Command line interface for pygount.
"""
# Copyright (c) 2016, Thomas Aglassinger.
# All rights reserved. Distributed under the BSD License.
import argparse
import logging
import os
import sys

import pygount.analysis
import pygount.common
import pygount.write

#: Valid formats for option --format.
_VALID_FORMATS = ('cloc-xml', 'sloccount')

_DEFAULT_ENCODING = 'automatic'
_DEFAULT_OUTPUT_FORMAT = 'sloccount'
_DEFAULT_OUTPUT = 'STDOUT'
_DEFAULT_SOURCE_PATTERNS = os.curdir
_DEFAULT_SUFFIXES = '*'

_HELP_ENCODING = '''encoding to use when reading source code; use "automatic"
 to take BOMs, XML prolog and magic headers into account and fall back to
 UTF-8 or CP1252 if none fits; use "automatic;<fallback>" to specify a
 different fallback encoding than CP1252; use "chardet" to let the chardet
 package determine the encoding; default: "%(default)s"'''

_HELP_EPILOG = '''SHELL-PATTERN is a pattern using *, ? and ranges like [a-z]
 as placeholders. PATTERNS is a comma separated list of SHELL-PATTERN. The
 prefix [regex] indicated that the PATTERNS use regular expression syntax. If
 default values are available, [...] indicates that the PATTERNS extend the
 existing default values.'''

_HELP_FORMAT = 'output format, one of: {0}; default: "%(default)s"'.format(
    ', '.join(['"' + format + '"' for format in _VALID_FORMATS]))

_HELP_GENERATED = '''comma separated list of regular expressions to detect
 generated code; default: %(default)s'''

_HELP_FOLDERS_TO_SKIP = '''comma separated list of glob patterns for folder
 names not to analyze. Use "..." as first entry to append patterns to the
 default patterns; default: %(default)s'''

_HELP_NAMES_TO_SKIP = '''comma separated list of glob patterns for file names
 not to analyze. Use "..." as first entry to append patterns to the default
 patterns; default: %(default)s'''

_HELP_SUFFIX = '''limit analysis on files matching any suffix in comma
 separated LIST; shell patterns are possible; example: "py,sql"; default:
 "%(default)s"'''

_log = logging.getLogger('pygount')

def _check_encoding(name, encoding_to_check, alternative_encoding, source=None):
    """
    Check that ``encoding`` is a valid Python encoding
    :param name: name under which the encoding is known to the user, e.g. 'default encoding'
    :param encoding_to_check: name of the encoding to check, e.g. 'utf-8'
    :param source: source where the encoding has been set, e.g. option name
    :raise pygount.common.OptionError if ``encoding`` is not a valid Python encoding
    """
    assert name is not None

    if encoding_to_check not in (alternative_encoding, 'chardet', None):
        try:
            ''.encode(encoding_to_check)
        except LookupError:
            raise pygount.common.OptionError(
                '{0} is "{1}" but must be "{2}" or a known Python encoding'.format(
                    name, encoding_to_check, alternative_encoding),
                source)

class Command():
    """
    Command interface for pygount, where options starting with defaults can
    gradually be set and finally :py:meth:`execute()`.
    """
    def __init__(self):
        self.set_encodings(_DEFAULT_ENCODING)
        self._has_duplicates = False
        self._folders_to_skip = pygount.common.regexes_from(pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT)
        self._generated_regexs = pygount.common.regexes_from(pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT)
        self._is_verbose = False
        self._names_to_skip = pygount.common.regexes_from(pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT)
        self._output = _DEFAULT_OUTPUT
        self._output_format = _DEFAULT_OUTPUT_FORMAT
        self._source_patterns = _DEFAULT_SOURCE_PATTERNS
        self._suffixes = pygount.common.regexes_from(_DEFAULT_SUFFIXES)

    def set_encodings(self, encoding, source=None):
        encoding_is_chardet = (encoding == 'chardet') or (encoding.startswith('chardet;'))
        if encoding_is_chardet and not pygount.analysis.has_chardet:  # pragma: no cover
            raise pygount.common.OptionError(
                'chardet must be installed to set default encoding to "chardet"')
        if encoding in ('automatic', 'chardet'):
            default_encoding = encoding
            fallback_encoding = None
        else:
            if encoding.startswith('automatic;') or encoding.startswith('chardet;'):
                first_encoding_semicolon_index = encoding.find(';')
                default_encoding = encoding[:first_encoding_semicolon_index]
                fallback_encoding = encoding[first_encoding_semicolon_index + 1:]
            else:
                default_encoding = encoding
                fallback_encoding = pygount.analysis.DEFAULT_FALLBACK_ENCODING
        self.set_default_encoding(default_encoding, source)
        self.set_fallback_encoding(fallback_encoding, source)

    @property
    def default_encoding(self):
        return self._default_encoding

    def set_default_encoding(self, default_encoding, source=None):
        _check_encoding('default encoding', default_encoding, 'automatic', source)
        self._default_encoding = default_encoding

    @property
    def fallback_encoding(self):
        return self._fallback_encoding

    def set_fallback_encoding(self, fallback_encoding, source=None):
        _check_encoding('fallback encoding', fallback_encoding, 'automatic', source)
        self._fallback_encoding = fallback_encoding

    @property
    def folders_to_skip(self):
        return self._folders_to_skip

    def set_folders_to_skip(self, regexes_or_patterns_text, source=None):
        self._folders_to_skip = pygount.common.regexes_from(
            regexes_or_patterns_text,
            pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT,
            source)

    @property
    def generated_regexps(self):
        return self._generated_regexs

    def set_generated_regexps(self, regexes_or_patterns_text, source=None):
        self._generated_regexs = pygount.common.regexes_from(
            regexes_or_patterns_text,
            pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT,
            source)

    @property
    def has_duplicates(self):
        return self._has_duplicates

    def set_has_duplicates(self, has_duplicates, source=None):
        self._has_duplicates = bool(has_duplicates)

    @property
    def is_verbose(self):
        return self._is_verbose

    def set_is_verbose(self, is_verbose, source=None):
        self._is_verbose = bool(is_verbose)

    @property
    def names_to_skip(self):
        return self._names_to_skip

    def set_names_to_skip(self, regexes_or_pattern_text, source=None):
        self._names_to_skip = pygount.common.regexes_from(
            regexes_or_pattern_text,
            pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT,
            source)

    @property
    def output(self):
        return self._output

    def set_output(self, output, source=None):
        assert output is not None
        self._output = output

    @property
    def output_format(self):
        return self._output_format

    def set_output_format(self, output_format, source=None):
        assert output_format is not None
        if output_format not in _VALID_FORMATS:
            raise pygount.common.OptionError(
                'format is {0} but must be one of: {1}'.format(output_format, _VALID_FORMATS),
                source)
        self._output_format = output_format

    @property
    def source_patterns(self):
        return self._source_patterns

    def set_source_patterns(self, glob_patterns_or_text, source=None):
        assert glob_patterns_or_text is not None
        self._source_patterns = pygount.common.as_list(glob_patterns_or_text)
        assert len(self._source_patterns) >= 0

    @property
    def suffixes(self):
        return self._suffixes

    def set_suffixes(self, regexes_or_patterns_text, source=None):
        assert regexes_or_patterns_text is not None
        self._suffixes = pygount.common.regexes_from(
            regexes_or_patterns_text, _DEFAULT_SUFFIXES, source)

    def argument_parser(self):
        parser = argparse.ArgumentParser(
            description='count source lines of code',
            epilog=_HELP_EPILOG)
        parser.add_argument('--duplicates', '-d', action='store_true', help='analyze duplicate files')
        parser.add_argument(
            '--encoding', '-e', default=_DEFAULT_ENCODING, help=_HELP_ENCODING
        )
        parser.add_argument(
            '--folders-to-skip', '-F', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT,
            help=_HELP_FOLDERS_TO_SKIP
        )
        parser.add_argument(
            '--format', '-f', metavar='FORMAT', choices=_VALID_FORMATS,
            default=_DEFAULT_OUTPUT_FORMAT,
            help=_HELP_FORMAT
        )
        parser.add_argument(
            '--generated', '-g', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT,
            help=_HELP_GENERATED
        )
        parser.add_argument(
            '--names-to-skip', '-N', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT,
            help=_HELP_NAMES_TO_SKIP
        )
        parser.add_argument(
            '--out', '-o', metavar='FILE', default=_DEFAULT_OUTPUT,
            help='file to write results to; use "STDOUT" for standard output; default: "%(default)s"'
        )
        parser.add_argument(
            '--suffix', '-s', metavar='PATTERNS',
            default=_DEFAULT_SUFFIXES,
            help=_HELP_SUFFIX
        )
        parser.add_argument(
            'source_patterns', metavar='SHELL-PATTERN', nargs='*',
            default=[os.getcwd()],
            help='source files and directories to scan; can use glob patterns; default: current directory')
        parser.add_argument('--verbose', '-v', action='store_true', help='explain what is being done')
        parser.add_argument('--version', action='version', version='%(prog)s ' + pygount.common.__version__)
        return parser

    def parsed_args(self, arguments):
        assert arguments is not None

        parser = self.argument_parser()
        args = parser.parse_args(arguments)
        if args.encoding == 'automatic':
            default_encoding = args.encoding
            fallback_encoding = None
        elif args.encoding == 'chardet':
            if not pygount.analysis.has_chardet:  # pragma: no cover
                parser.error('chardet must be installed in order to specify --encoding=chardet')
            default_encoding = args.encoding
            fallback_encoding = None
        else:
            if args.encoding.startswith('automatic;'):
                first_encoding_semicolon_index = args.encoding.find(';')
                default_encoding = args.encoding[:first_encoding_semicolon_index]
                fallback_encoding = args.encoding[first_encoding_semicolon_index + 1:]
                encoding_to_check = ('fallback encoding', fallback_encoding)
            else:
                default_encoding = args.encoding
                fallback_encoding = None
                encoding_to_check = ('encoding', default_encoding)
            if encoding_to_check is not None:
                name, encoding = encoding_to_check
                try:
                    ''.encode(encoding)
                except LookupError:
                    parser.error('{0} specified with --encoding must be a known Python encoding: {1}'.format(
                        name, encoding))
        return args, default_encoding, fallback_encoding

    def apply_arguments(self, arguments=None):
        if arguments is None:  # pragma: no cover
            arguments = sys.argv[1:]
        args, default_encoding, fallback_encoding = self.parsed_args(arguments)
        self.set_default_encoding(default_encoding, 'option --encoding')
        self.set_fallback_encoding(fallback_encoding, 'option --encoding')
        self.set_folders_to_skip(args.folders_to_skip, 'option --folders-to-skip')
        self.set_generated_regexps(args.generated, 'option --generated')
        self.set_has_duplicates(args.duplicates, 'option --duplicates')
        self.set_is_verbose(args.verbose, 'option --verbose')
        self.set_names_to_skip(args.names_to_skip, 'option --folders-to-skip')
        self.set_output(args.out, 'option --out')
        self.set_output_format(args.format, 'option --format')
        self.set_source_patterns(args.source_patterns, 'option PATTERNS')
        self.set_suffixes(args.suffix, 'option --suffix')

    def execute(self):
        _log.setLevel(logging.INFO if self.is_verbose else logging.WARNING)
        source_scanner = pygount.analysis.SourceScanner(
            self.source_patterns,
            self.suffixes)
        source_paths_and_groups_to_analyze = list(source_scanner.source_paths())
        duplicate_pool = pygount.analysis.DuplicatePool() if not self.has_duplicates else None

        if self.output == 'STDOUT':
            target_file = sys.stdout
            has_target_file_to_close = False
        else:
            target_file = open(self.output, 'w', encoding='utf-8', newline='')
            has_target_file_to_close = True

        try:
            if self.output_format == 'cloc-xml':
                writer_class = pygount.write.ClocXmlWriter
            else:
                assert self.output_format == 'sloccount'
                writer_class = pygount.write.LineWriter
            with writer_class(target_file) as writer:
                for source_path, group in source_paths_and_groups_to_analyze:
                    statistics = pygount.analysis.source_analysis(
                        source_path, group, self.default_encoding, self.fallback_encoding,
                        generated_regexes=self._generated_regexs,
                        duplicate_pool=duplicate_pool
                    )
                    writer.add(statistics)
        finally:
            if has_target_file_to_close:
                try:
                    target_file.close()
                except Exception as error:
                    raise OSError(
                        'cannot write output to "{0}": {1}'.format(self.output, error))

def pygount_command(arguments=None):
    result = 1
    command = Command()
    try:
        command.apply_arguments(arguments)
        command.execute()
        result = 0
    except KeyboardInterrupt:  # pragma: no cover
        _log.error('interrupted as requested by user')
    except (pygount.common.OptionError, OSError) as error:
        _log.error(error)
    except Exception as error:
        _log.exception(error)

    return result

def main():  # pragma: no cover
    logging.basicConfig(level=logging.WARNING)
    sys.exit(pygount_command())

if __name__ == '__main__':  # pragma: no cover
    main()
<commit_msg>Implemented --summary parameter Ouptuts summary by source type.<commit_after>"""
Command line interface for pygount.
"""
# Copyright (c) 2016, Thomas Aglassinger.
# All rights reserved. Distributed under the BSD License.
import argparse
import logging
import os
import sys

import pygount.analysis
import pygount.common
import pygount.write

#: Valid formats for option --format.
_VALID_FORMATS = ('cloc-xml', 'sloccount')

_DEFAULT_ENCODING = 'automatic'
_DEFAULT_OUTPUT_FORMAT = 'sloccount'
_DEFAULT_OUTPUT = 'STDOUT'
_DEFAULT_SOURCE_PATTERNS = os.curdir
_DEFAULT_SUFFIXES = '*'

_HELP_ENCODING = '''encoding to use when reading source code; use "automatic"
 to take BOMs, XML prolog and magic headers into account and fall back to
 UTF-8 or CP1252 if none fits; use "automatic;<fallback>" to specify a
 different fallback encoding than CP1252; use "chardet" to let the chardet
 package determine the encoding; default: "%(default)s"'''

_HELP_EPILOG = '''SHELL-PATTERN is a pattern using *, ? and ranges like [a-z]
 as placeholders. PATTERNS is a comma separated list of SHELL-PATTERN. The
 prefix [regex] indicated that the PATTERNS use regular expression syntax. If
 default values are available, [...] indicates that the PATTERNS extend the
 existing default values.'''

_HELP_FORMAT = 'output format, one of: {0}; default: "%(default)s"'.format(
    ', '.join(['"' + format + '"' for format in _VALID_FORMATS]))

_HELP_GENERATED = '''comma separated list of regular expressions to detect
 generated code; default: %(default)s'''

_HELP_FOLDERS_TO_SKIP = '''comma separated list of glob patterns for folder
 names not to analyze. Use "..." as first entry to append patterns to the
 default patterns; default: %(default)s'''

_HELP_NAMES_TO_SKIP = '''comma separated list of glob patterns for file names
 not to analyze. Use "..." as first entry to append patterns to the default
 patterns; default: %(default)s'''

_HELP_SUFFIX = '''limit analysis on files matching any suffix in comma
 separated LIST; shell patterns are possible; example: "py,sql"; default:
 "%(default)s"'''

_log = logging.getLogger('pygount')

def _check_encoding(name, encoding_to_check, alternative_encoding, source=None):
    """
    Check that ``encoding`` is a valid Python encoding
    :param name: name under which the encoding is known to the user, e.g. 'default encoding'
    :param encoding_to_check: name of the encoding to check, e.g. 'utf-8'
    :param source: source where the encoding has been set, e.g. option name
    :raise pygount.common.OptionError if ``encoding`` is not a valid Python encoding
    """
    assert name is not None

    if encoding_to_check not in (alternative_encoding, 'chardet', None):
        try:
            ''.encode(encoding_to_check)
        except LookupError:
            raise pygount.common.OptionError(
                '{0} is "{1}" but must be "{2}" or a known Python encoding'.format(
                    name, encoding_to_check, alternative_encoding),
                source)

class Command():
    """
    Command interface for pygount, where options starting with defaults can
    gradually be set and finally :py:meth:`execute()`.
    """
    def __init__(self):
        self.set_encodings(_DEFAULT_ENCODING)
        self._has_duplicates = False
        self._folders_to_skip = pygount.common.regexes_from(pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT)
        self._generated_regexs = pygount.common.regexes_from(pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT)
        self._is_verbose = False
        self._names_to_skip = pygount.common.regexes_from(pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT)
        self._output = _DEFAULT_OUTPUT
        self._output_format = _DEFAULT_OUTPUT_FORMAT
        self._source_patterns = _DEFAULT_SOURCE_PATTERNS
        self._suffixes = pygount.common.regexes_from(_DEFAULT_SUFFIXES)
        self._summary = False

    def set_encodings(self, encoding, source=None):
        encoding_is_chardet = (encoding == 'chardet') or (encoding.startswith('chardet;'))
        if encoding_is_chardet and not pygount.analysis.has_chardet:  # pragma: no cover
            raise pygount.common.OptionError(
                'chardet must be installed to set default encoding to "chardet"')
        if encoding in ('automatic', 'chardet'):
            default_encoding = encoding
            fallback_encoding = None
        else:
            if encoding.startswith('automatic;') or encoding.startswith('chardet;'):
                first_encoding_semicolon_index = encoding.find(';')
                default_encoding = encoding[:first_encoding_semicolon_index]
                fallback_encoding = encoding[first_encoding_semicolon_index + 1:]
            else:
                default_encoding = encoding
                fallback_encoding = pygount.analysis.DEFAULT_FALLBACK_ENCODING
        self.set_default_encoding(default_encoding, source)
        self.set_fallback_encoding(fallback_encoding, source)

    @property
    def default_encoding(self):
        return self._default_encoding

    def set_default_encoding(self, default_encoding, source=None):
        _check_encoding('default encoding', default_encoding, 'automatic', source)
        self._default_encoding = default_encoding

    @property
    def fallback_encoding(self):
        return self._fallback_encoding

    def set_fallback_encoding(self, fallback_encoding, source=None):
        _check_encoding('fallback encoding', fallback_encoding, 'automatic', source)
        self._fallback_encoding = fallback_encoding

    @property
    def folders_to_skip(self):
        return self._folders_to_skip

    def set_folders_to_skip(self, regexes_or_patterns_text, source=None):
        self._folders_to_skip = pygount.common.regexes_from(
            regexes_or_patterns_text,
            pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT,
            source)

    @property
    def generated_regexps(self):
        return self._generated_regexs

    def set_generated_regexps(self, regexes_or_patterns_text, source=None):
        self._generated_regexs = pygount.common.regexes_from(
            regexes_or_patterns_text,
            pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT,
            source)

    @property
    def has_duplicates(self):
        return self._has_duplicates

    def set_has_duplicates(self, has_duplicates, source=None):
        self._has_duplicates = bool(has_duplicates)

    @property
    def is_verbose(self):
        return self._is_verbose

    def set_is_verbose(self, is_verbose, source=None):
        self._is_verbose = bool(is_verbose)

    def set_show_summary(self, show_summary, source=None):
        self._summary = bool(show_summary)

    @property
    def names_to_skip(self):
        return self._names_to_skip

    def set_names_to_skip(self, regexes_or_pattern_text, source=None):
        self._names_to_skip = pygount.common.regexes_from(
            regexes_or_pattern_text,
            pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT,
            source)

    @property
    def output(self):
        return self._output

    def set_output(self, output, source=None):
        assert output is not None
        self._output = output

    @property
    def output_format(self):
        return self._output_format

    def set_output_format(self, output_format, source=None):
        assert output_format is not None
        if output_format not in _VALID_FORMATS:
            raise pygount.common.OptionError(
                'format is {0} but must be one of: {1}'.format(output_format, _VALID_FORMATS),
                source)
        self._output_format = output_format

    @property
    def source_patterns(self):
        return self._source_patterns

    def set_source_patterns(self, glob_patterns_or_text, source=None):
        assert glob_patterns_or_text is not None
        self._source_patterns = pygount.common.as_list(glob_patterns_or_text)
        assert len(self._source_patterns) >= 0

    @property
    def suffixes(self):
        return self._suffixes

    def set_suffixes(self, regexes_or_patterns_text, source=None):
        assert regexes_or_patterns_text is not None
        self._suffixes = pygount.common.regexes_from(
            regexes_or_patterns_text, _DEFAULT_SUFFIXES, source)

    def argument_parser(self):
        parser = argparse.ArgumentParser(
            description='count source lines of code',
            epilog=_HELP_EPILOG)
        parser.add_argument('--duplicates', '-d', action='store_true', help='analyze duplicate files')
        parser.add_argument(
            '--encoding', '-e', default=_DEFAULT_ENCODING, help=_HELP_ENCODING
        )
        parser.add_argument(
            '--folders-to-skip', '-F', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_FOLDER_PATTERNS_TO_SKIP_TEXT,
            help=_HELP_FOLDERS_TO_SKIP
        )
        parser.add_argument(
            '--format', '-f', metavar='FORMAT', choices=_VALID_FORMATS,
            default=_DEFAULT_OUTPUT_FORMAT,
            help=_HELP_FORMAT
        )
        parser.add_argument(
            '--generated', '-g', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_GENERATED_PATTERNS_TEXT,
            help=_HELP_GENERATED
        )
        parser.add_argument(
            '--names-to-skip', '-N', metavar='PATTERNS',
            default=pygount.analysis.DEFAULT_NAME_PATTERNS_TO_SKIP_TEXT,
            help=_HELP_NAMES_TO_SKIP
        )
        parser.add_argument(
            '--out', '-o', metavar='FILE', default=_DEFAULT_OUTPUT,
            help='file to write results to; use "STDOUT" for standard output; default: "%(default)s"'
        )
        parser.add_argument(
            '--suffix', '-s', metavar='PATTERNS',
            default=_DEFAULT_SUFFIXES,
            help=_HELP_SUFFIX
        )
        parser.add_argument(
            'source_patterns', metavar='SHELL-PATTERN', nargs='*',
            default=[os.getcwd()],
            help='source files and directories to scan; can use glob patterns; default: current directory')
        parser.add_argument('--verbose', '-v', action='store_true', help='explain what is being done')
        parser.add_argument('--version', action='version', version='%(prog)s ' + pygount.common.__version__)
        parser.add_argument('--summary', action='store_true', default=False,
            help='show summary')
        return parser

    def parsed_args(self, arguments):
        assert arguments is not None

        parser = self.argument_parser()
        args = parser.parse_args(arguments)
        if args.encoding == 'automatic':
            default_encoding = args.encoding
            fallback_encoding = None
        elif args.encoding == 'chardet':
            if not pygount.analysis.has_chardet:  # pragma: no cover
                parser.error('chardet must be installed in order to specify --encoding=chardet')
            default_encoding = args.encoding
            fallback_encoding = None
        else:
            if args.encoding.startswith('automatic;'):
                first_encoding_semicolon_index = args.encoding.find(';')
                default_encoding = args.encoding[:first_encoding_semicolon_index]
                fallback_encoding = args.encoding[first_encoding_semicolon_index + 1:]
                encoding_to_check = ('fallback encoding', fallback_encoding)
            else:
                default_encoding = args.encoding
                fallback_encoding = None
                encoding_to_check = ('encoding', default_encoding)
            if encoding_to_check is not None:
                name, encoding = encoding_to_check
                try:
                    ''.encode(encoding)
                except LookupError:
                    parser.error('{0} specified with --encoding must be a known Python encoding: {1}'.format(
                        name, encoding))
        return args, default_encoding, fallback_encoding

    def apply_arguments(self, arguments=None):
        if arguments is None:  # pragma: no cover
            arguments = sys.argv[1:]
        args, default_encoding, fallback_encoding = self.parsed_args(arguments)
        self.set_default_encoding(default_encoding, 'option --encoding')
        self.set_fallback_encoding(fallback_encoding, 'option --encoding')
        self.set_folders_to_skip(args.folders_to_skip, 'option --folders-to-skip')
        self.set_generated_regexps(args.generated, 'option --generated')
        self.set_has_duplicates(args.duplicates, 'option --duplicates')
        self.set_is_verbose(args.verbose, 'option --verbose')
        self.set_names_to_skip(args.names_to_skip, 'option --folders-to-skip')
        self.set_output(args.out, 'option --out')
        self.set_output_format(args.format, 'option --format')
        self.set_source_patterns(args.source_patterns, 'option PATTERNS')
        self.set_suffixes(args.suffix, 'option --suffix')
        self.set_show_summary(args.summary, 'option --summary')

    def execute(self):
        _log.setLevel(logging.INFO if self.is_verbose else logging.WARNING)
        source_scanner = pygount.analysis.SourceScanner(
            self.source_patterns,
            self.suffixes)
        source_paths_and_groups_to_analyze = list(source_scanner.source_paths())
        duplicate_pool = pygount.analysis.DuplicatePool() if not self.has_duplicates else None

        if self.output == 'STDOUT':
            target_file = sys.stdout
            has_target_file_to_close = False
        else:
            target_file = open(self.output, 'w', encoding='utf-8', newline='')
            has_target_file_to_close = True

        try:
            if self.output_format == 'cloc-xml':
                writer_class = pygount.write.ClocXmlWriter
            else:
                assert self.output_format == 'sloccount'
                writer_class = pygount.write.LineWriter
            with writer_class(target_file) as writer:
                summary = {}

                for source_path, group in source_paths_and_groups_to_analyze:
                    statistics = pygount.analysis.source_analysis(
                        source_path, group, self.default_encoding, self.fallback_encoding,
                        generated_regexes=self._generated_regexs,
                        duplicate_pool=duplicate_pool
                    )
                    if self._summary:
                        if statistics.language not in summary:
                            # summary[statistics.language] = statistics
                            summary[statistics.language] = pygount.analysis.SourceAnalysis(
                                path="",
                                language=statistics.language,
                                group=statistics.group,
                                code=statistics.code,
                                documentation=statistics.documentation,
                                empty=statistics.empty,
                                string=statistics.string,
                                state=statistics.state,
                                state_info=statistics.state_info
                            )
                        else:
                            summary[statistics.language] = pygount.analysis.SourceAnalysis(
                                path="",
                                language=statistics.language,
                                group=summary[statistics.language].group,
                                code=summary[statistics.language].code + statistics.code,
                                documentation=summary[statistics.language].documentation + statistics.documentation,
                                empty=summary[statistics.language].empty + statistics.empty,
                                string=summary[statistics.language].string + statistics.string,
                                state=statistics.state,
                                state_info=statistics.state_info
                            )
                    else:
                        writer.add(statistics)

                # Adding summary lines to output
                for language,value in summary.items():
                    writer.add(value)
        finally:
            print(self._summary)
            if has_target_file_to_close:
                try:
                    target_file.close()
                except Exception as error:
                    raise OSError(
                        'cannot write output to "{0}": {1}'.format(self.output, error))

def pygount_command(arguments=None):
    result = 1
    command = Command()
    try:
        command.apply_arguments(arguments)
        command.execute()
        result = 0
    except KeyboardInterrupt:  # pragma: no cover
        _log.error('interrupted as requested by user')
    except (pygount.common.OptionError, OSError) as error:
        _log.error(error)
    except Exception as error:
        _log.exception(error)

    return result

def main():  # pragma: no cover
    logging.basicConfig(level=logging.WARNING)
    sys.exit(pygount_command())

if __name__ == '__main__':  # pragma: no cover
    main()
<|endoftext|>


<commit_before>try:
	from browser import window, document
	from javascript import JSObject, JSConstructor
	from ggame import *

	jq = window.jQuery

	if not jq(".inputScreen").length:
		jq("body").append('

<input type = "text" id = "toInput"><input type = "submit" id = "toSubmit">

')
		jq(".inputScreen").hide()

	input_queue = []
	winput_queue = []
	#App1 = App
	winput_started = False
	def input_callback():
		input_value = jq('#toInput').val()
		jq('#toInput').val('')

		input_t = jq('#toPrompt').text()
		jq('#toPrompt').text('')

		global input_queue

		print(input_t + " " + input_value)
		input_queue[0][1](input_t, input_value)
		input_queue.pop(0)
		if len(input_queue) > 0:
			inputStart(input_queue[0][0])

	def input_fade(ev):
		jq('.inputScreen').fadeOut(300, input_callback)
		jq('#toSubmit').off('click')

	def inputStart(text):
		jq('.inputScreen').fadeIn(300)
		jq('#toPrompt').text(text)
		jq('#toSubmit').on('click', input_fade)

	def input(text, callback):
		global input_queue
		input_queue.append([text, callback])
		if len(input_queue) == 1:
			inputStart(text)

	def winput_callback():
		winput_value = App._win._w.document.getElementById('toInput').value
		App._win._w.document.getElementById('toInput').value = ''

		winput_t = App._win._w.document.getElementById('toPrompt').textContent
		App._win._w.document.getElementById('toPrompt').textContent = ""

		global winput_queue

		print(winput_t + " " + winput_value)
		winput_queue[0][1](winput_t, winput_value)
		winput_queue.pop(0)
		if len(winput_queue) > 0:
			winputStart(winput_queue[0][0])

	def winput_fade(ev):
		App._win._w.document.getElementById('inputScreen').style.display = "none"
		winput_callback()
		App._win._w.document.getElementById('toSubmit').removeEventListener('click', winput_fade)

	def winputStart(text):
		App._win._w.document.getElementById('inputScreen').style.display = "block"
		App._win._w.document.getElementById('toPrompt').textContent = text
		App._win._w.document.getElementById('toSubmit').addEventListener('click', winput_fade)

	def winput(text, callback):
		global winput_queue
		global winput_started
		winput_queue.append([text, callback])
		if winput_started:
			winputStart(text)
			winput_started = False
			print("superWin")
		print("winning")

	def winput_init():
		global winput_started
		global winput_queue
		winput_started = True
		winputStart(winput_queue[0][0])
		print("started")
		print(winput_queue[0][0])

except:
	underInput = input
	def input(text, callback):
		x = underInput(text+" ")
		callback(text, x)

#def first(text, result):
#    print("Hi " + result)
#    input("What's your favorite color?", second)

#def second(text, result):
#    print("Nice! I like " + result + " too.")

<commit_msg>Update pyinput.py<commit_after>try:
	from browser import window, document
	from javascript import JSObject, JSConstructor
	from ggame import *

	jq = window.jQuery

	if not jq(".inputScreen").length:
		jq("body").append('

<input type = "text" id = "toInput"><input type = "submit" id = "toSubmit">

')
		jq(".inputScreen").hide()

	input_queue = []
	winput_queue = []
	#App1 = App
	print(App.winput_ready)
	winput_started = False
	def input_callback():
		input_value = jq('#toInput').val()
		jq('#toInput').val('')

		input_t = jq('#toPrompt').text()
		jq('#toPrompt').text('')

		global input_queue

		print(input_t + " " + input_value)
		input_queue[0][1](input_t, input_value)
		input_queue.pop(0)
		if len(input_queue) > 0:
			inputStart(input_queue[0][0])

	def input_fade(ev):
		jq('.inputScreen').fadeOut(300, input_callback)
		jq('#toSubmit').off('click')

	def inputStart(text):
		jq('.inputScreen').fadeIn(300)
		jq('#toPrompt').text(text)
		jq('#toSubmit').on('click', input_fade)

	def input(text, callback):
		global input_queue
		input_queue.append([text, callback])
		if len(input_queue) == 1:
			inputStart(text)

	def winput_callback():
		winput_value = App._win._w.document.getElementById('toInput').value
		App._win._w.document.getElementById('toInput').value = ''

		winput_t = App._win._w.document.getElementById('toPrompt').textContent
		App._win._w.document.getElementById('toPrompt').textContent = ""

		global winput_queue

		print(winput_t + " " + winput_value)
		winput_queue[0][1](winput_t, winput_value)
		winput_queue.pop(0)
		if len(winput_queue) > 0:
			winputStart(winput_queue[0][0])

	def winput_fade(ev):
		App._win._w.document.getElementById('inputScreen').style.display = "none"
		winput_callback()
		App._win._w.document.getElementById('toSubmit').removeEventListener('click', winput_fade)

	def winputStart(text):
		App._win._w.document.getElementById('inputScreen').style.display = "block"
		App._win._w.document.getElementById('toPrompt').textContent = text
		App._win._w.document.getElementById('toSubmit').addEventListener('click', winput_fade)

	def winput(text, callback):
		global winput_queue
		global winput_started
		winput_queue.append([text, callback])
		if winput_started:
			winputStart(text)
			winput_started = False
			print("superWin")
		print("winning")

	def winput_init():
		global winput_started
		global winput_queue
		winput_started = True
		winputStart(winput_queue[0][0])
		print("started")
		print(winput_queue[0][0])

except:
	underInput = input
	def input(text, callback):
		x = underInput(text+" ")
		callback(text, x)

#def first(text, result):
#    print("Hi " + result)
#    input("What's your favorite color?", second)

#def second(text, result):
#    print("Nice! I like " + result + " too.")

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# SasView documentation build configuration file, created by
# sphinx-quickstart on Wed Aug 28 14:59:44 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os, collections

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
from distutils.util import get_platform
platform = '.%s-%s'%(get_platform(),sys.version[:3])
build_lib = os.path.abspath('../../../build/lib'+platform)
sys.path.insert(0, build_lib)
print "-- path --"
print "\n".join(sys.path)
import sans.sansview
from sans.sansview import __version__ as sasview_version
print "version:",sasview_version

# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
              'sphinx.ext.todo',
              'sphinx.ext.coverage',
              'sphinx.ext.mathjax',
              'sphinx.ext.viewcode']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'SasView'
copyright = u'2013, The SasView Project'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '3.0.0'
# The full version, including alpha/beta/rc tags.
release = '3.0.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
#
# PGP 2014/04/03: We have some code which doesn't get carried over to
# the build directory.  Exclude the appropriate *.rst files here so
# that we don't get various "ImportError: No module named ___" when
# running Sphinx.
exclude_patterns = ["*sans.perspectives.simulation.rst",
                    "*sans.pr.c_extensions.rst",
                    "*sans.realspace.rst",
                    "*sans.simulation.rst",]

# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# -- Options for HTML output ---------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'default'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'SasViewdoc'

# Turn off permalinks, which are a nice feature for the docs when viewed in a
# browser, but which look weird (and cannot be "right-click->copy url") in
# the SasView help.
html_add_permalinks = ""

# -- Options for LaTeX output --------------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
  ('index', 'SasView.tex', u'SasView Documentation',
   u'The SasView Project', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output --------------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'sasview', u'SasView Documentation',
     [u'The SasView Project'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output ------------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'SasView', u'SasView Documentation',
   u'The SasView Project', 'SasView', 'One line description of project.',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
<commit_msg>Refs #221 - Remove unnecessary sasview version finding code.<commit_after># -*- coding: utf-8 -*-
#
# SasView documentation build configuration file, created by
# sphinx-quickstart on Wed Aug 28 14:59:44 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.

import sys, os, collections

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
from distutils.util import get_platform
platform = '.%s-%s'%(get_platform(),sys.version[:3])
build_lib = os.path.abspath('../../../build/lib'+platform)
sys.path.insert(0, build_lib)

# -- General configuration -----------------------------------------------------

# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'

# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
              'sphinx.ext.todo',
              'sphinx.ext.coverage',
              'sphinx.ext.mathjax',
              'sphinx.ext.viewcode']

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The suffix of source filenames.
source_suffix = '.rst'

# The encoding of source files.
#source_encoding = 'utf-8-sig'

# The master toctree document.
master_doc = 'index'

# General information about the project.
project = u'SasView'
copyright = u'2013, The SasView Project'

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '3.0.0'
# The full version, including alpha/beta/rc tags.
release = '3.0.0'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None

# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
#
# PGP 2014/04/03: We have some code which doesn't get carried over to
# the build directory.  Exclude the appropriate *.rst files here so
# that we don't get various "ImportError: No module named ___" when
# running Sphinx.
exclude_patterns = ["*sans.perspectives.simulation.rst",
                    "*sans.pr.c_extensions.rst",
                    "*sans.realspace.rst",
                    "*sans.simulation.rst",]

# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None

# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True

# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True

# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []

# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False

# -- Options for HTML output ---------------------------------------------------

# The theme to use for HTML and HTML Help pages.  See the documentation for
# a list of builtin themes.
html_theme = 'default'

# Theme options are theme-specific and customize the look and feel of a theme
# further.  For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}

# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []

# The name for this set of Sphinx documents.  If None, it defaults to
# "<project> v<release> documentation".
#html_title = None

# A shorter title for the navigation bar.  Default is the same as html_title.
#html_short_title = None

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None

# The name of an image file (within the static path) to use as favicon of the
# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']

# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'

# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True

# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}

# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}

# If false, no module index is generated.
#html_domain_indices = True

# If false, no index is generated.
#html_use_index = True

# If true, the index is split into individual pages for each letter.
#html_split_index = False

# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True

# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True

# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True

# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it.  The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''

# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None

# Output file base name for HTML help builder.
htmlhelp_basename = 'SasViewdoc'

# Turn off permalinks, which are a nice feature for the docs when viewed in a
# browser, but which look weird (and cannot be "right-click->copy url") in
# the SasView help.
html_add_permalinks = ""

# -- Options for LaTeX output --------------------------------------------------

latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#'preamble': '',
}

# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
  ('index', 'SasView.tex', u'SasView Documentation',
   u'The SasView Project', 'manual'),
]

# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None

# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False

# If true, show page references after internal links.
#latex_show_pagerefs = False

# If true, show URL addresses after external links.
#latex_show_urls = False

# Documents to append as an appendix to all manuals.
#latex_appendices = []

# If false, no module index is generated.
#latex_domain_indices = True

# -- Options for manual page output --------------------------------------------

# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
    ('index', 'sasview', u'SasView Documentation',
     [u'The SasView Project'], 1)
]

# If true, show URL addresses after external links.
#man_show_urls = False

# -- Options for Texinfo output ------------------------------------------------

# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
#  dir menu entry, description, category)
texinfo_documents = [
  ('index', 'SasView', u'SasView Documentation',
   u'The SasView Project', 'SasView', 'One line description of project.',
   'Miscellaneous'),
]

# Documents to append as an appendix to all manuals.
#texinfo_appendices = []

# If false, no module index is generated.
#texinfo_domain_indices = True

# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
<|endoftext|>


<commit_before>"""Paster Commands, for use with paster in your project

The command(s) listed here are for use with Paste to enable easy creation of
various core Pylons templates.

Currently available commands are::

    controller, shell
"""
import os
import sys

import paste.fixture
import paste.registry
import paste.deploy.config
from paste.deploy import loadapp, appconfig
from paste.script.command import Command, BadCommand
from paste.script.filemaker import FileOp
from paste.script.pluginlib import find_egg_info_dir

import pylons.util as util

def can_import(name):
    """Attempt to __import__ the specified package/module, returning True when
    succeeding, otherwise False"""
    try:
        __import__(name)
        return True
    except ImportError:
        return False

def validate_name(name):
    """Validate that the name for the controller isn't present on the
    path already"""
    if not name:
        # This happens when the name is an existing directory
        raise BadCommand('Please give the name of a controller.')
    if can_import(name):
        raise BadCommand(
            "\n\nA module named '%s' is already present in your "
            "PYTHON_PATH.\nChoosing a conflicting name will likely cause "
            "import problems in\nyour controller at some point. It's "
            "suggested that you choose an\nalternate name, and if you'd "
            "like that name to be accessible as\n'%s', add a route "
            "to your projects config/routing.py file similar\nto:\n"
            "    map.connect('%s', controller='my_%s')" \
            % (name, name, name, name))
    return True

class ControllerCommand(Command):
    """Create a Controller and accompanying functional test

    The Controller command will create the standard controller template
    file and associated functional test to speed creation of controllers.

    Example usage::

        yourproj% paster controller comments
        Creating yourproj/yourproj/controllers/comments.py
        Creating yourproj/yourproj/tests/functional/test_comments.py

    If you'd like to have controllers underneath a directory, just include
    the path as the controller name and the necessary directories will be
    created for you::

        yourproj% paster controller admin/trackback
        Creating yourproj/controllers/admin
        Creating yourproj/yourproj/controllers/admin/trackback.py
        Creating yourproj/yourproj/tests/functional/test_admin_trackback.py
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 1
    max_args = 1
    group_name = 'pylons'

    default_verbosity = 3

    parser = Command.standard_parser(simulate=True)
    parser.add_option('--no-test',
                      action='store_true',
                      dest='no_test',
                      help="Don't create the test; just the controller")

    def command(self):
        """Main command to create controller"""
        try:
            file_op = FileOp(source_dir=os.path.join(
                os.path.dirname(__file__), 'templates'))
            try:
                name, directory = file_op.parse_path_name_args(self.args[0])
            except:
                raise BadCommand('No egg_info directory was found')

            # Check the name isn't the same as the package
            base_package = file_op.find_dir('controllers', True)[0]
            if base_package.lower() == name.lower():
                raise BadCommand(
                    'Your controller name should not be the same as '
                    'the package name %r.'% base_package
            )
            # Validate the name
            name = name.replace('-', '_')
            validate_name(name)

            # Check to see if PROJ.lib.base exists
            try:
                __import__(base_package + '.lib.base')
                importstatement = "from %s.lib.base import *" % base_package
            except:
                # Assume its the minimal template
                importstatement = "from %s.controllers import *" % base_package

            # Setup the controller
            fullname = os.path.join(directory, name)
            controller_name = util.class_name_from_module_name(
                name.split('/')[-1])
            if not fullname.startswith(os.sep):
                fullname = os.sep + fullname
            testname = fullname.replace(os.sep, '_')[1:]
            file_op.template_vars.update({'name': controller_name,
                                          'fname': os.path.join(directory, name),
                                          'importstatement': importstatement})
            file_op.copy_file(template='controller.py_tmpl',
                         dest=os.path.join('controllers', directory),
                         filename=name)
            if not self.options.no_test:
                file_op.copy_file(template='test_controller.py_tmpl',
                             dest=os.path.join('tests', 'functional'),
                             filename='test_'+testname)
        except BadCommand, e:
            raise BadCommand('An error occurred. %s' % e)
        except:
            msg = str(sys.exc_info()[1])
            raise BadCommand('An unknown error occurred. %s' % msg)

class RestControllerCommand(Command):
    """Create a REST Controller and accompanying functional test

    The RestController command will create a REST-based Controller file for use
    with the map.resource REST-based dispatching. This template includes the
    methods that map.resource dispatches to in addition to doc strings for
    clarification on when the methods will be called.

    The first argument should be the singular form of the REST resource. The
    second argument is the plural form of the word. If its a nested controller,
    put the directory information in front as shown in the second example
    below.

    Example usage::

        yourproj% paster restcontroller comment comments
        Creating yourproj/yourproj/controllers/comments.py
        Creating yourproj/yourproj/tests/functional/test_comments.py

    If you'd like to have controllers underneath a directory, just include
    the path as the controller name and the necessary directories will be
    created for you::

        yourproj% paster restcontroller admin/tracback admin/trackbacks
        Creating yourproj/controllers/admin
        Creating yourproj/yourproj/controllers/admin/trackbacks.py
        Creating yourproj/yourproj/tests/functional/test_admin_trackbacks.py
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 2
    max_args = 2
    group_name = 'pylons'

    default_verbosity = 3

    parser = Command.standard_parser(simulate=True)
    parser.add_option('--no-test',
                      action='store_true',
                      dest='no_test',
                      help="Don't create the test; just the controller")

    def command(self):
        """Main command to create controller"""
        try:
            file_op = FileOp(source_dir=os.path.join(
                os.path.dirname(__file__), 'templates'))
            try:
                singularname, singulardirectory = \
                    file_op.parse_path_name_args(self.args[0])
                pluralname, pluraldirectory = \
                    file_op.parse_path_name_args(self.args[1])
            except:
                raise BadCommand('No egg_info directory was found')

            # Check the name isn't the same as the package
            base_package = file_op.find_dir('controllers', True)[0]
            if base_package.lower() == pluralname.lower():
                raise BadCommand(
                    'Your controller name should not be the same as '
                    'the package name %r.'% base_package
            )
            # Validate the name
            for name in [singularname, pluralname]:
                name = name.replace('-', '_')
                validate_name(name)

            # Setup the controller
            fullname = os.path.join(pluraldirectory, pluralname)
            controller_name = util.class_name_from_module_name(
                pluralname.split('/')[-1])
            if not fullname.startswith(os.sep):
                fullname = os.sep + fullname
            testname = fullname.replace(os.sep, '_')[1:]

            nameprefix = ''
            if pluraldirectory:
                nameprefix = pluraldirectory.replace(os.path.sep, '_') + '_'

            controller_c = ''
            if nameprefix:
                controller_c = ", controller='%s', \n\t" % \
                    '/'.join([pluraldirectory, pluralname])
                controller_c += "path_prefix='/%s', name_prefix='%s_'" % \
                    (pluraldirectory, pluraldirectory)
            command = "map.resource('%s', '%s'%s)\n" % \
                (singularname, pluralname, controller_c)

            file_op.template_vars.update(
                {'classname': controller_name,
                 'pluralname': pluralname,
                 'singularname': singularname,
                 'name': controller_name,
                 'nameprefix': nameprefix,
                 'resource_command': command.replace('\n\t', '\n%s#%s' % \
                                                         (' '*4, ' '*9)),
                 'fname': os.path.join(pluraldirectory, pluralname)}
            )

            resource_command = ("\nTo create the appropriate RESTful mapping, "
                                "add a map statement to your\n")
            resource_command += ("config/routing.py file near the top like "
                                 "this:\n\n")
            resource_command += command
            file_op.copy_file(template='restcontroller.py_tmpl',
                         dest=os.path.join('controllers', pluraldirectory),
                         filename=pluralname)
            if not self.options.no_test:
                file_op.copy_file(template='test_controller.py_tmpl',
                             dest=os.path.join('tests', 'functional'),
                             filename='test_'+testname)
            print resource_command
        except BadCommand, e:
            raise BadCommand('An error occurred. %s' % e)
        except:
            msg = str(sys.exc_info()[1])
            raise BadCommand('An unknown error occurred. %s' % msg)

class ShellCommand(Command):
    """Open an interactive shell with the Pylons app loaded

    The optional CONFIG_FILE argument specifies the config file to use for
    the interactive shell. CONFIG_FILE defaults to 'development.ini'.

    This allows you to test your mapper, models, and simulate web requests
    using ``paste.fixture``.

    Example::

        $ paster shell my-development.ini
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 0
    max_args = 1
    group_name = 'pylons'

    parser = Command.standard_parser(simulate=True)

    def command(self):
        """Main command to create a new shell"""
        self.verbose = 3
        if len(self.args) == 0:
            # Assume the .ini file is ./development.ini
            config_file = 'development.ini'
            if not os.path.isfile(config_file):
                raise BadCommand('%sError: CONFIG_FILE not found at: .%s%s\n'
                                 'Please specify a CONFIG_FILE' % \
                                 (self.parser.get_usage(), os.path.sep,
                                  config_file))
        else:
            config_file = self.args[0]

        config_name = 'config:%s' % config_file
        here_dir = os.getcwd()
        locs = dict(__name__="pylons-admin")

        # Load app config into paste.deploy to simulate request config
        conf = appconfig(config_name, relative_to=here_dir)
        conf = dict(app_conf=conf.local_conf,
                    global_conf=conf.global_conf)
        paste.deploy.config.CONFIG.push_thread_config(conf)

        # Load locals and populate with objects for use in shell
        sys.path.insert(0, here_dir)

        # Load the wsgi app first so that everything is initialized right
        wsgiapp = loadapp(config_name, relative_to=here_dir)
        test_app = paste.fixture.TestApp(wsgiapp)

        # Query the test app to setup the environment
        tresponse = test_app.get('/_test_vars')
        request_id = int(tresponse.body)

        # Disable restoration during test_app requests
        test_app.pre_request_hook = lambda self: \
            paste.registry.restorer.restoration_end()
        test_app.post_request_hook = lambda self: \
            paste.registry.restorer.restoration_begin(request_id)

        # Restore the state of the Pylons special objects
        # (StackedObjectProxies)
        paste.registry.restorer.restoration_begin(request_id)

        # Determine the package name from the .egg-info top_level.txt.
        egg_info = find_egg_info_dir(here_dir)
        f = open(os.path.join(egg_info, 'top_level.txt'))
        packages = [l.strip() for l in f.readlines()
                    if l.strip() and not l.strip().startswith('#')]
        f.close()

        has_models = False
        found_base = False
        # Start the rest of our imports now that the app is loaded
        for pkg_name in packages:
            if not has_models:
                # The Minimal template lacks an official models package
                models_package = pkg_name + '.models'
                has_models = can_import(models_package)

            # Import all objects from the base module
            if not found_base:
                base_module = pkg_name + '.lib.base'
                found_base = can_import(base_module)
                if not found_base:
                    # Minimal template
                    base_module = pkg_name + '.controllers'
                    found_base = can_import(base_module)

        if not found_base:
            raise ImportError("Could not import base module. Are you sure this "
                              "is a Pylons app?")

        base = sys.modules[base_module]
        base_public = [__name for __name in dir(base) if not \
                       __name.startswith('_') or __name == '_']
        locs.update([(name, getattr(base, name)) for name in base_public])
        locs.update(
            dict(
                mapper=tresponse.pylons_config.map,
                wsgiapp=wsgiapp,
                app=test_app,
            )
        )
        if has_models:
            locs['model'] = sys.modules[models_package]

        banner = "  All objects from %s are available\n" % base_module
        banner += "  Additional Objects:\n"
        banner += "  %-10s -  %s\n" % ('mapper', 'Routes mapper object')
        if has_models:
            banner += "  %-10s -  %s\n" % ('model',
                                           'Models from models package')
        banner += "  %-10s -  %s\n" % ('wsgiapp',
            'This projects WSGI App instance')
        banner += "  %-10s -  %s\n" % ('app',
            'paste.fixture wrapped around wsgiapp')

        try:
            # try to use IPython if possible
            from IPython.Shell import IPShellEmbed

            shell = IPShellEmbed(user_ns=locs)
            shell.set_banner(shell.IP.BANNER + '\n\n' + banner)
            try:
                shell()
            finally:
                paste.registry.restorer.restoration_end()
        except ImportError:
            import code

            class CustomShell(code.InteractiveConsole):
                """Custom shell class to handle raw input"""
                def raw_input(self, *args, **kw):
                    """Capture raw input in exception wrapping"""
                    try:
                        return code.InteractiveConsole.raw_input(
                            self, *args, **kw)
                    except EOFError:
                        # In the future, we'll put our own override as needed
                        # to save models, TG style
                        raise EOFError

            newbanner = "Pylons Interactive Shell\nPython %s\n\n" % sys.version
            banner = newbanner + banner
            shell = CustomShell(locals=locs)
            try:
                import readline
            except ImportError:
                pass
            try:
                shell.interact(banner)
            finally:
                paste.registry.restorer.restoration_end()

__all__ = ['ControllerCommand', 'RestControllerCommand', 'ShellCommand']
<commit_msg>[svn] only attempt to import the models package immediately after finding the base package, this is more correct Refs #229<commit_after>"""Paster Commands, for use with paster in your project

The command(s) listed here are for use with Paste to enable easy creation of
various core Pylons templates.

Currently available commands are::

    controller, shell
"""
import os
import sys

import paste.fixture
import paste.registry
import paste.deploy.config
from paste.deploy import loadapp, appconfig
from paste.script.command import Command, BadCommand
from paste.script.filemaker import FileOp
from paste.script.pluginlib import find_egg_info_dir

import pylons.util as util

def can_import(name):
    """Attempt to __import__ the specified package/module, returning True when
    succeeding, otherwise False"""
    try:
        __import__(name)
        return True
    except ImportError:
        return False

def validate_name(name):
    """Validate that the name for the controller isn't present on the
    path already"""
    if not name:
        # This happens when the name is an existing directory
        raise BadCommand('Please give the name of a controller.')
    if can_import(name):
        raise BadCommand(
            "\n\nA module named '%s' is already present in your "
            "PYTHON_PATH.\nChoosing a conflicting name will likely cause "
            "import problems in\nyour controller at some point. It's "
            "suggested that you choose an\nalternate name, and if you'd "
            "like that name to be accessible as\n'%s', add a route "
            "to your projects config/routing.py file similar\nto:\n"
            "    map.connect('%s', controller='my_%s')" \
            % (name, name, name, name))
    return True

class ControllerCommand(Command):
    """Create a Controller and accompanying functional test

    The Controller command will create the standard controller template
    file and associated functional test to speed creation of controllers.

    Example usage::

        yourproj% paster controller comments
        Creating yourproj/yourproj/controllers/comments.py
        Creating yourproj/yourproj/tests/functional/test_comments.py

    If you'd like to have controllers underneath a directory, just include
    the path as the controller name and the necessary directories will be
    created for you::

        yourproj% paster controller admin/trackback
        Creating yourproj/controllers/admin
        Creating yourproj/yourproj/controllers/admin/trackback.py
        Creating yourproj/yourproj/tests/functional/test_admin_trackback.py
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 1
    max_args = 1
    group_name = 'pylons'

    default_verbosity = 3

    parser = Command.standard_parser(simulate=True)
    parser.add_option('--no-test',
                      action='store_true',
                      dest='no_test',
                      help="Don't create the test; just the controller")

    def command(self):
        """Main command to create controller"""
        try:
            file_op = FileOp(source_dir=os.path.join(
                os.path.dirname(__file__), 'templates'))
            try:
                name, directory = file_op.parse_path_name_args(self.args[0])
            except:
                raise BadCommand('No egg_info directory was found')

            # Check the name isn't the same as the package
            base_package = file_op.find_dir('controllers', True)[0]
            if base_package.lower() == name.lower():
                raise BadCommand(
                    'Your controller name should not be the same as '
                    'the package name %r.'% base_package
            )
            # Validate the name
            name = name.replace('-', '_')
            validate_name(name)

            # Check to see if PROJ.lib.base exists
            try:
                __import__(base_package + '.lib.base')
                importstatement = "from %s.lib.base import *" % base_package
            except:
                # Assume its the minimal template
                importstatement = "from %s.controllers import *" % base_package

            # Setup the controller
            fullname = os.path.join(directory, name)
            controller_name = util.class_name_from_module_name(
                name.split('/')[-1])
            if not fullname.startswith(os.sep):
                fullname = os.sep + fullname
            testname = fullname.replace(os.sep, '_')[1:]
            file_op.template_vars.update({'name': controller_name,
                                          'fname': os.path.join(directory, name),
                                          'importstatement': importstatement})
            file_op.copy_file(template='controller.py_tmpl',
                         dest=os.path.join('controllers', directory),
                         filename=name)
            if not self.options.no_test:
                file_op.copy_file(template='test_controller.py_tmpl',
                             dest=os.path.join('tests', 'functional'),
                             filename='test_'+testname)
        except BadCommand, e:
            raise BadCommand('An error occurred. %s' % e)
        except:
            msg = str(sys.exc_info()[1])
            raise BadCommand('An unknown error occurred. %s' % msg)

class RestControllerCommand(Command):
    """Create a REST Controller and accompanying functional test

    The RestController command will create a REST-based Controller file for use
    with the map.resource REST-based dispatching. This template includes the
    methods that map.resource dispatches to in addition to doc strings for
    clarification on when the methods will be called.

    The first argument should be the singular form of the REST resource. The
    second argument is the plural form of the word. If its a nested controller,
    put the directory information in front as shown in the second example
    below.

    Example usage::

        yourproj% paster restcontroller comment comments
        Creating yourproj/yourproj/controllers/comments.py
        Creating yourproj/yourproj/tests/functional/test_comments.py

    If you'd like to have controllers underneath a directory, just include
    the path as the controller name and the necessary directories will be
    created for you::

        yourproj% paster restcontroller admin/tracback admin/trackbacks
        Creating yourproj/controllers/admin
        Creating yourproj/yourproj/controllers/admin/trackbacks.py
        Creating yourproj/yourproj/tests/functional/test_admin_trackbacks.py
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 2
    max_args = 2
    group_name = 'pylons'

    default_verbosity = 3

    parser = Command.standard_parser(simulate=True)
    parser.add_option('--no-test',
                      action='store_true',
                      dest='no_test',
                      help="Don't create the test; just the controller")

    def command(self):
        """Main command to create controller"""
        try:
            file_op = FileOp(source_dir=os.path.join(
                os.path.dirname(__file__), 'templates'))
            try:
                singularname, singulardirectory = \
                    file_op.parse_path_name_args(self.args[0])
                pluralname, pluraldirectory = \
                    file_op.parse_path_name_args(self.args[1])
            except:
                raise BadCommand('No egg_info directory was found')

            # Check the name isn't the same as the package
            base_package = file_op.find_dir('controllers', True)[0]
            if base_package.lower() == pluralname.lower():
                raise BadCommand(
                    'Your controller name should not be the same as '
                    'the package name %r.'% base_package
            )
            # Validate the name
            for name in [singularname, pluralname]:
                name = name.replace('-', '_')
                validate_name(name)

            # Setup the controller
            fullname = os.path.join(pluraldirectory, pluralname)
            controller_name = util.class_name_from_module_name(
                pluralname.split('/')[-1])
            if not fullname.startswith(os.sep):
                fullname = os.sep + fullname
            testname = fullname.replace(os.sep, '_')[1:]

            nameprefix = ''
            if pluraldirectory:
                nameprefix = pluraldirectory.replace(os.path.sep, '_') + '_'

            controller_c = ''
            if nameprefix:
                controller_c = ", controller='%s', \n\t" % \
                    '/'.join([pluraldirectory, pluralname])
                controller_c += "path_prefix='/%s', name_prefix='%s_'" % \
                    (pluraldirectory, pluraldirectory)
            command = "map.resource('%s', '%s'%s)\n" % \
                (singularname, pluralname, controller_c)

            file_op.template_vars.update(
                {'classname': controller_name,
                 'pluralname': pluralname,
                 'singularname': singularname,
                 'name': controller_name,
                 'nameprefix': nameprefix,
                 'resource_command': command.replace('\n\t', '\n%s#%s' % \
                                                         (' '*4, ' '*9)),
                 'fname': os.path.join(pluraldirectory, pluralname)}
            )

            resource_command = ("\nTo create the appropriate RESTful mapping, "
                                "add a map statement to your\n")
            resource_command += ("config/routing.py file near the top like "
                                 "this:\n\n")
            resource_command += command
            file_op.copy_file(template='restcontroller.py_tmpl',
                         dest=os.path.join('controllers', pluraldirectory),
                         filename=pluralname)
            if not self.options.no_test:
                file_op.copy_file(template='test_controller.py_tmpl',
                             dest=os.path.join('tests', 'functional'),
                             filename='test_'+testname)
            print resource_command
        except BadCommand, e:
            raise BadCommand('An error occurred. %s' % e)
        except:
            msg = str(sys.exc_info()[1])
            raise BadCommand('An unknown error occurred. %s' % msg)

class ShellCommand(Command):
    """Open an interactive shell with the Pylons app loaded

    The optional CONFIG_FILE argument specifies the config file to use for
    the interactive shell. CONFIG_FILE defaults to 'development.ini'.

    This allows you to test your mapper, models, and simulate web requests
    using ``paste.fixture``.

    Example::

        $ paster shell my-development.ini
    """
    summary = __doc__.splitlines()[0]
    usage = '\n' + __doc__

    min_args = 0
    max_args = 1
    group_name = 'pylons'

    parser = Command.standard_parser(simulate=True)

    def command(self):
        """Main command to create a new shell"""
        self.verbose = 3
        if len(self.args) == 0:
            # Assume the .ini file is ./development.ini
            config_file = 'development.ini'
            if not os.path.isfile(config_file):
                raise BadCommand('%sError: CONFIG_FILE not found at: .%s%s\n'
                                 'Please specify a CONFIG_FILE' % \
                                 (self.parser.get_usage(), os.path.sep,
                                  config_file))
        else:
            config_file = self.args[0]

        config_name = 'config:%s' % config_file
        here_dir = os.getcwd()
        locs = dict(__name__="pylons-admin")

        # Load app config into paste.deploy to simulate request config
        conf = appconfig(config_name, relative_to=here_dir)
        conf = dict(app_conf=conf.local_conf,
                    global_conf=conf.global_conf)
        paste.deploy.config.CONFIG.push_thread_config(conf)

        # Load locals and populate with objects for use in shell
        sys.path.insert(0, here_dir)

        # Load the wsgi app first so that everything is initialized right
        wsgiapp = loadapp(config_name, relative_to=here_dir)
        test_app = paste.fixture.TestApp(wsgiapp)

        # Query the test app to setup the environment
        tresponse = test_app.get('/_test_vars')
        request_id = int(tresponse.body)

        # Disable restoration during test_app requests
        test_app.pre_request_hook = lambda self: \
            paste.registry.restorer.restoration_end()
        test_app.post_request_hook = lambda self: \
            paste.registry.restorer.restoration_begin(request_id)

        # Restore the state of the Pylons special objects
        # (StackedObjectProxies)
        paste.registry.restorer.restoration_begin(request_id)

        # Determine the package name from the .egg-info top_level.txt.
        egg_info = find_egg_info_dir(here_dir)
        f = open(os.path.join(egg_info, 'top_level.txt'))
        packages = [l.strip() for l in f.readlines()
                    if l.strip() and not l.strip().startswith('#')]
        f.close()

        # Start the rest of our imports now that the app is loaded
        found_base = False
        for pkg_name in packages:
            # Import all objects from the base module
            base_module = pkg_name + '.lib.base'
            found_base = can_import(base_module)
            if not found_base:
                # Minimal template
                base_module = pkg_name + '.controllers'
                found_base = can_import(base_module)

            if found_base:
                models_package = pkg_name + '.models'
                # The Minimal template lacks an official models package
                has_models = can_import(models_package)
                break

        if not found_base:
            raise ImportError("Could not import base module. Are you sure this "
                              "is a Pylons app?")

        base = sys.modules[base_module]
        base_public = [__name for __name in dir(base) if not \
                       __name.startswith('_') or __name == '_']
        locs.update([(name, getattr(base, name)) for name in base_public])
        locs.update(
            dict(
                mapper=tresponse.pylons_config.map,
                wsgiapp=wsgiapp,
                app=test_app,
            )
        )
        if has_models:
            locs['model'] = sys.modules[models_package]

        banner = "  All objects from %s are available\n" % base_module
        banner += "  Additional Objects:\n"
        banner += "  %-10s -  %s\n" % ('mapper', 'Routes mapper object')
        if has_models:
            banner += "  %-10s -  %s\n" % ('model',
                                           'Models from models package')
        banner += "  %-10s -  %s\n" % ('wsgiapp',
            'This projects WSGI App instance')
        banner += "  %-10s -  %s\n" % ('app',
            'paste.fixture wrapped around wsgiapp')

        try:
            # try to use IPython if possible
            from IPython.Shell import IPShellEmbed

            shell = IPShellEmbed(user_ns=locs)
            shell.set_banner(shell.IP.BANNER + '\n\n' + banner)
            try:
                shell()
            finally:
                paste.registry.restorer.restoration_end()
        except ImportError:
            import code

            class CustomShell(code.InteractiveConsole):
                """Custom shell class to handle raw input"""
                def raw_input(self, *args, **kw):
                    """Capture raw input in exception wrapping"""
                    try:
                        return code.InteractiveConsole.raw_input(
                            self, *args, **kw)
                    except EOFError:
                        # In the future, we'll put our own override as needed
                        # to save models, TG style
                        raise EOFError

            newbanner = "Pylons Interactive Shell\nPython %s\n\n" % sys.version
            banner = newbanner + banner
            shell = CustomShell(locals=locs)
            try:
                import readline
            except ImportError:
                pass
            try:
                shell.interact(banner)
            finally:
                paste.registry.restorer.restoration_end()

__all__ = ['ControllerCommand', 'RestControllerCommand', 'ShellCommand']
<|endoftext|>


<commit_before># -*- coding: iso-8859-1 -*-

#   Copyright 2010 Pepijn de Vos
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from ctypes import *
from win32api import GetSystemMetrics
from base import PyMouseMeta, PyMouseEventMeta
import pythoncom, pyHook
from time import sleep

class POINT(Structure):
    _fields_ = [("x", c_ulong),
                ("y", c_ulong)]

class PyMouse(PyMouseMeta):
    """MOUSEEVENTF_(button and action) constants
    are defined at win32con, buttonAction is that value"""
    def press(self, x, y, button = 1):
        buttonAction = 2**((2*button)-1)
        self.move(x,y)
        win32api.mouse_event(buttonAction, x, y)

    def release(self, x, y, button = 1):
        buttonAction = 2**((2*button))
        self.move(x,y)
        win32api.mouse_event(buttonAction, x, y)

    def move(self, x, y):
        windll.user32.SetCursorPos(x, y)

    def position(self):
        pt = POINT()
        windll.user32.GetCursorPos(byref(pt))
        return pt.x, pt.y

    def screen_size(self):
        width = GetSystemMetrics(0)
        height = GetSystemMetrics(1)
        return width, height

class PyMouseEvent(PyMouseEventMeta):
    def __init__(self):
        PyMouseEventMeta.__init__(self)
        self.hm = pyHook.HookManager()
    def run(self):
        hm.MouseAllButtons = self._click
        hm.MouseMove = self._move
        hm.HookMouse()
        while self.state:
            sleep(0.01)
            pythoncom.PumpWaitingMessages()

    def stop(self):
        self.hm.UnhookMouse()
        self.state = False

    def _click(self, event):
        x,y = event.Position

        if event.Message == pyHook.HookConstants.WM_LBUTTONDOWN:
            self.click(x, y, 1, True)
        elif event.Message == pyHook.HookConstants.WM_LBUTTONUP:
            self.click(x, y, 1, False)
        elif event.Message == pyHook.HookConstants.WM_RBUTTONDOWN:
            self.click(x, y, 2, True)
        elif event.Message == pyHook.HookConstants.WM_RBUTTONUP:
            self.click(x, y, 2, False)
        elif event.Message == pyHook.HookConstants.WM_MBUTTONDOWN:
            self.click(x, y, 3, True)
        elif event.Message == pyHook.HookConstants.WM_MBUTTONUP:
            self.click(x, y, 3, False)
        return not self.capture

    def _move(self, event):
        x,y = event.Position
        self.move(x, y)
        return not self.capture
<commit_msg>i forgot  change hm var to instance var<commit_after># -*- coding: iso-8859-1 -*-

#   Copyright 2010 Pepijn de Vos
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

from ctypes import *
from win32api import GetSystemMetrics
from base import PyMouseMeta, PyMouseEventMeta
import pythoncom, pyHook
from time import sleep

class POINT(Structure):
    _fields_ = [("x", c_ulong),
                ("y", c_ulong)]

class PyMouse(PyMouseMeta):
    """MOUSEEVENTF_(button and action) constants
    are defined at win32con, buttonAction is that value"""
    def press(self, x, y, button = 1):
        buttonAction = 2**((2*button)-1)
        self.move(x,y)
        win32api.mouse_event(buttonAction, x, y)

    def release(self, x, y, button = 1):
        buttonAction = 2**((2*button))
        self.move(x,y)
        win32api.mouse_event(buttonAction, x, y)

    def move(self, x, y):
        windll.user32.SetCursorPos(x, y)

    def position(self):
        pt = POINT()
        windll.user32.GetCursorPos(byref(pt))
        return pt.x, pt.y

    def screen_size(self):
        width = GetSystemMetrics(0)
        height = GetSystemMetrics(1)
        return width, height

class PyMouseEvent(PyMouseEventMeta):
    def __init__(self):
        PyMouseEventMeta.__init__(self)
        self.hm = pyHook.HookManager()

def run(self):
        self.hm.MouseAllButtons = self._click
        self.hm.MouseMove = self._move
        self.hm.HookMouse()
        while self.state:
            sleep(0.01)
            pythoncom.PumpWaitingMessages()

    def stop(self):
        self.hm.UnhookMouse()
        self.state = False

    def _click(self, event):
        x,y = event.Position

        if event.Message == pyHook.HookConstants.WM_LBUTTONDOWN:
            self.click(x, y, 1, True)
        elif event.Message == pyHook.HookConstants.WM_LBUTTONUP:
            self.click(x, y, 1, False)
        elif event.Message == pyHook.HookConstants.WM_RBUTTONDOWN:
            self.click(x, y, 2, True)
        elif event.Message == pyHook.HookConstants.WM_RBUTTONUP:
            self.click(x, y, 2, False)
        elif event.Message == pyHook.HookConstants.WM_MBUTTONDOWN:
            self.click(x, y, 3, True)
        elif event.Message == pyHook.HookConstants.WM_MBUTTONUP:
            self.click(x, y, 3, False)
        return not self.capture

    def _move(self, event):
        x,y = event.Position
        self.move(x, y)
        return not self.capture
<|endoftext|>