Beispiel #1
0
 def from_input(cls, argument: str, user: User,
                sub_repo) -> 'E621TaggingSource':
     parsed = InputParser(argument)
     tags_arg = parsed.get_arg_by_names([
         "tags", "watched_tags", "to_tag", "watched tags", "to tag", "watch"
     ])
     search_arg = parsed.get_arg_by_names([
         "search",
         "query",
         "search_query",
         "search query",
         "subscription",
         "sub",
         "search_term",
         "search term",
     ])
     if tags_arg is not None:
         tags = tags_arg.split()
         if search_arg is not None:
             search = search_arg
         else:
             search = parsed.remaining_text
     else:
         if search_arg is not None:
             search = search_arg
             tags = parsed.remaining_text.split()
         else:
             raise hallo.modules.subscriptions.subscription_exception.SubscriptionException(
                 'You need to specify a search term with search="search term" and '
                 'tags to watch with tags="tags to watch"')
     return E621TaggingSource(search, tags)
Beispiel #2
0
def test_mismatched_quotes():
    p = InputParser('yo \'base unit"="hello world"')
    assert p.remaining_text == "yo 'base"
    assert p.args_dict['unit"'] == "hello world"
    p = InputParser("yo 'base unit'=\"hello's world\"")
    assert p.remaining_text == "yo"
    assert p.args_dict["base unit"] == "hello's world"
Beispiel #3
0
def test_get_arg_by_names_first_match():
    p = InputParser("blah blah arg1=val1 arg2=val2 arg3=val3")
    assert p.remaining_text == "blah blah"
    assert p.get_arg_by_names(["arg1", "arg2"]) == "val1"
    assert p.args_dict["arg1"] == "val1"
    assert p.args_dict["arg2"] == "val2"
    assert p.args_dict["arg3"] == "val3"
Beispiel #4
0
 def run(self, event):
     # Load repo, clean line
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function)  # type: Convert
     repo = convert_function_obj.convert_repo
     # Parse input
     parsed = InputParser(event.command_args)
     # Check if unit is defined
     unit_name = parsed.get_arg_by_names(self.NAMES_UNIT)
     # Check if type is defined
     type_obj = None
     type_name = parsed.get_arg_by_names(self.NAMES_TYPE)
     if type_name is not None:
         type_obj = repo.get_type_by_name(type_name)
         if type_obj is None:
             return event.create_response("Invalid type specified.")
     # Check if delete name is specified
     del_name = parsed.get_arg_by_names(self.NAMES_DEL)
     if del_name is None:
         del_name = parsed.remaining_text
     # Check if description is sufficient to narrow it to 1 and only 1 unit
     unit_list = (repo.get_full_unit_list()
                  if type_obj is None else type_obj.get_full_unit_list())
     user_unit_options = []
     for unit_obj in unit_list:
         # if unit name is defined and not a valid name for the unit, skip it.
         if unit_name is not None and not unit_obj.has_name(unit_name):
             continue
         # If input_name is not a valid name for the unit, skip it.
         if not unit_obj.has_name(del_name):
             continue
         # Otherwise it's the one, add it to the list
         user_unit_options.append(unit_obj)
     # Check if that narrowed it down correctly.
     if len(user_unit_options) == 0:
         return event.create_response(
             "There are no units matching that description.")
     if len(user_unit_options) >= 2:
         return event.create_response(
             "It is ambiguous which unit you refer to.")
     # Check this unit has other names.
     user_unit = user_unit_options[0]
     if len(user_unit.name_list) == 1:
         return event.create_response(
             "This unit only has 1 name, you cannot remove its last name.")
     # Remove name
     user_unit.remove_name(del_name)
     # Save repo
     repo.save_json()
     # Output
     return event.create_response(
         'Removed name "{}" from "{}" unit.'.format(del_name,
                                                    user_unit.name_list[0]))
Beispiel #5
0
def test_parse_string_all_numbers():
    p = InputParser("5 421 8916 34.5 -3")
    assert p.remaining_text == "5 421 8916 34.5 -3"
    assert len(p.args_dict) == 0
    assert len(p.string_words) == 0
    assert len(p.number_words) == 5
    assert p.number_words == [5, 421, 8916, 34.5, -3]
Beispiel #6
0
 def run(self, event):
     # Load convert repo
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function)  # type: Convert
     repo = convert_function_obj.convert_repo
     # Parse input
     parsed = InputParser(event.command_args)
     # If decimals is null, return error
     if len(parsed.number_words) == 0:
         return event.create_response(
             "Please specify a conversion type and a number of decimal places it should output."
         )
     # Convert decimals to integer
     decimals = int(parsed.number_words[0])
     # Get selected type
     input_type = repo.get_type_by_name(" ".join(parsed.string_words))
     # If type does not exist, return error
     if input_type is None:
         return event.create_response(
             "This is not a recognised conversion type.")
     # Set decimals
     input_type.decimals = decimals
     # Save repo
     repo.save_json()
     # Output message
     return event.create_response(
         "Set the number of decimal places to display for " +
         '"{}" type units at {} places.'.format(input_type.name, decimals))
Beispiel #7
0
def test_parse_string_mix_of_numbers_and_args():
    p = InputParser("blah blah arg1=val1 arg2=val2 5")
    assert p.remaining_text == "blah blah 5"
    assert p.args_dict["arg1"] == "val1"
    assert p.args_dict["arg2"] == "val2"
    assert p.string_words == ["blah", "blah"]
    assert p.number_words == [5]
Beispiel #8
0
def test_parse_string_no_numbers():
    p = InputParser("blah bloo blee")
    assert p.remaining_text == "blah bloo blee"
    assert len(p.args_dict) == 0
    assert len(p.string_words) == 3
    assert len(p.number_words) == 0
    assert p.string_words == ["blah", "bloo", "blee"]
Beispiel #9
0
def test_all_types():
    p = InputParser(
        "yo 'base unit'=\"hello world\" arg1='value 1' 'arg 2'=val2 arg3=val3")
    assert p.remaining_text == "yo"
    assert p.args_dict["base unit"] == "hello world"
    assert p.args_dict["arg1"] == "value 1"
    assert p.args_dict["arg 2"] == "val2"
    assert p.args_dict["arg3"] == "val3"
Beispiel #10
0
 def add_unit(self, user_input, ref_measure_list):
     """
     :type user_input: str
     :type ref_measure_list: list[ConvertMeasure]
     :rtype: str
     """
     # Check reference measure has exactly 1 unit option
     if len(ref_measure_list) == 0:
         return "There is no defined unit matching the reference name."
     if len(ref_measure_list) > 1:
         return "It is ambiguous which unit you are referring to."
     # Get unit type
     ref_measure = ref_measure_list[0]
     ref_amount = ref_measure.amount
     ref_unit = ref_measure.unit
     ref_type = ref_unit.type
     ref_value = ref_unit.value
     ref_offset = ref_unit.offset
     base_unit = ref_type.base_unit
     base_name = base_unit.name_list[0]
     # Get amount & unit name
     # TODO: accept calculation
     parsed = InputParser(user_input)
     if len(parsed.number_words) != 1:
         return "Please specify an amount when setting a new unit."
     input_amount_float = float(parsed.number_words[0])
     # Remove amountString from userInput
     input_name = " ".join(parsed.string_words)
     # Check name isn't already in use.
     if ref_type.get_unit_by_name(input_name) is not None:
         return "There's already a unit of that type by that name."
     # Add unit
     new_unit = hallo.modules.convert.convert_repo.ConvertUnit(
         ref_type, [input_name], 1)
     ref_type.add_unit(new_unit)
     # Update offset or value, based on what the user inputed.
     # If either given amount are zero, set the offset of varUnit.
     if input_amount_float == 0 or ref_amount == 0:
         # Calculate the new offset
         new_offset = ref_offset + ref_amount * ref_value - input_amount_float * 1
         new_unit.update_offset(new_offset)
         # Save repo
         repo = ref_unit.type.repo
         repo.save_json()
         # Output message
         return "Created new unit {} with offset: 0 {} = {} {}.".format(
             input_name, input_name, new_offset, base_name)
     # Get new value
     new_value = (ref_offset + ref_amount * ref_value -
                  0) / input_amount_float
     new_unit.update_value(new_value)
     # Save repo
     repo = ref_unit.type.repo
     repo.save_json()
     # Output message
     return "Created new unit {} with value: 1 {} = {} {}.".format(
         input_name, input_name, new_value, base_name)
Beispiel #11
0
 def run(self, event):
     # Load repo, clean line
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function
     )  # type: Convert
     repo = convert_function_obj.convert_repo
     # Clean input
     line_clean = event.command_args.strip()
     parsed_input = InputParser(line_clean)
     # Check if base unit is defined
     unit_name = parsed_input.get_arg_by_names(self.NAMES_BASE_UNIT)
     # Check if decimal places is defined
     decimals = parsed_input.get_arg_by_names(self.NAMES_DECIMALS)
     decimals = int(decimals) if decimals is not None else None
     # Clean unit and type setting from the line to just get the name to remove
     input_name = parsed_input.remaining_text
     # Check that type name doesn't already exist.
     existing_type = repo.get_type_by_name(input_name)
     if existing_type is not None:
         return event.create_response("A type by this name already exists.")
     # Check base unit name was defined.
     if unit_name is None:
         return event.create_response(
             "You must define a base unit for this type using unit=<unit name>."
         )
     # Create new type, Create new unit, set unit as base unit, set decimals
     new_type = hallo.modules.convert.convert_repo.ConvertType(repo, input_name)
     new_base_unit = hallo.modules.convert.convert_repo.ConvertUnit(new_type, [unit_name], 1)
     new_type.base_unit = new_base_unit
     if decimals is not None:
         new_type.decimals = decimals
     # add type to repo, save
     repo.add_type(new_type)
     repo.save_json()
     # Output message
     decimal_string = ""
     if decimals is not None:
         decimal_string = " and {} decimal places".format(decimals)
     output_string = 'Created new type "{}" with base unit "{}"{}.'.format(
         input_name, unit_name, decimal_string
     )
     return event.create_response(output_string)
Beispiel #12
0
 def run(self, event):
     # Load repo
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function)  # type: Convert
     repo = convert_function_obj.convert_repo
     # Parse input
     parsed = InputParser(event.command_args)
     # Check if type is specified
     type_name = parsed.get_arg_by_names(self.NAMES_TYPE)
     unit_name = parsed.get_arg_by_names(self.NAMES_UNIT)
     prefix_group_name = parsed.get_arg_by_names(self.NAMES_PREFIXGROUP)
     prefix_name = parsed.get_arg_by_names(self.NAMES_PREFIX)
     if type_name is not None:
         # Get type name and object
         type_obj = repo.get_type_by_name(type_name)
         if type_obj is None:
             return event.create_response("Unrecognised type specified.")
         # Check if unit & type are specified
         if unit_name is not None:
             # Get unit name and object
             unit_obj = type_obj.get_unit_by_name(unit_name)
             if unit_obj is None:
                 return event.create_response(
                     "Unrecognised unit specified.")
             return event.create_response(
                 self.output_unit_as_string(unit_obj))
         # Type is defined, but not unit.
         return event.create_response(self.output_type_as_string(type_obj))
     # Check if prefix group is specified
     if prefix_group_name is not None:
         # Check if prefix & group are specified
         prefix_group_obj = repo.get_prefix_group_by_name(prefix_group_name)
         if prefix_group_obj is None:
             return event.create_response(
                 "Unrecognised prefix group specified.")
         # Check if prefix group & prefix are specified
         if prefix_name is not None:
             # Get prefix name and object
             prefix_obj = prefix_group_obj.get_prefix_by_name(
                 prefix_name) or prefix_group_obj.get_prefix_by_abbr(
                     prefix_name)
             if prefix_obj is None:
                 return event.create_response(
                     "Unrecognised prefix specified.")
             return event.create_response(
                 self.output_prefix_as_string(prefix_obj))
         # Prefix group is defined, but not prefix
         return event.create_response(
             self.output_prefix_group_as_string(prefix_group_obj))
     # Check if unit is specified
     if unit_name is not None:
         output_lines = []
         # Loop through types, getting units for each type
         for type_obj in repo.type_list:
             unit_obj = type_obj.get_unit_by_name(unit_name)
             # If unit exists by that name, add the string format to output list
             if unit_obj is not None:
                 output_lines.append(self.output_unit_as_string(unit_obj))
         if len(output_lines) == 0:
             return event.create_response("Unrecognised unit specified.")
         return event.create_response("\n".join(output_lines))
     # Check if prefix is specified
     if prefix_name is not None:
         output_lines = []
         # Loop through groups, getting prefixes for each group
         for prefix_group_obj in repo.prefix_group_list:
             prefix_obj = prefix_group_obj.get_prefix_by_name(
                 prefix_name) or prefix_group_obj.get_prefix_by_abbr(
                     prefix_name)
             # If prefix exists by that name, add the string format to output list
             if prefix_obj is not None:
                 output_lines.append(
                     self.output_prefix_as_string(prefix_obj))
         if len(output_lines) == 0:
             return event.create_response("Unrecognised prefix specified.")
         return event.create_response("\n".join(output_lines))
     # Nothing was specified, return info on the repo.
     return event.create_response(self.output_repo_as_string(repo))
Beispiel #13
0
def test_multiple_simple_args():
    p = InputParser("blah blah arg1=val1 arg2=val2 arg3=val3")
    assert p.remaining_text == "blah blah"
    assert p.args_dict["arg1"] == "val1"
    assert p.args_dict["arg2"] == "val2"
    assert p.args_dict["arg3"] == "val3"
Beispiel #14
0
def test_unstripped_input():
    p = InputParser("   blah blah ")
    assert p.remaining_text == "blah blah"
Beispiel #15
0
def test_remaining_text_start_and_end():
    p = InputParser("blah blah arg1=val1 arg2=val2 hey")
    assert p.remaining_text == "blah blah hey"
    assert p.args_dict["arg1"] == "val1"
    assert p.args_dict["arg2"] == "val2"
Beispiel #16
0
def test_unquoted_args_unquoted_values():
    p = InputParser("yo base unit=hello world")
    assert p.remaining_text == "yo base world"
    assert p.args_dict["unit"] == "hello"
Beispiel #17
0
def test_no_args():
    p = InputParser("blah blah")
    assert p.remaining_text == "blah blah"
    assert len(p.args_dict) == 0
Beispiel #18
0
def test_quoted_args_quoted_values():
    p = InputParser("yo 'base unit'=\"hello world\"")
    assert p.remaining_text == "yo"
    assert p.args_dict["base unit"] == "hello world"
Beispiel #19
0
 def run(self, event):
     # Load convert repo
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function
     )  # type: Convert
     repo = convert_function_obj.convert_repo
     # Parse input
     parsed = InputParser(event.command_args)
     # Check if a type is specified
     type_name = parsed.get_arg_by_names(self.NAMES_TYPE)
     # Clean type setting from the line to just get the name to remove
     input_name = parsed.remaining_text
     # Find unit
     if type_name is not None:
         type_obj = repo.get_type_by_name(type_name)
         if type_obj is None:
             return event.create_response("This conversion type is not recognised.")
         input_unit = type_obj.get_unit_by_name(input_name)
         if input_unit is None:
             return event.create_response(
                 "This unit name is not recognised for that unit type."
             )
     else:
         input_unit_list = []
         for type_obj in repo.type_list:
             input_unit = type_obj.get_unit_by_name(input_name)
             if input_unit is not None:
                 input_unit_list.append(input_unit)
         # Check if results are 0
         if len(input_unit_list) == 0:
             return event.create_response(
                 "No unit by that name is found in any type."
             )
         # Check if results are >=2
         if len(input_unit_list) >= 2:
             unit_outputs = []
             for input_unit in input_unit_list:
                 unit_outputs.append(
                     "{} (type={})".format(
                         input_unit.name_list[0], input_unit.type.name
                     )
                 )
             return event.create_response(
                 "There is more than one unit matching this name: {}".format(
                     ", ".join(unit_outputs)
                 )
             )
         input_unit = input_unit_list[0]
     # Ensure it is not a base unit for its type
     if input_unit == input_unit.type.base_unit:
         return event.create_response(
             "You cannot remove the base unit for a unit type."
         )
     # Remove unit
     input_unit_name = input_unit.name_list[0]
     input_unit.type.remove_unit(input_unit)
     # Done
     return event.create_response(
         'Removed unit "{}" from conversion repository.'.format(input_unit_name)
     )
Beispiel #20
0
 def run(self, event):
     # Load repository
     function_dispatcher = event.server.hallo.function_dispatcher
     convert_function = function_dispatcher.get_function_by_name("convert")
     convert_function_obj = function_dispatcher.get_function_object(
         convert_function)  # type: Convert
     repo = convert_function_obj.convert_repo
     # Parse input
     parsed = InputParser(event.command_args)
     # Check for type=
     type_name = parsed.get_arg_by_names(self.NAMES_TYPE)
     # Check for unit=
     unit_name = parsed.get_arg_by_names(self.NAMES_UNIT)
     # Check for abbr=
     abbr_name = parsed.get_arg_by_names(self.NAMES_ABBR)
     # If unit= or abbr= then remaining is the other one.
     if unit_name is None and abbr_name is not None:
         unit_name = parsed.remaining_text
     if abbr_name is None and unit_name is not None:
         abbr_name = parsed.remaining_text
     # Get unit list
     if type_name is None:
         unit_list = repo.get_full_unit_list()
     else:
         type_obj = repo.get_type_by_name(type_name)
         if type_obj is None:
             return event.create_response("Unrecognised type.")
         unit_list = type_obj.get_full_unit_list()
     # If no unit=, try splitting the line to find where the old name ends and new name begins
     if unit_name is None and abbr_name is None:
         # Check at least 2 words are given
         line_split = parsed.remaining_text.split()
         if len(line_split) <= 1:
             return event.create_response(
                 "You must specify both a unit name and an abbreviation to add."
             )
         # Scan remaining text for split
         pairs = parsed.split_remaining_into_two(
             lambda x, y: any([u.has_name(x) for u in unit_list]))
         # If not exactly 1 split, return an error
         if len(pairs) != 1:
             return event.create_response(
                 "Could not parse where unit name ends and abbreviation begins. "
                 "Please specify with unit=<name>")
         # Handle the returned pair
         unit_name = pairs[0][0]
         abbr_name = pairs[0][1]
     # Get the unit object from the name
     input_unit_list = []
     for unit_obj in unit_list:
         if unit_obj.has_name(unit_name):
             input_unit_list.append(unit_obj)
     # If 0 units found, throw error
     if len(input_unit_list) == 0:
         return event.create_response("No unit found by that name.")
     # If 2+ units found, throw error
     if len(input_unit_list) >= 2:
         return event.create_response(
             "Unit name is too ambiguous, please specify with unit=<name> and type=<name>."
         )
     unit_obj = input_unit_list[0]
     # If abbreviation name is empty, throw error
     if len(abbr_name) == 0:
         return event.create_response("Abbreviation name cannot be blank.")
     # Add the new name
     unit_obj.add_abbr(abbr_name)
     # Save repo
     repo.save_json()
     # Output message
     return event.create_response('Added "{}" as a new abbreviation for '
                                  'the "{}" unit.'.format(
                                      abbr_name, unit_obj.name_list[0]))
    def run(self, event):
        # Load repository
        function_dispatcher = event.server.hallo.function_dispatcher
        convert_function = function_dispatcher.get_function_by_name("convert")
        convert_function_obj = function_dispatcher.get_function_object(
            convert_function)  # type: Convert
        repo = convert_function_obj.convert_repo
        # Parse input
        parsed = InputParser(event.command_args)
        # Check for type=
        type_name = parsed.get_arg_by_names(self.NAMES_TYPE)
        # Check for unit=
        unit_name = parsed.get_arg_by_names(self.NAMES_UNIT)
        # Check for prefixgroup=
        prefix_group_name = parsed.get_arg_by_names(self.NAMES_PREFIX_GROUP)
        # clean up the line
        input_name = parsed.remaining_text
        # If unit name xor prefix group is none, use input name
        if unit_name is None and prefix_group_name is not None:
            unit_name = input_name
        if prefix_group_name is None and unit_name is not None:
            prefix_group_name = input_name
        # Get unit list
        if type_name is None:
            unit_list = repo.get_full_unit_list()
        else:
            type_obj = repo.get_type_by_name(type_name)
            if type_obj is None:
                return event.create_response("Unrecognised type specified.")
            unit_list = type_obj.get_full_unit_list()
        # Get parse remaining text into unit name and prefix group name
        if unit_name is None and prefix_group_name is None:
            # Check at least 2 words are given
            line_split = parsed.remaining_text.split()
            if len(line_split) <= 1:
                return event.create_response(
                    "You must specify both a unit name and a prefix group to set."
                )

            # Scan remaining text for split

            def is_unit_name_valid(name):
                return any([u.has_name(name) for u in unit_list])

            def is_prefix_group_valid(name):
                return (name.lower() == "none"
                        or repo.get_prefix_group_by_name(name) is not None)

            pairs = parsed.split_remaining_into_two(
                lambda x, y: is_unit_name_valid(x) and is_prefix_group_valid(y
                                                                             ))
            # If not exactly 1 split, return an error
            if len(pairs) != 1:
                return event.create_response(
                    "Could not parse where unit name ends and prefix group begins. "
                    "Please specify with unit=<name> prefix_group=<name>")
            # Handle the returned pair
            unit_name = pairs[0][0]
            prefix_group_name = pairs[0][1]
            if prefix_group_name.lower() == "none":
                prefix_group = None
            else:
                prefix_group = repo.get_prefix_group_by_name(prefix_group_name)
        else:
            prefix_group = repo.get_prefix_group_by_name(prefix_group_name)
            if prefix_group is None and prefix_group_name.lower() != "none":
                return event.create_response("Prefix group not recognised.")
        # Get unit object from name
        input_unit_list = []
        for unit_obj in unit_list:
            if unit_obj.has_name(unit_name):
                input_unit_list.append(unit_obj)
        # If 0 units found, throw error
        if len(input_unit_list) == 0:
            return event.create_response("No unit found by that name.")
        # If 2+ units found, throw error
        if len(input_unit_list) >= 2:
            return event.create_response(
                "Unit name is too ambiguous, please specify with unit= and type= ."
            )
        unit_obj = input_unit_list[0]
        # Set the prefix group
        unit_obj.valid_prefix_group = prefix_group
        # Save repo
        repo.save_json()
        # Output message
        if prefix_group is None:
            prefix_group_name = "none"
        else:
            prefix_group_name = prefix_group.name
        return event.create_response('Set "{}" as the prefix group for '
                                     'the "{}" unit.'.format(
                                         prefix_group_name,
                                         unit_obj.name_list[0]))