def handle(_, block: Block, options: list[str]): """Hides or shows blocks based on their tags. Every option with the exception of the last is treated as a tag category. The last option is the tag inside that category.""" if options == []: raise GeneratorError(_EMPTY_TAG_ERROR.format("handler")) command_category = options[:-1] command_tag = options[-1] tag_index = len(options) - 1 for rule in block.get_rules(_NAME): split_description = rule.description.split() if split_description == []: raise GeneratorError(_EMPTY_TAG_ERROR.format("rule"), rule.line_number) if len(split_description) <= tag_index: continue rule_category = split_description[:tag_index] rule_tag = split_description[tag_index] if command_category == rule_category: if command_tag == rule_tag: block.show() else: block.hide() return [block]
def _parse_rule_params(rule: Rule, previous_params: list[_Params]): current_filepath = previous_params[-1].filepath parts = rule.description.split(_SPLITTER) if len(parts) > 3: error = _INCORRECT_RULE_FORMAT_ERROR.format(rule.description) raise GeneratorError(error, rule.line_number, current_filepath) filepath = _parse_rule_filepath(current_filepath, parts[0].strip()) if not os.path.exists(filepath): error = _FILTER_DOES_NOT_EXIST_ERROR.format(rule.description) raise GeneratorError(error, rule.line_number, current_filepath) blockname = parts[1].strip() if len(parts) > 1 else None if blockname == "": error = _EMPTY_PARAMETER_ERROR.format(rule.description, "block name") raise GeneratorError(error, rule.line_number, current_filepath) line_pattern = parts[2].strip() if len(parts) > 2 else None if line_pattern == "": error = _EMPTY_PARAMETER_ERROR.format(rule.description, "line pattern") raise GeneratorError(error, rule.line_number, current_filepath) params = _Params(filepath, blockname, line_pattern) if any(params.cycle_with(previous) for previous in previous_params): error = _CIRCULAR_REFERENCE_ERROR.format(rule.description) raise GeneratorError(error, rule.line_number, current_filepath) return params
def handle(_, block: Block, options: list[str]): """Handles creation of strictness subfilters. Only one option is accepted and it should include the strictness value to use.""" if len(options) != 1: raise GeneratorError( _STRICTNESS_ARG_COUNT_ERROR.format("handler", len(options))) if not options[0].strip().isdigit(): raise GeneratorError( _STRICTNESS_ARG_TYPE_ERROR.format("handler", options[0])) command_strictness = int(options[0]) for rule in block.get_rules(_NAME): if not rule.description.strip().isdigit(): raise GeneratorError( _STRICTNESS_ARG_TYPE_ERROR.format("rule", rule.description), rule.line_number) rule_strictness = int(rule.description) if rule_strictness >= command_strictness: block.show() else: block.hide() return [block]
def _get_blocks(self, filepath: str): try: with open(self.filepath, "r") as file: raw_lines = file.readlines() return Block.extract(raw_lines) except FileNotFoundError: raise GeneratorError(_FILE_NOT_FOUND_ERROR, filepath=filepath) except PermissionError: raise GeneratorError(_PERMISSION_ERROR, filepath=filepath)
def save(self, output_filepath: str): """Saves the filter to the indicated output filepath.""" self._create_directory(output_filepath) try: with open(output_filepath, "w") as file: for block in self.blocks: for line in block.lines: file.write(f"{line.text}\n") except FileExistsError: raise GeneratorError(_FILE_EXISTS_ERROR, filepath=self.filepath) except PermissionError: raise GeneratorError(_PERMISSION_ERROR, filepath=self.filepath)
def __init__(self, text: str, number: int): self.text: str = text.rstrip() if '\n' in self.text: raise GeneratorError(_MULTILINE_STRING_ERROR, number) self.number: int = number self.rules: list[Rule] = Rule.extract(number, text)
def __init__(self, args: list[str]): if len(args) < 2: raise GeneratorError(_TOO_LITTLE_ARGUMENTS_ERROR) self.input_filepath: str = args[0] self.output_filepath: str = self._get_output_file(args[1]) self.handler: str = self._get_handler(args[1:]) self.options: list[str] = self._get_options(args[1:])
def _get_handler(self, args: list[str]): if args[0].startswith(_HANDLER_TAG): return args[0].lstrip(_HANDLER_TAG) elif len(args) > 1 and args[1].startswith(_HANDLER_TAG): return args[1].lstrip(_HANDLER_TAG) else: raise GeneratorError(_HANDLER_NOT_FOUND_ERROR)
def _get_line(block: Block, line_pattern: str, filepath: str): for line in block.lines: if line.contains(line_pattern) or line.contains_in_comment( line_pattern): return line blockname = _get_blockname(block) error = _LINE_PATTERN_NOT_FOUND.format(line_pattern, blockname) raise GeneratorError(error, block.line_number, filepath)
def _get_league(options: list[str]): global _current_league try: if not _current_league: headers = {'User-Agent': _POE_FILTER_GENERATOR_USER_AGENT} response = requests.get(_LEAGUE_NAME_API_URL, headers=headers) response.raise_for_status() leagues = response.json() if _STANDARD_TAG in options: _current_league = leagues[_LEAGUE_NAME_STANDARD_INDEX]["id"] elif _HARDCORE_TAG in options: _current_league = leagues[_LEAGUE_NAME_TEMP_HC_INDEX]["id"] else: _current_league = leagues[_LEAGUE_NAME_TEMP_INDEX]["id"] return _current_league except HTTPError as error: raise GeneratorError( _HTTP_ERROR.format(_LEAGUE_NAMES_ERROR_TEXT, error)) except (ConnectTimeout, ReadTimeout, Timeout, requests.ConnectionError): raise GeneratorError( _CONNECTION_ERROR.format(_LEAGUE_NAMES_ERROR_TEXT))
def _get_poe_ninja_lines(league: str, type: str): global _poe_ninja_cache try: if type not in _poe_ninja_cache: type_is_currency_or_frags = type == _TYPES[ "cur"] or type == _TYPES["fra"] url = _CURRENCY_API_URL if type_is_currency_or_frags else _ITEM_API_URL response = requests.get(url, params={ "league": league, "type": type }) response.raise_for_status() _poe_ninja_cache[type] = response.json()["lines"] return _poe_ninja_cache[type] except HTTPError as error: raise GeneratorError( _HTTP_ERROR.format(_POE_NINJA_DATA_ERROR_TEXT, error)) except (ConnectTimeout, ReadTimeout, Timeout, requests.ConnectionError): raise GeneratorError( _CONNECTION_ERROR.format(_POE_NINJA_DATA_ERROR_TEXT))
def extract(cls, line_number: int, text: str): """Returns all rules in a text as a list of rules.""" rules = [] if _RULE_START in text: text = text[text.index(_RULE_START) + len(_RULE_START):] rule_strings = text.split(_RULE_SEPARATOR) for rule_string in rule_strings: fields = rule_string.split(maxsplit=1) if len(fields) > 2: raise GeneratorError(_TOO_MANY_FIELDS_ERROR, line_number) name = fields[0].strip() if name == '': raise GeneratorError(_EMPTY_NAME_ERROR, line_number) description = fields[1].strip() if len(fields) == 2 else "" if description == '' and len(fields) == 2: raise GeneratorError(_EMPTY_DESCRIPTION_ERROR, line_number) rules.append(Rule(line_number, name, description)) return rules
def _parse_rule_params(rule: Rule): parts = rule.description.split() if len(parts) < 2 or len(parts) > 3: raise GeneratorError(_RULE_PARAMETER_COUNT_ERROR.format(len(parts)), rule.line_number) try: if len(parts) == 2: return { "type": _TYPES[parts[0]], "lower": float(parts[1]), "upper": None } else: return { "type": _TYPES[parts[0]], "lower": float(parts[1]), "upper": float(parts[2]) } except KeyError: raise GeneratorError(_RULE_TYPE_ERROR.format(parts[0]), rule.line_number) except ValueError: raise GeneratorError(_RULE_BOUNDS_ERROR.format(parts[1], parts[2]), rule.line_number)
def _get_handler(self, handler_name: str): try: return importlib.import_module(_HANDLERS_PATH + handler_name) except ModuleNotFoundError: raise GeneratorError(_HANDLER_NOT_FOUND_ERROR.format(handler_name))
def _get_block(filter: Filter, blockname: str): for block in filter.blocks: if blockname == _get_blockname(block): return block error = _BLOCK_NOT_FOUND_ERROR.format(blockname) raise GeneratorError(error, filepath=filter.filepath)