예제 #1
0
def main():
    # Parse the arguments
    parser = argparse.ArgumentParser()

    parser.add_argument('-c',
                        '--config',
                        type=str,
                        metavar='config_file',
                        help='The path for the config file',
                        default='config.ini')
    args = parser.parse_args()

    # Read the config file options
    config = configparser.ConfigParser()
    config.read(args.config)

    # Initialize the classes
    api = APIAccess(
        config['LANGUAGE']['L2'], config['LANGUAGE']['L1'],
        config.getboolean('EXAMPLE_SENTENCES', 'PreferLongSentences'),
        config.getboolean('EXAMPLE_SENTENCES', 'Cloze'))
    input_reader = InputReader(config['INPUT']['Mode'],
                               config['INPUT']['FileName'])
    output_writer = OutputWriter(config['OUTPUT'])
    audio = AudioManager(config['LANGUAGE']['L2'], config['AUDIO']['Folder'],
                         config.getboolean('AUDIO', 'Normalize'))

    # Read the input file and get all the distinct meanings for each
    # word, then append them to the output file
    failed = []
    for word in input_reader.get_next_word():
        try:
            results = api.get_dict_info(word)

            # Try to find the audio file for the word and update the results
            audio_file = audio.get_audio(word)
            for result in results:
                result['Pronounciation'] = audio_file

            output_writer.write_output(results)
        except PermissionError as e:
            # Happens if the Lexicala API doesn't allow connection
            print(e)
            print('Terminating the Program')
            exit(0)
        except Exception as e:
            # Shouldn't happen normally
            raise e

        # Book keeping and printing
        if not len(results):
            failed.append(word)

        print(f'{word} finished with {len(results)} results')

    print(f'Failed: {failed}')
예제 #2
0
 def __init__(self):
     self._language = StoryLanguage(self.__class__.language)
     self._title = self._get_title()
     self._validate_header()
     self._scenarios = []
     self._output = self._get_output()
     self._output_writer = OutputWriter(self._output,
                                        self._language,
                                        self.colored)
     self._add_scenarios()
예제 #3
0
 def __init__(self, story):
     self._title = self._get_title_from_class_name_or_docstring()
     self._story = story
     self._language = story._language
     self._output = story._output
     self._should_be_colored = story.colored
     self._failures = []
     self._errors = []
     self._pendings = []
     self._failure_color = story.failure_color
     self._error_color = story.error_color
     self._pending_color = story.pending_color
     self._output_writer = OutputWriter(self._output,
                                        self._language,
                                        self._should_be_colored)
예제 #4
0
class Scenario(object):
    _givens = []
    _whens = []
    _thens = []
    
    @staticmethod
    @pending
    def undefined_step(*args, **kw):
        """it doesn't do anything, is just marked as pending"""

    def __init__(self, story):
        self._title = self._get_title_from_class_name_or_docstring()
        self._story = story
        self._language = story._language
        self._output = story._output
        self._should_be_colored = story.colored
        self._failures = []
        self._errors = []
        self._pendings = []
        self._failure_color = story.failure_color
        self._error_color = story.error_color
        self._pending_color = story.pending_color
        self._output_writer = OutputWriter(self._output,
                                           self._language,
                                           self._should_be_colored)

    def _get_title_from_class_name_or_docstring(self):
        """returns the docstring if defined or
           the class name converted from cammel case to spaces"""
        return self.__doc__ or\
               convert_from_cammel_case_to_spaces(self.__class__.__name__)

    def _colored(self, message, color):
        """returns message colored with color
           if the scenario is allowed to use colors"""
        if self._should_be_colored:
            return colored(message, color)
        return message

    def _get_message_with_values_based_on_template(self, message, args):
        """returns a message based on a template and values:
           message_template -> Hello (.+)!
           values -> [World]
           message returned -> Hello World!"""
        for arg in args:
            message = re.sub(TEMPLATE_PATTERN, str(arg), message, 1)
        return message

    def _get_traceback_info(self):
        """this method is like traceback.format_exc,
        but it internationalizates the phrase and
        it doesn't need parameters"""
        exc, value, tb = sys.exc_info()
        return format_traceback(exc, value, tb, self._language)

    def _run_step(self, step, step_name):
        method, message_template, args = step
        message = self._get_message_with_values_based_on_template(message_template, args)
        if hasattr(method, 'pending'):
            self._pendings.append(method)
            self._output_writer.output_pending_step_line(step_name,
                                                         message,
                                                         self._pending_color)
            return
        try:
            method(self, *args)
            self._output_writer.output_ok_step_line(step_name,
                                                    message,
                                                    'green')
        except AssertionError, e:
            self._failures.append(self._get_traceback_info())
            self._output_writer.output_fail_step_line(step_name,
                                                     message,
                                                     self._failure_color)
        except Exception, e:
            self._errors.append(self._get_traceback_info())
            self._output_writer.output_error_step_line(step_name,
                                                       message,
                                                       self._error_color)
예제 #5
0
class Story(object):
    output = sys.stdout
    colored = True
    language = 'en-us'
    scenarios = []
    template_color = 'term'
    failure_color = 'red'
    error_color = 'red'
    pending_color = 'blue'
    title = ''
    namespace = None

    def __init__(self):
        self._language = StoryLanguage(self.__class__.language)
        self._title = self._get_title()
        self._validate_header()
        self._scenarios = []
        self._output = self._get_output()
        self._output_writer = OutputWriter(self._output,
                                           self._language,
                                           self.colored)
        self._add_scenarios()

    def _get_title(self):
        return self.title or convert_from_cammel_case_to_spaces(self.__class__.__name__)

    def _validate_header(self):
        meaningful_lines = [line.strip() for line in self.__doc__.split('\n')
                                if line.strip()]
        for line in meaningful_lines:
            if not (line.startswith(self._language['as_a']) or\
                    line.startswith(self._language['i_want_to']) or\
                    line.startswith(self._language['so_that']) or\
                    line.startswith(self._language['in_order_to'])):
                raise InvalidStoryHeader('Invalid Story Header!')

    def _get_output(self):
        """return output stream depending on the ``output`` class attribute.
        if ``output`` is a kind of string, it returns an open file stream.
        if not, returns the output itself"""
        if type(self.__class__.output) in [str, unicode]:
            return open(self.__class__.output, 'w')
        return self.__class__.output

    def _get_this_class_module(self):
        """return the class' module object"""
        module_root = __import__(self.__class__.__module__)
        for module in self.__class__.__module__.split('.')[1:]:
            module_root = getattr(module_root, module)
        return module_root

    def _look_for_scenario_in_story_module(self, scenario):
        module = self._get_this_class_module()
        if scenario not in dir(module):
            raise ScenarioNotFound()
        return getattr(module, scenario)

    def _get_scenarios_from_story_module(self):
        """return all Scenario's subclasses from the story module"""
        module = self._get_this_class_module()
        scenarios = []
        for attr_name in dir(module):
            attr = getattr(module, attr_name)
            if isinstance(attr, type) and \
               (Scenario in attr.__bases__ or \
                Cenario in attr.__bases__) and \
               attr is not Cenario:
                scenarios.append(attr)
        return scenarios

    def _add_scenario(self, scenario):
        """add a scenario based on its value.
        if it is a string, look for it in the story's module,
        if not, instantiate it"""
        if scenario.__class__ in [unicode, str]:
            this_scenario_class = self._look_for_scenario_in_story_module(scenario)
            this_scenario = this_scenario_class(self)
        else:
            this_scenario = scenario(self)
        self._set_defined_steps(this_scenario)
        self._scenarios.append(this_scenario)
        return self

    def _add_scenarios(self):
        """add all scenarios specified in the Story class.
        if not specified any, get all from story's module"""
        scenarios = self.__class__.scenarios
        if len(self.__class__.scenarios) == 0:
            scenarios = self._get_scenarios_from_story_module()
        for scenario in scenarios:
                self._add_scenario(scenario)

    def _find_step_matching_to(self, step, msg_set, args_default):
        """find step matching to ``msg_set`` in all scenarios,
           passing ``args_default``"""
        for scenario in self._scenarios:
            for meth, msg, args in getattr(scenario, step):
                msg_pattern = re.sub(TEMPLATE_PATTERN, r'(.+)', msg)
                msg_pattern = re.escape(msg_pattern)
                msg_pattern = msg_pattern.replace(re.escape(r'(.+)'), r'(.+)')
                regex = re.match(msg_pattern, msg_set)
                if regex:
                    return meth, msg_set, regex.groups()
        return Scenario.undefined_step, msg_set, args_default

    def _set_defined_steps(self, scenario):
        for step in ['_givens', '_whens', '_thens']:
            scenario_steps = getattr(scenario, step)
            for i in range(len(scenario_steps)):
                method, msg, args = scenario_steps[i]
                if method is None:
                    scenario_steps[i] = self._find_step_matching_to(step,
                                                                    msg,
                                                                    args)

    def _close_output_file_stream(self):
        """close output files that are not
           sys.stdout, sys.stderr, sys.stdin"""
        if type(self._output) == file and\
           self._output.fileno() > 3:
            self._output.close()

    def _colored(self, msg, color):
        if self.colored == False:
            return msg
        return colored(msg, color)

    def _show_header(self):
        """shows story's title and feature request, role and motivation"""
        self._output.write(self._colored(
                                '%s: %s\n' % (self._language['story'],
                                              self._title),
                                                  self.template_color))
        for line in [line.strip() for line in self.__doc__.split('\n') if line.strip()]:
            self._output.write(self._colored(
                                '  ' + line + '\n', self.template_color))

    @classmethod
    def run(instance_or_class):
        """``run`` can be called with a Story instance or a Story subclass.
           If passed a class, instantiates it"""
        if isinstance(instance_or_class, type):
            self = instance_or_class()
        else:
            self = instance_or_class
        self._show_header()

        number_of_scenarios = len(self._scenarios)
        number_of_failures = number_of_errors = number_of_pendings = 0

        self.namespace = Namespace()
        self.before_all(self.namespace)
         
        status_code = True
        try:
          for scenario, number in zip(self._scenarios, range(1, len(self._scenarios)+1)):
              self._output.write(self._colored('\n  %s %d: %s\n' % (
                                                  self._language['scenario'],
                                                  number,
                                                  scenario.title),
                                                      self.template_color))
              self.before_each(scenario)
              failures, errors, pendings = scenario.run()
              self.after_each(scenario)
              number_of_failures += len(failures)
              number_of_errors += len(errors)
              number_of_pendings += len(pendings)
              status_code = status_code and len(errors) == 0 and len(failures) == 0

          self._output_writer.output_statistics(number_of_scenarios,
                                 number_of_failures,
                                 number_of_errors,
                                 number_of_pendings,
                                 self.template_color)
          self._close_output_file_stream()
          return status_code
        finally:
          self.after_all(self.namespace)


    def before_all(self, scenario):
        pass

    def before_each(self, scenario):
        pass

    def after_all(self, scenario):
        pass

    def after_each(self, scenario):
        pass