コード例 #1
0
 def _report_summary(
     self,
     error_messages,
     failed_file_paths,
     total_modules,
     total_successes,
     total_tests,
     ):
     if failed_file_paths:
         print()
         for error_message in error_messages:
             print(error_message)
     for file_path in failed_file_paths:
         string = 'FAILED: {}'.format(file_path)
         print(string)
     print()
     test_identifier = stringtools.pluralize('test', total_tests)
     module_identifier = stringtools.pluralize('module', total_modules)
     string = '{} of {} {} passed in {} {}.'
     string = string.format(
         total_successes,
         total_tests,
         test_identifier,
         total_modules,
         module_identifier,
         )
     print(string)
     if total_successes == total_tests:
         sys.exit(0)
     else:
         sys.exit(1)
コード例 #2
0
ファイル: ReplaceInFilesScript.py プロジェクト: DnMllr/abjad
    def process_args(self, args):
        r'''Processes `args`.

        Returns none.
        '''
        print('Replacing {!r} with {!r} ...'.format(args.old, args.new))
        skipped_dirs_patterns = self.skipped_directories + args.without_dirs
        skipped_files_patterns = self.skipped_files + args.without_files
        if args.regex or (not args.regex and args.whole_words_only):
            args.old = self._get_regex_search_callable(args)
            index, length = args.old('', 0)
            if 0 <= index:
                message = 'regex pattern {!r} matches the empty string.'
                message = message.format(args.old.pattern.pattern)
                raise ValueError(message)
        else:
            args.old = self._get_naive_search_callable(args)
        changed_file_count = 0
        changed_line_count = 0
        changed_item_count = 0
        for root, dirs, files in os.walk(args.path):
            dirs_to_remove = []
            for dir in dirs:
                for pattern in skipped_dirs_patterns:
                    if fnmatch.fnmatch(dir, pattern):
                        dirs_to_remove.append(dir)
                        break
            for dir in dirs_to_remove:
                dirs.remove(dir)
            for file in sorted(files):
                valid = True
                for pattern in skipped_files_patterns:
                    if fnmatch.fnmatch(file, pattern):
                        valid = False
                        break
                if not valid:
                    continue
                changed_lines, changed_items = self._process_file(
                    args, os.path.join(root, file))
                if changed_lines:
                    changed_file_count += 1
                    changed_line_count += changed_lines
                    changed_item_count += changed_items
        print()
        item_identifier = stringtools.pluralize('instance', changed_item_count)
        line_identifier = stringtools.pluralize('line', changed_line_count)
        file_identifier = stringtools.pluralize('file', changed_file_count)
        message = '\tReplaced {} {} over {} {} in {} {}.'
        message = message.format(
                changed_item_count, 
                item_identifier,
                changed_line_count, 
                line_identifier,
                changed_file_count,
                file_identifier,
                )
        print(message)
コード例 #3
0
    def process_args(self, args):
        r'''Processes `args`.

        Returns none.
        '''
        print('Replacing {!r} with {!r} ...'.format(args.old, args.new))
        skipped_dirs_patterns = self.skipped_directories + args.without_dirs
        skipped_files_patterns = self.skipped_files + args.without_files
        if args.regex or (not args.regex and args.whole_words_only):
            args.old = self._get_regex_search_callable(args)
            index, length = args.old('', 0)
            if 0 <= index:
                message = 'regex pattern {!r} matches the empty string.'
                message = message.format(args.old.pattern.pattern)
                raise ValueError(message)
        else:
            args.old = self._get_naive_search_callable(args)
        changed_file_count = 0
        changed_line_count = 0
        changed_item_count = 0
        for root, dirs, files in os.walk(args.path):
            dirs_to_remove = []
            for dir in dirs:
                for pattern in skipped_dirs_patterns:
                    if fnmatch.fnmatch(dir, pattern):
                        dirs_to_remove.append(dir)
                        break
            for dir in dirs_to_remove:
                dirs.remove(dir)
            for file in sorted(files):
                valid = True
                for pattern in skipped_files_patterns:
                    if fnmatch.fnmatch(file, pattern):
                        valid = False
                        break
                if not valid:
                    continue
                changed_lines, changed_items = self._process_file(
                    args, os.path.join(root, file))
                if changed_lines:
                    changed_file_count += 1
                    changed_line_count += changed_lines
                    changed_item_count += changed_items
        print()
        item_identifier = stringtools.pluralize('instance', changed_item_count)
        line_identifier = stringtools.pluralize('line', changed_line_count)
        file_identifier = stringtools.pluralize('file', changed_file_count)
        message = '\tReplaced {} {} over {} {} in {} {}.'
        message = message.format(
            changed_item_count,
            item_identifier,
            changed_line_count,
            line_identifier,
            changed_file_count,
            file_identifier,
        )
        print(message)
コード例 #4
0
 def _report(
     self,
     error_messages=None,
     failed_file_paths=None,
     print_to_terminal=False,
     result=None,
     total_tests=None,
     total_failures=None,
     total_modules=None,
 ):
     if failed_file_paths:
         if print_to_terminal:
             print()
         else:
             result.append('')
         for error_message in error_messages:
             if print_to_terminal:
                 print(error_message)
             else:
                 result.append(error_message)
     for file_path in failed_file_paths:
         string = 'FAILED: {}'.format(file_path)
         if print_to_terminal:
             print(string)
         else:
             result.append(string)
     if print_to_terminal:
         print()
     else:
         result.append('')
     test_identifier = stringtools.pluralize('test', total_tests)
     module_identifier = stringtools.pluralize('module', total_modules)
     string = ('{total_successes} passed, {total_failures} failed out of '
               '{total_tests} {test_identifier} '
               'in {total_modules} {module_identifier}.')
     string = string.format(
         module_identifier=module_identifier,
         test_identifier=test_identifier,
         total_failures=total_failures,
         total_modules=total_modules,
         total_successes=total_tests - total_failures,
         total_tests=total_tests,
     )
     if print_to_terminal:
         print(string)
         if failed_file_paths:
             sys.exit(1)
         else:
             sys.exit(0)
     else:
         result.append(string)
         return result
コード例 #5
0
ファイル: DoctestScript.py プロジェクト: ajyoon/abjad
 def _report(
     self,
     error_messages=None,
     failed_file_paths=None,
     print_to_terminal=False,
     result=None,
     total_tests=None,
     total_failures=None,
     total_modules=None,
     ):
     if failed_file_paths:
         if print_to_terminal:
             print()
         else:
             result.append('')
         for error_message in error_messages:
             if print_to_terminal:
                 print(error_message)
             else:
                 result.append(error_message)
     for file_path in failed_file_paths:
         string = 'FAILED: {}'.format(file_path)
         if print_to_terminal:
             print(string)
         else:
             result.append(string)
     total_successes = total_tests - total_failures
     if print_to_terminal:
         print()
     else:
         result.append('')
     test_identifier = stringtools.pluralize('test', total_tests)
     module_identifier = stringtools.pluralize('module', total_modules)
     string = '{} of {} {} passed in {} {}.'
     string = string.format(
         total_successes,
         total_tests,
         test_identifier,
         total_modules,
         module_identifier,
         )
     if print_to_terminal:
         print(string)
         if failed_file_paths:
             sys.exit(1)
         else:
             sys.exit(0)
     else:
         result.append(string)
         return result
コード例 #6
0
ファイル: AssetController.py プロジェクト: jefftrevino/abjad
    def pytest(self):
        r'''Pytests Python files.

        Returns none.
        '''
        message = 'running py.test ...'
        self._io_manager._display(message)
        assets = []
        paths = self._list_python_files_in_visible_assets()
        for path in paths:
            assert os.path.isfile(path)
        paths = [
            _ for _ in paths if os.path.basename(_).startswith('test_')
            ]
        for path in paths:
            if os.path.isdir(path):
                assets.append(path)
            elif os.path.isfile(path) and path.endswith('.py'):
                assets.append(path)
        if not assets:
            message = 'no testable assets found.'
            self._io_manager._display(message)
        else:
            count = len(paths)
            identifier = stringtools.pluralize('asset', count=count)
            message = '{} testable {} found ...'
            message = message.format(count, identifier)
            self._io_manager._display(message)
            assets = ' '.join(assets)
            command = 'py.test -rf {}'.format(assets)
            self._io_manager.run_command(command, capitalize=False)
コード例 #7
0
ファイル: Wrangler.py プロジェクト: jefftrevino/abjad
    def add_every_asset(self):
        r'''Adds every asset to repository.

        Returns none.
        '''
        self._session._attempted_to_add = True
        if self._session.is_repository_test:
            return
        managers = self._list_visible_asset_managers()
        inputs, outputs = [], []
        method_name = 'add'
        for manager in managers:
            method = getattr(manager, method_name)
            inputs_, outputs_ = method(dry_run=True)
            inputs.extend(inputs_)
            outputs.extend(outputs_)
        messages = self._format_messaging(inputs, outputs, verb='add')
        self._io_manager._display(messages)
        if not inputs:
            return
        result = self._io_manager._confirm()
        if self._session.is_backtracking or not result:
            return
        with self._io_manager._silent():
            for manager in managers:
                method = getattr(manager, method_name)
                method()
        count = len(inputs)
        identifier = stringtools.pluralize('file', count)
        message = 'added {} {} to repository.'
        message = message.format(count, identifier)
        self._io_manager._display(message)
コード例 #8
0
    def add_every_asset(self):
        r'''Adds every asset to repository.

        Returns none.
        '''
        self._session._attempted_to_add = True
        if self._session.is_repository_test:
            return
        managers = self._list_visible_asset_managers()
        inputs, outputs = [], []
        method_name = 'add'
        for manager in managers:
            method = getattr(manager, method_name)
            inputs_, outputs_ = method(dry_run=True)
            inputs.extend(inputs_)
            outputs.extend(outputs_)
        messages = self._format_messaging(inputs, outputs, verb='add')
        self._io_manager._display(messages)
        if not inputs:
            return
        result = self._io_manager._confirm()
        if self._session.is_backtracking or not result:
            return
        with self._io_manager._silent():
            for manager in managers:
                method = getattr(manager, method_name)
                method()
        count = len(inputs)
        identifier = stringtools.pluralize('file', count)
        message = 'added {} {} to repository.'
        message = message.format(count, identifier)
        self._io_manager._display(message)
コード例 #9
0
    def pytest(self):
        r'''Pytests Python files.

        Returns none.
        '''
        message = 'running py.test ...'
        self._io_manager._display(message)
        assets = []
        paths = self._list_python_files_in_visible_assets()
        for path in paths:
            assert os.path.isfile(path)
        paths = [_ for _ in paths if os.path.basename(_).startswith('test_')]
        for path in paths:
            if os.path.isdir(path):
                assets.append(path)
            elif os.path.isfile(path) and path.endswith('.py'):
                assets.append(path)
        if not assets:
            message = 'no testable assets found.'
            self._io_manager._display(message)
        else:
            count = len(paths)
            identifier = stringtools.pluralize('asset', count=count)
            message = '{} testable {} found ...'
            message = message.format(count, identifier)
            self._io_manager._display(message)
            assets = ' '.join(assets)
            command = 'py.test -rf {}'.format(assets)
            self._io_manager.run_command(command, capitalize=False)
コード例 #10
0
ファイル: Timer.py プロジェクト: quesebifurcan/abjad
    def total_time_message(self):
        r'''Gets total time message.

        Truncated to the nearest second.

        Returns string.
        '''
        from abjad.tools import stringtools
        identifier = stringtools.pluralize('second', int(self.elapsed_time))
        message = 'total time {} {} ...'
        message = message.format(int(self.elapsed_time), identifier)
        return message
コード例 #11
0
 def _handle_numeric_user_input(self, result):
     paths = self._list_visible_asset_paths()
     if result in paths:
         path = result
         manager = self._initialize_manager(path)
         if not self._session.is_test:
             with self._io_manager._silent():
                 result = manager.check_package(
                     return_supply_messages=True,
                     supply_missing=True,
                     )
             messages, supplied_directories, supplied_files = result
             messages = []
             tab = self._io_manager._tab
             if supplied_directories:
                 identifier = 'directory'
                 count = len(supplied_directories)
                 identifier = stringtools.pluralize(identifier, count)
                 message = 'Made missing {}:'.format(identifier)
                 messages.append(message)
                 directories = [tab + _ for _ in supplied_directories]
                 messages.extend(directories)
             if supplied_files:
                 identifier = 'file'
                 count = len(supplied_files)
                 identifier = stringtools.pluralize(identifier, count)
                 message = 'Made missing {}:'.format(identifier)
                 messages.append(message)
                 files = [tab + _ for _ in supplied_files]
                 messages.extend(files)
             if messages:
                 self._io_manager._display(messages)
                 self._io_manager._acknowledge()
                 if self._session.is_backtracking:
                     return
         manager._run()
コード例 #12
0
 def _handle_numeric_user_input(self, result):
     paths = self._list_visible_asset_paths()
     if result in paths:
         path = result
         manager = self._initialize_manager(path)
         if not self._session.is_test:
             with self._io_manager._silent():
                 result = manager.check_package(
                     return_supply_messages=True,
                     supply_missing=True,
                 )
             messages, supplied_directories, supplied_files = result
             messages = []
             tab = self._io_manager._tab
             if supplied_directories:
                 identifier = 'directory'
                 count = len(supplied_directories)
                 identifier = stringtools.pluralize(identifier, count)
                 message = 'Made missing {}:'.format(identifier)
                 messages.append(message)
                 directories = [tab + _ for _ in supplied_directories]
                 messages.extend(directories)
             if supplied_files:
                 identifier = 'file'
                 count = len(supplied_files)
                 identifier = stringtools.pluralize(identifier, count)
                 message = 'Made missing {}:'.format(identifier)
                 messages.append(message)
                 files = [tab + _ for _ in supplied_files]
                 messages.extend(files)
             if messages:
                 self._io_manager._display(messages)
                 self._io_manager._acknowledge()
                 if self._session.is_backtracking:
                     return
         manager._run()
コード例 #13
0
    def remove_items(self):
        r'''Removes items from collection.

        Returns none.
        '''
        getter = self._io_manager._make_getter()
        items_identifier = stringtools.pluralize(self._item_identifier)
        getter.append_menu_section_range(
            items_identifier, self._numbered_section)
        argument_range = getter._run()
        if self._session.is_backtracking or argument_range is None:
            return
        indices = [argument_number - 1 for argument_number in argument_range]
        indices = list(reversed(sorted(set(indices))))
        items = self._collection[:]
        items = sequencetools.remove_elements(items, indices)
        self._collection[:] = items
コード例 #14
0
 def _format_counted_check_messages(
     self,
     paths,
     identifier,
     participal,
 ):
     messages = []
     if paths:
         tab = self._io_manager._tab
         count = len(paths)
         identifier = stringtools.pluralize(identifier, count)
         message = '{} {} {}:'
         message = message.format(count, identifier, participal)
         messages.append(message)
         for path in paths:
             message = tab + path
             messages.append(message)
     return messages
コード例 #15
0
 def _select_visible_asset_paths(self):
     getter = self._io_manager._make_getter()
     plural_identifier = stringtools.pluralize(self._asset_identifier)
     message = 'enter {}(s) to remove'
     message = message.format(plural_identifier)
     menu = self._make_asset_selection_menu()
     asset_section = menu['assets']
     getter.append_menu_section_range(
         message,
         asset_section,
     )
     numbers = getter._run()
     if self._session.is_backtracking or numbers is None:
         return
     indices = [_ - 1 for _ in numbers]
     paths = [_.return_value for _ in asset_section.menu_entries]
     paths = sequencetools.retain_elements(paths, indices)
     return paths
コード例 #16
0
ファイル: PackageManager.py プロジェクト: jefftrevino/abjad
 def _format_counted_check_messages(
     self,
     paths,
     identifier,
     participal,
     ):
     messages = []
     if paths:
         tab = self._io_manager._tab
         count = len(paths)
         identifier = stringtools.pluralize(identifier, count)
         message = '{} {} {}:'
         message = message.format(count, identifier, participal)
         messages.append(message)
         for path in paths:
             message = tab + path
             messages.append(message)
     return messages
コード例 #17
0
ファイル: Wrangler.py プロジェクト: jefftrevino/abjad
 def _select_visible_asset_paths(self):
     getter = self._io_manager._make_getter()
     plural_identifier = stringtools.pluralize(self._asset_identifier)
     message = 'enter {}(s) to remove'
     message = message.format(plural_identifier)
     menu = self._make_asset_selection_menu()
     asset_section = menu['assets']
     getter.append_menu_section_range(
         message, 
         asset_section,
         )
     numbers = getter._run()
     if self._session.is_backtracking or numbers is None:
         return
     indices = [_ - 1 for _ in numbers]
     paths = [_.return_value for _ in asset_section.menu_entries]
     paths = sequencetools.retain_elements(paths, indices)
     return paths
コード例 #18
0
    def check_every_file(self):
        r'''Checks every file.

        Returns none.
        '''
        paths = self._list_asset_paths(valid_only=False)
        paths = [_ for _ in paths if os.path.basename(_)[0].isalpha()]
        paths = [_ for _ in paths if not _.endswith('.pyc')]
        current_directory = self._get_current_directory()
        if current_directory:
            paths = [_ for _ in paths if _.startswith(current_directory)]
        invalid_paths = []
        for path in paths:
            file_name = os.path.basename(path)
            if not self._is_valid_directory_entry(file_name):
                invalid_paths.append(path)
        messages = []
        if not invalid_paths:
            count = len(paths)
            message = '{} ({} files): OK'.format(self._breadcrumb, count)
            messages.append(message)
        else:
            message = '{}:'.format(self._breadcrumb)
            messages.append(message)
            identifier = 'file'
            count = len(invalid_paths)
            identifier = stringtools.pluralize(identifier, count)
            message = '{} unrecognized {} found:'
            message = message.format(count, identifier)
            tab = self._io_manager._tab
            message = tab + message
            messages.append(message)
            for invalid_path in invalid_paths:
                message = tab + tab + invalid_path
                messages.append(message)
        self._io_manager._display(messages)
        missing_files, missing_directories = [], []
        return messages, missing_files, missing_directories
コード例 #19
0
ファイル: FileWrangler.py プロジェクト: jefftrevino/abjad
    def check_every_file(self):
        r'''Checks every file.

        Returns none.
        '''
        paths = self._list_asset_paths(valid_only=False)
        paths = [_ for _ in paths if os.path.basename(_)[0].isalpha()]
        paths = [_ for _ in paths if not _.endswith('.pyc')]
        current_directory = self._get_current_directory()
        if current_directory:
            paths = [_ for _ in paths if _.startswith(current_directory)]
        invalid_paths = []
        for path in paths:
            file_name = os.path.basename(path)
            if not self._is_valid_directory_entry(file_name):
                invalid_paths.append(path)
        messages = []
        if not invalid_paths:
            count = len(paths)
            message = '{} ({} files): OK'.format(self._breadcrumb, count)
            messages.append(message)
        else:
            message = '{}:'.format(self._breadcrumb)
            messages.append(message)
            identifier = 'file'
            count = len(invalid_paths)
            identifier = stringtools.pluralize(identifier, count)
            message = '{} unrecognized {} found:'
            message = message.format(count, identifier)
            tab = self._io_manager._tab
            message = tab + message
            messages.append(message)
            for invalid_path in invalid_paths:
                message = tab + tab + invalid_path
                messages.append(message)
        self._io_manager._display(messages)
        missing_files, missing_directories = [], []
        return messages, missing_files, missing_directories
コード例 #20
0
 def _format_ratio_check_messages(
     self,
     found_paths,
     total_paths,
     identifier,
     participal='found',
 ):
     messages = []
     denominator = len(total_paths)
     numerator = len(found_paths)
     identifier = stringtools.pluralize(identifier, denominator)
     if denominator:
         message = '{} of {} {} {}:'
     else:
         message = '{} of {} {} {}.'
     message = message.format(numerator, denominator, identifier,
                              participal)
     messages.append(message)
     tab = self._io_manager._tab
     for path in sorted(found_paths):
         message = tab + path
         messages.append(message)
     return messages
コード例 #21
0
ファイル: PackageManager.py プロジェクト: jefftrevino/abjad
 def _format_ratio_check_messages(
     self,
     found_paths,
     total_paths,
     identifier,
     participal='found',
     ):
     messages = []
     denominator = len(total_paths)
     numerator = len(found_paths)
     identifier = stringtools.pluralize(identifier, denominator)
     if denominator:
         message = '{} of {} {} {}:'
     else:
         message = '{} of {} {} {}.'
     message = message.format(
         numerator, denominator, identifier, participal)
     messages.append(message)
     tab = self._io_manager._tab
     for path in sorted(found_paths):
         message = tab + path
         messages.append(message)
     return messages
コード例 #22
0
    def remove_every_unadded_asset(self):
        r'''Removes files not yet added to repository of every asset.

        Returns none.
        '''
        self._session._attempted_remove_unadded_assets = True
        if self._session.is_test and not self._session.is_in_score:
            return
        paths = self._list_visible_asset_paths()
        paths = self._extract_common_parent_directories(paths)
        paths.sort()
        inputs, outputs = [], []
        managers = []
        method_name = 'remove_unadded_assets'
        for path in paths:
            manager = self._io_manager._make_package_manager(path)
            managers.append(manager)
            method = getattr(manager, method_name)
            inputs_, outputs_ = method(dry_run=True)
            inputs.extend(inputs_)
            outputs.extend(outputs_)
        messages = self._format_messaging(inputs, outputs, verb='remove')
        self._io_manager._display(messages)
        if not inputs:
            return
        result = self._io_manager._confirm()
        if self._session.is_backtracking or not result:
            return
        with self._io_manager._silent():
            for manager in managers:
                method = getattr(manager, method_name)
                method()
        count = len(inputs)
        identifier = stringtools.pluralize('asset', count)
        message = 'removed {} unadded {}.'
        message = message.format(count, identifier)
        self._io_manager._display(message)
コード例 #23
0
ファイル: Wrangler.py プロジェクト: jefftrevino/abjad
    def remove_every_unadded_asset(self):
        r'''Removes files not yet added to repository of every asset.

        Returns none.
        '''
        self._session._attempted_remove_unadded_assets = True
        if self._session.is_test and not self._session.is_in_score:
            return
        paths = self._list_visible_asset_paths()
        paths = self._extract_common_parent_directories(paths)
        paths.sort()
        inputs, outputs = [], []
        managers = []
        method_name = 'remove_unadded_assets'
        for path in paths:
            manager = self._io_manager._make_package_manager(path)
            managers.append(manager)
            method = getattr(manager, method_name)
            inputs_, outputs_ = method(dry_run=True)
            inputs.extend(inputs_)
            outputs.extend(outputs_)
        messages = self._format_messaging(inputs, outputs, verb='remove')
        self._io_manager._display(messages)
        if not inputs:
            return
        result = self._io_manager._confirm()
        if self._session.is_backtracking or not result:
            return
        with self._io_manager._silent():
            for manager in managers:
                method = getattr(manager, method_name)
                method()
        count = len(inputs)
        identifier = stringtools.pluralize('asset', count)
        message = 'removed {} unadded {}.'
        message = message.format(count, identifier)
        self._io_manager._display(message)
コード例 #24
0
ファイル: AssetController.py プロジェクト: jefftrevino/abjad
    def doctest(self):
        r'''Doctests Python files.

        Returns none.
        '''
        message = 'running doctest ...'
        self._io_manager._display(message)
        assets = []
        paths = self._list_visible_asset_paths()
        for path in paths:
            if path.endswith('.py'):
                assets.append(path)
            if os.path.isdir(path):
                triples = os.walk(path)
                for directory_name, subdirectories, file_names in triples:
                    for file_name in file_names:
                        if file_name.endswith('.py'):
                            file_path = os.path.join(
                                directory_name,
                                file_name,
                                )
                            assets.append(file_path)
        if not assets:
            message = 'no testable assets found.'
            self._io_manager._display(message)
        else:
            count = len(assets)
            identifier = stringtools.pluralize('asset', count=count)
            message = '{} testable {} found ...'
            message = message.format(count, identifier)
            self._io_manager._display(message)
            script = developerscripttools.RunDoctestsScript()
            strings = script.process_args(
                file_paths=assets,
                print_to_terminal=False,
                )
            self._io_manager._display(strings, capitalize=False)
コード例 #25
0
    def doctest(self):
        r'''Doctests Python files.

        Returns none.
        '''
        message = 'running doctest ...'
        self._io_manager._display(message)
        assets = []
        paths = self._list_visible_asset_paths()
        for path in paths:
            if path.endswith('.py'):
                assets.append(path)
            if os.path.isdir(path):
                triples = os.walk(path)
                for directory_name, subdirectories, file_names in triples:
                    for file_name in file_names:
                        if file_name.endswith('.py'):
                            file_path = os.path.join(
                                directory_name,
                                file_name,
                            )
                            assets.append(file_path)
        if not assets:
            message = 'no testable assets found.'
            self._io_manager._display(message)
        else:
            count = len(assets)
            identifier = stringtools.pluralize('asset', count=count)
            message = '{} testable {} found ...'
            message = message.format(count, identifier)
            self._io_manager._display(message)
            script = developerscripttools.RunDoctestsScript()
            strings = script.process_args(
                file_paths=assets,
                print_to_terminal=False,
            )
            self._io_manager._display(strings, capitalize=False)
コード例 #26
0
ファイル: PackageManager.py プロジェクト: jefftrevino/abjad
    def check_package(
        self,
        problems_only=None,
        return_messages=False,
        return_supply_messages=False,
        supply_missing=None,
        ):
        r'''Checks package.

        Returns none.
        '''
        if problems_only is None:
            prompt = 'show problem assets only?'
            result = self._io_manager._confirm(prompt)
            if self._session.is_backtracking or result is None:
                return
            problems_only = bool(result)
        tab = self._io_manager._tab
        optional_directories, optional_files = [], []
        missing_directories, missing_files = [], []
        required_directories, required_files = [], []
        supplied_directories, supplied_files = [], []
        unrecognized_directories, unrecognized_files = [], []
        names = self._list()
        for name in names:
            path = os.path.join(self._path, name)
            if os.path.isdir(path):
                if name in self._required_directories:
                    required_directories.append(path)
                elif name in self._optional_directories:
                    optional_directories.append(path)
                else:
                    unrecognized_directories.append(path)
            elif os.path.isfile(path):
                if name in self._required_files:
                    required_files.append(path)
                elif name in self._optional_files:
                    optional_files.append(path)
                else:
                    unrecognized_files.append(path)
            else:
                raise TypeError(path)
        recognized_directories = required_directories + optional_directories
        recognized_files = required_files + optional_files
        for required_directory in self._required_directories:
            path = os.path.join(self._path, required_directory)
            if path not in recognized_directories:
                missing_directories.append(path)
        for required_file in self._required_files:
            path = os.path.join(self._path, required_file)
            if path not in recognized_files:
                missing_files.append(path)
        messages = []
        if not problems_only:
            messages_ = self._format_ratio_check_messages(
                required_directories,
                self._required_directories,
                'required directory',
                participal='found',
                )
            messages.extend(messages_)
        if missing_directories:
            messages_ = self._format_ratio_check_messages(
                missing_directories,
                self._required_directories,
                'required directory',
                'missing',
                )
            messages.extend(messages_)
        if not problems_only:
            messages_ = self._format_ratio_check_messages(
                required_files,
                self._required_files,
                'required file',
                'found',
                )
            messages.extend(messages_)
        if missing_files:
            messages_ = self._format_ratio_check_messages(
                missing_files,
                self._required_files,
                'required file',
                'missing',
                )
            messages.extend(messages_)
        if not problems_only:
            messages_ = self._format_counted_check_messages(
                optional_directories,
                'optional directory',
                participal='found',
                )
            messages.extend(messages_)
            messages_ = self._format_counted_check_messages(
                optional_files,
                'optional file',
                participal='found',
                )
            messages.extend(messages_)
        messages_ = self._format_counted_check_messages(
            unrecognized_directories,
            'unrecognized directory',
            participal='found',
            )
        messages.extend(messages_)
        messages_ = self._format_counted_check_messages(
            unrecognized_files,
            'unrecognized file',
            participal='found',
            )
        messages.extend(messages_)
        tab = self._io_manager._tab
        messages = [tab + _ for _ in messages]
        name = self._path_to_asset_menu_display_string(self._path)
        found_problems = missing_directories or \
            missing_files or \
            unrecognized_directories or \
            unrecognized_files
        count = len(names)
        wranglers = self._get_top_level_wranglers()
        if wranglers or not return_messages:
            message = 'top level ({} assets):'.format(count)
            if not found_problems:
                message = '{} OK'.format(message)
            messages.insert(0, message)
            messages = [stringtools.capitalize_start(_) for _ in messages]
            messages = [tab + _ for _ in messages]
        message = '{}:'.format(name)
        if not wranglers and not found_problems and return_messages:
            message = '{} OK'.format(message)
        messages.insert(0, message)
        if wranglers:
            controller = self._io_manager._controller(
                controller=self,
                current_score_directory=self._path,
                )
            silence = self._io_manager._silent()
            with controller, silence:
                tab = self._io_manager._tab
                for wrangler in wranglers:
                    if hasattr(wrangler, 'check_every_package'):
                        result = wrangler.check_every_package(
                            indent=1,
                            problems_only=problems_only,
                            supply_missing=False,
                            )
                    else:
                        result = wrangler.check_every_file()
                    messages_, missing_directories_, missing_files_ = result
                    missing_directories.extend(missing_directories_)
                    missing_files.extend(missing_files_)
                    messages_ = [
                        stringtools.capitalize_start(_) for _ in messages_]
                    messages_ = [tab + _ for _ in messages_]
                    messages.extend(messages_)
        if return_messages:
            return messages, missing_directories, missing_files
        else:
            self._io_manager._display(messages)
        if not missing_directories + missing_files:
            return messages, missing_directories, missing_files
        if supply_missing is None:
            directory_count = len(missing_directories)
            file_count = len(missing_files)
            directories = stringtools.pluralize('directory', directory_count)
            files = stringtools.pluralize('file', file_count)
            if missing_directories and missing_files:
                prompt = 'supply missing {} and {}?'.format(directories, files)
            elif missing_directories:
                prompt = 'supply missing {}?'.format(directories)
            elif missing_files:
                prompt = 'supply missing {}?'.format(files)
            else:
                raise ValueError
            result = self._io_manager._confirm(prompt)
            if self._session.is_backtracking or result is None:
                return
            supply_missing = bool(result)
        if not supply_missing:
            return messages, missing_directories, missing_files
        messages = []
        messages.append('Made:')
        for missing_directory in missing_directories:
            os.makedirs(missing_directory)
            gitignore_path = os.path.join(missing_directory, '.gitignore')
            with open(gitignore_path, 'w') as file_pointer:
                file_pointer.write('')
            message = tab + missing_directory
            messages.append(message)
            supplied_directories.append(missing_directory)
        for missing_file in missing_files:
            if missing_file.endswith('__init__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
            elif missing_file.endswith('__metadata__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
                lines.append('import collections')
                lines.append('')
                lines.append('')
                lines.append('metadata = collections.OrderedDict([])')
            elif missing_file.endswith('__views__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
                lines.append(self._abjad_import_statement)
                lines.append('from scoremanager import idetools')
                lines.append('')
                lines.append('')
                line = 'view_inventory = idetools.ViewInventory([])'
                lines.append(line)
            elif missing_file.endswith('definition.py'):
                source_path = os.path.join(
                    self._configuration.score_manager_directory,
                    'boilerplate',
                    'definition.py',
                    )
                with open(source_path, 'r') as file_pointer:
                    lines = file_pointer.readlines()
                lines = [_.strip() for _ in lines]
            else:
                message = 'do not know how to make stub for {}.'
                message = message.format(missing_file)
                raise ValueError(message)
            contents = '\n'.join(lines)
            with open(missing_file, 'w') as file_pointer:
                file_pointer.write(contents)
            message = tab + missing_file
            messages.append(message)
            supplied_files.append(missing_file)
        if return_supply_messages:
            return messages, supplied_directories, supplied_files
        else:
            self._io_manager._display(messages)
        return messages, supplied_directories, supplied_files
コード例 #27
0
 def _report_time(self, timer, prefix='Runtime'):
     message = '        {}: {} {}'
     total_time = int(timer.elapsed_time)
     identifier = stringtools.pluralize('second', total_time)
     message = message.format(prefix, total_time, identifier)
     print(message)
コード例 #28
0
ファイル: __illustrate__.py プロジェクト: trevorbaca/akasha
        )
        lilypond_file, segment_metadata = result
    except:
        traceback.print_exc()
        sys.exit(1)
    try:
        current_directory = os.path.dirname(__file__)
        dummy_session = idetools.Session()
        abjad_ide = idetools.AbjadIDE(session=dummy_session)
        abjad_ide._write_metadata_py(current_directory, segment_metadata)
    except:
        traceback.print_exc()
        sys.exit(1)
    message = "Abjad runtime {} {} ..."
    total_time = int(timer.elapsed_time)
    identifier = stringtools.pluralize("second", total_time)
    message = message.format(total_time, identifier)
    print(message)
try:
    current_directory = os.path.dirname(__file__)
    ly_path = os.path.join(current_directory, "illustration.ly")
    pdf_path = os.path.join(current_directory, "illustration.pdf")
    output_paths = (ly_path, pdf_path)
    with systemtools.Timer() as timer:
        persist(lilypond_file).as_pdf(pdf_path)
    message = "LilyPond runtime {} {} ..."
    total_time = int(timer.elapsed_time)
    identifier = stringtools.pluralize("second", total_time)
    message = message.format(total_time, identifier)
    print(message)
    for output_path in output_paths:
コード例 #29
0
ファイル: ScorePackageScript.py プロジェクト: ajyoon/abjad
 def _report_time(self, timer, prefix='Runtime'):
     message = '        {}: {} {}'
     total_time = int(timer.elapsed_time)
     identifier = stringtools.pluralize('second', total_time)
     message = message.format(prefix, total_time, identifier)
     print(message)
コード例 #30
0
    def check_package(
        self,
        problems_only=None,
        return_messages=False,
        return_supply_messages=False,
        supply_missing=None,
    ):
        r'''Checks package.

        Returns none.
        '''
        if problems_only is None:
            prompt = 'show problem assets only?'
            result = self._io_manager._confirm(prompt)
            if self._session.is_backtracking or result is None:
                return
            problems_only = bool(result)
        tab = self._io_manager._tab
        optional_directories, optional_files = [], []
        missing_directories, missing_files = [], []
        required_directories, required_files = [], []
        supplied_directories, supplied_files = [], []
        unrecognized_directories, unrecognized_files = [], []
        names = self._list()
        for name in names:
            path = os.path.join(self._path, name)
            if os.path.isdir(path):
                if name in self._required_directories:
                    required_directories.append(path)
                elif name in self._optional_directories:
                    optional_directories.append(path)
                else:
                    unrecognized_directories.append(path)
            elif os.path.isfile(path):
                if name in self._required_files:
                    required_files.append(path)
                elif name in self._optional_files:
                    optional_files.append(path)
                else:
                    unrecognized_files.append(path)
            else:
                raise TypeError(path)
        recognized_directories = required_directories + optional_directories
        recognized_files = required_files + optional_files
        for required_directory in self._required_directories:
            path = os.path.join(self._path, required_directory)
            if path not in recognized_directories:
                missing_directories.append(path)
        for required_file in self._required_files:
            path = os.path.join(self._path, required_file)
            if path not in recognized_files:
                missing_files.append(path)
        messages = []
        if not problems_only:
            messages_ = self._format_ratio_check_messages(
                required_directories,
                self._required_directories,
                'required directory',
                participal='found',
            )
            messages.extend(messages_)
        if missing_directories:
            messages_ = self._format_ratio_check_messages(
                missing_directories,
                self._required_directories,
                'required directory',
                'missing',
            )
            messages.extend(messages_)
        if not problems_only:
            messages_ = self._format_ratio_check_messages(
                required_files,
                self._required_files,
                'required file',
                'found',
            )
            messages.extend(messages_)
        if missing_files:
            messages_ = self._format_ratio_check_messages(
                missing_files,
                self._required_files,
                'required file',
                'missing',
            )
            messages.extend(messages_)
        if not problems_only:
            messages_ = self._format_counted_check_messages(
                optional_directories,
                'optional directory',
                participal='found',
            )
            messages.extend(messages_)
            messages_ = self._format_counted_check_messages(
                optional_files,
                'optional file',
                participal='found',
            )
            messages.extend(messages_)
        messages_ = self._format_counted_check_messages(
            unrecognized_directories,
            'unrecognized directory',
            participal='found',
        )
        messages.extend(messages_)
        messages_ = self._format_counted_check_messages(
            unrecognized_files,
            'unrecognized file',
            participal='found',
        )
        messages.extend(messages_)
        tab = self._io_manager._tab
        messages = [tab + _ for _ in messages]
        name = self._path_to_asset_menu_display_string(self._path)
        found_problems = missing_directories or \
            missing_files or \
            unrecognized_directories or \
            unrecognized_files
        count = len(names)
        wranglers = self._get_top_level_wranglers()
        if wranglers or not return_messages:
            message = 'top level ({} assets):'.format(count)
            if not found_problems:
                message = '{} OK'.format(message)
            messages.insert(0, message)
            messages = [stringtools.capitalize_start(_) for _ in messages]
            messages = [tab + _ for _ in messages]
        message = '{}:'.format(name)
        if not wranglers and not found_problems and return_messages:
            message = '{} OK'.format(message)
        messages.insert(0, message)
        if wranglers:
            controller = self._io_manager._controller(
                controller=self,
                current_score_directory=self._path,
            )
            silence = self._io_manager._silent()
            with controller, silence:
                tab = self._io_manager._tab
                for wrangler in wranglers:
                    if hasattr(wrangler, 'check_every_package'):
                        result = wrangler.check_every_package(
                            indent=1,
                            problems_only=problems_only,
                            supply_missing=False,
                        )
                    else:
                        result = wrangler.check_every_file()
                    messages_, missing_directories_, missing_files_ = result
                    missing_directories.extend(missing_directories_)
                    missing_files.extend(missing_files_)
                    messages_ = [
                        stringtools.capitalize_start(_) for _ in messages_
                    ]
                    messages_ = [tab + _ for _ in messages_]
                    messages.extend(messages_)
        if return_messages:
            return messages, missing_directories, missing_files
        else:
            self._io_manager._display(messages)
        if not missing_directories + missing_files:
            return messages, missing_directories, missing_files
        if supply_missing is None:
            directory_count = len(missing_directories)
            file_count = len(missing_files)
            directories = stringtools.pluralize('directory', directory_count)
            files = stringtools.pluralize('file', file_count)
            if missing_directories and missing_files:
                prompt = 'supply missing {} and {}?'.format(directories, files)
            elif missing_directories:
                prompt = 'supply missing {}?'.format(directories)
            elif missing_files:
                prompt = 'supply missing {}?'.format(files)
            else:
                raise ValueError
            result = self._io_manager._confirm(prompt)
            if self._session.is_backtracking or result is None:
                return
            supply_missing = bool(result)
        if not supply_missing:
            return messages, missing_directories, missing_files
        messages = []
        messages.append('Made:')
        for missing_directory in missing_directories:
            os.makedirs(missing_directory)
            gitignore_path = os.path.join(missing_directory, '.gitignore')
            with open(gitignore_path, 'w') as file_pointer:
                file_pointer.write('')
            message = tab + missing_directory
            messages.append(message)
            supplied_directories.append(missing_directory)
        for missing_file in missing_files:
            if missing_file.endswith('__init__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
            elif missing_file.endswith('__metadata__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
                lines.append('import collections')
                lines.append('')
                lines.append('')
                lines.append('metadata = collections.OrderedDict([])')
            elif missing_file.endswith('__views__.py'):
                lines = []
                lines.append(self._configuration.unicode_directive)
                lines.append(self._abjad_import_statement)
                lines.append('from scoremanager import idetools')
                lines.append('')
                lines.append('')
                line = 'view_inventory = idetools.ViewInventory([])'
                lines.append(line)
            elif missing_file.endswith('definition.py'):
                source_path = os.path.join(
                    self._configuration.score_manager_directory,
                    'boilerplate',
                    'definition.py',
                )
                with open(source_path, 'r') as file_pointer:
                    lines = file_pointer.readlines()
                lines = [_.strip() for _ in lines]
            else:
                message = 'do not know how to make stub for {}.'
                message = message.format(missing_file)
                raise ValueError(message)
            contents = '\n'.join(lines)
            with open(missing_file, 'w') as file_pointer:
                file_pointer.write(contents)
            message = tab + missing_file
            messages.append(message)
            supplied_files.append(missing_file)
        if return_supply_messages:
            return messages, supplied_directories, supplied_files
        else:
            self._io_manager._display(messages)
        return messages, supplied_directories, supplied_files
コード例 #31
0
ファイル: __illustrate__.py プロジェクト: trevorbaca/faberge
    try:
        current_directory = os.path.dirname(__file__)
        dummy_session = idetools.Session()
        abjad_ide = idetools.AbjadIDE(
            session=dummy_session, 
            )
        abjad_ide._write_metadata_py(
            current_directory,
            segment_metadata, 
            )
    except:
        traceback.print_exc()
        sys.exit(1)
    message = 'Abjad runtime {} {} ...'
    total_time = int(timer.elapsed_time)
    identifier = stringtools.pluralize('second', total_time)
    message = message.format(total_time, identifier)
    print(message)
try:
    current_directory = os.path.dirname(__file__)
    ly_path = os.path.join(
        current_directory,
        'illustration.ly',
        )
    pdf_path = os.path.join(
        current_directory,
        'illustration.pdf',
        )
    output_paths = (ly_path, pdf_path)
    with systemtools.Timer() as timer:
        persist(lilypond_file).as_pdf(pdf_path)
コード例 #32
0
ファイル: RunDoctestsScript.py プロジェクト: jdavancens/abjad
    def process_args(
        self,
        args=None,
        file_paths=None,
        print_to_terminal=True,
    ):
        r'''Processes `args`.

        Returns none when `print_to_terminal` is false.

        Returns string(s) when `print_to_terminal` is true.

        Returns none.
        '''
        assert not (args and file_paths)
        result = []
        globs = importlib.import_module('abjad').__dict__.copy()
        try:
            experimental_module = importlib.import_module('experimental')
            experimental_demos_module = importlib.import_module('experimental')
            globs.update(experimental_module.__dict__)
            globs.update(experimental_demos_module.__dict__)
        except:
            pass
        try:
            ide_module = importlib.import_module('ide')
            globs['ide'] = ide_module
        except:
            pass
        globs['print_function'] = print_function
        optionflags = (doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS)
        if args and args.diff:
            optionflags = optionflags | doctest.REPORT_NDIFF
        if args and args.x:
            optionflags = optionflags | doctest.REPORT_ONLY_FIRST_FAILURE
        total_failures = 0
        total_modules = 0
        total_tests = 0
        failed_file_paths = []
        error_messages = []
        if not file_paths:
            file_paths = []
            if os.path.isdir(args.path):
                for dir_path, dir_names, file_names in os.walk(args.path):
                    dir_names[:] = [
                        x for x in dir_names
                        if not x.startswith(('.', 'mothballed'))
                    ]
                    for file_name in sorted(file_names):
                        if (file_name.endswith('.py')
                                and not file_name.startswith('test_')
                                and not file_name == '__init__.py'):
                            file_path = os.path.abspath(
                                os.path.join(dir_path, file_name))
                            file_paths.append(file_path)
            elif os.path.isfile(args.path):
                file_paths.append(args.path)
        for file_path in sorted(file_paths):
            total_modules += 1
            relative_path = os.path.relpath(file_path)
            string_buffer = StringIO()
            with systemtools.RedirectedStreams(stdout=string_buffer):
                failure_count, test_count = doctest.testfile(
                    file_path,
                    module_relative=False,
                    globs=globs,
                    optionflags=optionflags,
                )
            if failure_count:
                failed_file_paths.append(os.path.relpath(file_path))
                error_messages.append(string_buffer.getvalue())
                if print_to_terminal:
                    result_code = ''.join((
                        self.colors['RED'],
                        'FAILED',
                        self.colors['END'],
                    ))
                    print(relative_path, result_code)
                else:
                    result_code = 'FAILED'
                    string = '{} {}'.format(relative_path, result_code)
                    result.append(string)
                if args and args.x:
                    break
            else:
                if print_to_terminal:
                    result_code = ''.join((
                        self.colors['BLUE'],
                        'OK',
                        self.colors['END'],
                    ))
                    print(relative_path, result_code)
                else:
                    result_code = 'OK'
                    string = '{} {}'.format(relative_path, result_code)
                    result.append(string)
            total_failures += failure_count
            total_tests += test_count
        if failed_file_paths:
            if print_to_terminal:
                print()
            else:
                result.append('')
            for error_message in error_messages:
                if print_to_terminal:
                    print(error_message)
                else:
                    result.append(error_message)
        for file_path in failed_file_paths:
            string = 'FAILED: {}'.format(file_path)
            if print_to_terminal:
                print(string)
            else:
                result.append(string)
        total_successes = total_tests - total_failures
        if print_to_terminal:
            print()
        else:
            result.append('')
        test_identifier = stringtools.pluralize('test', total_tests)
        module_identifier = stringtools.pluralize('module', total_modules)
        string = '{} of {} {} passed in {} {}.'
        string = string.format(
            total_successes,
            total_tests,
            test_identifier,
            total_modules,
            module_identifier,
        )
        if print_to_terminal:
            print(string)
            if total_successes == total_tests:
                sys.exit(0)
            else:
                sys.exit(1)
        else:
            result.append(string)
            return result
コード例 #33
0
ファイル: RunDoctestsScript.py プロジェクト: DnMllr/abjad
    def process_args(
        self,
        args=None,
        file_paths=None,
        print_to_terminal=True,
        ):
        r'''Processes `args`.

        Returns none when `print_to_terminal` is false.

        Returns string(s) when `print_to_terminal` is true.

        Returns none.
        '''
        assert not (args and file_paths)
        result = []
        globs = importlib.import_module('abjad').__dict__.copy()
        try:
            experimental_module = importlib.import_module('experimental')
            experimental_demos_module = importlib.import_module('experimental')
            globs.update(experimental_module.__dict__)
            globs.update(experimental_demos_module.__dict__)
        except:
            pass
        try:
            ide_module = importlib.import_module('ide')
            globs['ide'] = ide_module
        except:
            pass
        globs['print_function'] = print_function
        optionflags = (
            doctest.NORMALIZE_WHITESPACE |
            doctest.ELLIPSIS
            )
        if args and args.diff:
            optionflags = optionflags | doctest.REPORT_NDIFF
        if args and args.x:
            optionflags = optionflags | doctest.REPORT_ONLY_FIRST_FAILURE
        total_failures = 0
        total_modules = 0
        total_tests = 0
        failed_file_paths = []
        error_messages = []
        if not file_paths:
            file_paths = []
            if os.path.isdir(args.path):
                for dir_path, dir_names, file_names in os.walk(args.path):
                    dir_names[:] = [x for x in dir_names
                        if not x.startswith(('.', 'mothballed'))]
                    for file_name in sorted(file_names):
                        if (file_name.endswith('.py') and
                            not file_name.startswith('test_') and
                            not file_name == '__init__.py'):
                            file_path = os.path.abspath(
                                os.path.join(dir_path, file_name))
                            file_paths.append(file_path)
            elif os.path.isfile(args.path):
                file_paths.append(args.path)
        for file_path in sorted(file_paths):
            total_modules += 1
            relative_path = os.path.relpath(file_path)
            string_buffer = StringIO()
            with systemtools.RedirectedStreams(stdout=string_buffer):
                failure_count, test_count = doctest.testfile(
                    file_path,
                    module_relative=False,
                    globs=globs,
                    optionflags=optionflags,
                    )
            if failure_count:
                failed_file_paths.append(os.path.relpath(file_path))
                error_messages.append(string_buffer.getvalue())
                if print_to_terminal:
                    result_code = ''.join((
                        self.colors['RED'],
                        'FAILED',
                        self.colors['END'],
                        ))
                    print(relative_path, result_code)
                else:
                    result_code = 'FAILED'
                    string = '{} {}'.format(relative_path, result_code)
                    result.append(string)
                if args and args.x:
                    break
            else:
                if print_to_terminal:
                    result_code = ''.join((
                        self.colors['BLUE'],
                        'OK',
                        self.colors['END'],
                        ))
                    print(relative_path, result_code)
                else:
                    result_code = 'OK'
                    string = '{} {}'.format(relative_path, result_code)
                    result.append(string)
            total_failures += failure_count
            total_tests += test_count
        if failed_file_paths:
            if print_to_terminal:
                print()
            else:
                result.append('')
            for error_message in error_messages:
                if print_to_terminal:
                    print(error_message)
                else:
                    result.append(error_message)
        for file_path in failed_file_paths:
            string = 'FAILED: {}'.format(file_path)
            if print_to_terminal:
                print(string)
            else:
                result.append(string)
        total_successes = total_tests - total_failures
        if print_to_terminal:
            print()
        else:
            result.append('')
        test_identifier = stringtools.pluralize('test', total_tests)
        module_identifier = stringtools.pluralize('module', total_modules)
        string = '{} of {} {} passed in {} {}.'
        string = string.format(
            total_successes,
            total_tests,
            test_identifier,
            total_modules,
            module_identifier,
            )
        if print_to_terminal:
            print(string)
            if total_successes == total_tests:
                sys.exit(0)
            else:
                sys.exit(1)
        else:
            result.append(string)
            return result