def replace_completely(self, regex: Regex, text: str) -> 'String': string: str = self._rep while regex.matches(string): match_index: Tuple[str, int] = regex.find_match_index(string) match: str = match_index[0] index: int = match_index[1] string = string[:index] + text + string[index + len(match):] return String(string)
class Argument: DIRECTORY_PATH_REGEX: Regex = Regex( r'(C:\\)?(([A-z0-9 ])+\\)?([A-z0-9 ])+') FILE_PATH_REGEX: Regex = Regex( r'(C:\\)?(([A-z0-9 ])+\\)?([A-z0-9 ])+\.\w+') def __init__(self, name: str, description: str, values: List[str] = None, regex: Regex = None, required: bool = True, repeated: bool = False) -> None: self._name: str = name self._description: str = description self._values: List[str] = values self._regex: Regex = regex self._required: bool = required self._repeated: bool = repeated @property def name(self) -> str: return self._name @property def description(self) -> str: return self._description @property def values(self) -> List[str]: return self._values @property def regex(self) -> Regex: return self._regex @property def required(self) -> bool: return self._required @property def repeated(self) -> bool: return self._repeated
def split_sections(self, regex: Regex, include_separator: bool = True) -> List[str]: match_indexes: List[int] = [match_index[1] for match_index in regex.find_match_indexes(self._rep)] section_indexes: List[Tuple[int, int]] = [ (match_indexes[index], match_indexes[index + 1]) if index < len(match_indexes) - 1 else ( match_indexes[index], len(self._rep)) for index in range(0, len(match_indexes))] sections: List[str] = [] for start_index, end_index in section_indexes: consumer: Consumer = Consumer(self._rep[start_index:end_index]) if not include_separator: consumer.consume_through_regex(regex) sections.append(consumer.consume_to_end()) return sections
def is_file_valid(file_name: str, ignored_files: List[Regex], regex: Regex = None) -> bool: ignore_matches: List[Regex] = [] if ignored_files is not None: ignore_matches = [ file_regex for file_regex in ignored_files if file_regex.matches(file_name) ] not_ignored: bool = ignored_files is None or len(ignore_matches) == 0 matches_regex: bool = regex is None or regex.matches(file_name) return not_ignored and matches_regex
def is_directory_valid(directory_name: str, ignored_directories: List[Regex], regex: Regex = None) -> bool: ignore_matches: List[Regex] = [] if ignored_directories is not None: ignore_matches = [ directory_regex for directory_regex in ignored_directories if directory_regex.matches(directory_name) ] not_ignored: bool = ignored_directories is None or len(ignore_matches) == 0 matches_regex: bool = regex is None or regex.matches(directory_name) return not_ignored and matches_regex
from datetime import date from enum import IntEnum from typing import Dict, List from cac.consumer import Consumer from cac.math import Math from cac.regex import Regex from cac.string import String DATE_REGEX_1: Regex = Regex(r'\d{4}\D\d{2}\D\d{2}') DATE_REGEX_2: Regex = Regex(r'\d{2}\D\d{2}\D\d{4}') NUMBER_REGEX: Regex = Regex(r'\d+') NUM_MONTHS: int = 12 DAYS_IN_MONTHS: List[int] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] DAYS_IN_WEEK: int = 7 LEAP_MONTH: int = 2 LEAP_YEAR_FREQUENCY: int = 4 MONTHS: Dict[str, int] = { 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12
def matches(self, regex: Regex) -> bool: return regex.matches(self._rep)
def consume_through_regex(self, regex: Regex) -> str: match_index: Tuple[str, int] = regex.find_match_index(self._rep) return self._remove_chars(match_index[1] + len(match_index[0]))
def consume_regex(self, regex: Regex) -> str: match_index: Tuple[str, int] = regex.find_match_index(self._rep) if match_index[1] != 0: raise ValueError('Consumer does not start with regex \'' + str(regex) + '\'') return self.consume_through_sequence(match_index[0])
from typing import List, Tuple from cac.regex import Regex WHITESPACE_REGEX: Regex = Regex(r'\s') class Consumer: def __init__(self, rep: str) -> None: self._rep: str = rep def __str__(self) -> str: return self._rep def __repr__(self) -> str: return self._rep def __len__(self) -> int: return len(self._rep) def has_input(self) -> bool: return len(self._rep) > 0 def starts_with(self, sequence: str) -> bool: return self._rep.startswith(sequence) def contains(self, sequence: str) -> bool: return sequence in self._rep def matches(self, regex: Regex) -> bool:
def find_matching_lines(string_list: List[str], regex: Regex) -> List[str]: return [string for string in string_list if regex.matches(string)]
class Ignore: DIRECTORIES: List[Regex] = [ Regex(r'.ebextensions'), Regex(r'.git'), Regex(r'.idea'), Regex(r'.settings'), Regex(r'.vscode'), Regex(r'My Music'), Regex(r'My Pictures'), Regex(r'My Videos'), Regex(r'__pycache__'), Regex(r'bin'), Regex(r'build'), Regex(r'bundle'), Regex(r'dist'), Regex(r'node_modules'), Regex(r'out'), Regex(r'out-tsc'), Regex(r'target'), Regex(r'venv') ] FILES: List[Regex] = [ Regex(r'\.class$'), Regex(r'\.classpath$'), Regex(r'\.d.ts$'), Regex(r'\.factorypath$'), Regex(r'\.ico$'), Regex(r'\.ini$'), Regex(r'\.jpeg$'), Regex(r'\.jpg$'), Regex(r'\.lock$'), Regex(r'^package-lock.json$'), Regex(r'\.png$'), Regex(r'\.project$'), Regex(r'\.pyc$'), Regex(r'\.pyo$'), Regex(r'\.pyd$'), Regex(r'\.xlsx$') ]
import sys from typing import Dict, List, Set from cac.cli.argument import Argument from cac.cli.flag import Flag from cac.cli.printer import Printer from cac.finder import Finder from cac.regex import Regex FLAG_REGEX: Regex = Regex(r'^--?([A-z]\w*)$') def validate_parameter(parameter: str, input_flag: str, flag: Flag) -> None: if flag.values is not None and len( flag.values) > 0 and parameter not in flag.values: raise ValueError( 'Input \'{0}\' provided for flag \'{1}\' does not match one of the expected values ' '{2}'.format(parameter, input_flag, str(flag.values))) if flag.regex is not None and not flag.regex.matches(parameter): raise ValueError( 'Input \'{0}\' provided for flag \'{1}\' does not match the expected format ' '{2}'.format(parameter, input_flag, str(flag.regex))) def validate_argument(input_argument: str, argument: Argument) -> None: if argument.values is not None and len( argument.values) > 0 and input_argument not in argument.values: raise ValueError( 'Input \'{0}\' provided for argument \'{1}\' does not match one of the expected values ' '{2}'.format(input_argument, argument.name, str(argument.values))) if argument.regex is not None and not argument.regex.matches(
class Duration: DURATION_REGEX: Regex = Regex(r'(\d+:)?\d+:\d+') # noinspection PyArgumentEqualDefault @staticmethod def parse_duration(rep: str) -> 'Duration': if not Duration.DURATION_REGEX.matches(rep): raise ValueError('Duration must match the correct format') matches: List[str] = NUMBER_REGEX.find_matches(rep) if len(matches) == 2: return Duration(0, int(matches[0]), int(matches[1])) return Duration(int(matches[0]), int(matches[1]), int(matches[2])) def __init__(self, hours: int = 0, minutes: int = 0, seconds: int = 0) -> None: self._hours: int = hours self._minutes: int = minutes self._seconds: int = seconds def __eq__(self, other: 'Duration') -> bool: return self.hours == other.hours and self.minutes == other.minutes and self.seconds == other.seconds def __str__(self) -> str: return String.pad_number(self.hours, 2) + ':' + String.pad_number( self.minutes, 2) + ':' + String.pad_number(self.seconds, 2) def __repr__(self) -> str: return self.__str__() def __lt__(self, other: 'Duration') -> bool: reduced_self: Duration = self.reduce() reduced_other: Duration = other.reduce() if reduced_self.hours == reduced_other.hours: if reduced_self.minutes == reduced_other.minutes: if reduced_self.seconds == reduced_other.seconds: return False return reduced_self.seconds < reduced_other.seconds return reduced_self.minutes < reduced_other.minutes return reduced_self.hours < reduced_other.hours def __le__(self, other: 'Duration') -> bool: reduced_self: Duration = self.reduce() reduced_other: Duration = other.reduce() if reduced_self.hours == reduced_other.hours: if reduced_self.minutes == reduced_other.minutes: if reduced_self.seconds == reduced_other.seconds: return False return reduced_self.seconds <= reduced_other.seconds return reduced_self.minutes <= reduced_other.minutes return reduced_self.hours <= reduced_other.hours def __gt__(self, other: 'Duration') -> bool: reduced_self: Duration = self.reduce() reduced_other: Duration = other.reduce() if reduced_self.hours == reduced_other.hours: if reduced_self.minutes == reduced_other.minutes: if reduced_self.seconds == reduced_other.seconds: return False return reduced_self.seconds > reduced_other.seconds return reduced_self.minutes > reduced_other.minutes return reduced_self.hours > reduced_other.hours def __ge__(self, other: 'Duration') -> bool: reduced_self: Duration = self.reduce() reduced_other: Duration = other.reduce() if reduced_self.hours == reduced_other.hours: if reduced_self.minutes == reduced_other.minutes: if reduced_self.seconds == reduced_other.seconds: return False return reduced_self.seconds >= reduced_other.seconds return reduced_self.minutes >= reduced_other.minutes return reduced_self.hours >= reduced_other.hours @property def hours(self) -> int: return self._hours @property def minutes(self) -> int: return self._minutes @property def seconds(self) -> int: return self._seconds def add(self, segment_duration: 'Duration') -> 'Duration': full_duration: Duration = self._copy() full_duration._hours += segment_duration.hours full_duration._minutes += segment_duration.minutes full_duration._seconds += segment_duration.seconds return full_duration.reduce() def subtract(self, segment_duration: 'Duration') -> 'Duration': full_duration: Duration = self._copy() full_duration._hours -= segment_duration.hours full_duration._minutes -= segment_duration.minutes full_duration._seconds -= segment_duration.seconds while full_duration._seconds < 0: full_duration._seconds += 60 full_duration._minutes -= 1 while full_duration._minutes < 0: full_duration._minutes += 60 full_duration._hours -= 1 if full_duration._hours < 0: raise ValueError('Hours cannot be negative') return full_duration.reduce() def divide(self, number: int) -> 'Duration': expanded_duration: Duration = self._expand() divided_seconds: int = round(expanded_duration.seconds / number) divided_duration: Duration = Duration(0, 0, divided_seconds) return divided_duration.reduce() def reduce(self, round_up: bool = False) -> 'Duration': duration: Duration = self._copy() while duration._seconds >= 60: duration._seconds -= 60 duration._minutes += 1 if round_up and duration._seconds > 0: duration._minutes += 1 while duration._minutes >= 60: duration._minutes -= 60 duration._hours += 1 return duration def _expand(self) -> 'Duration': duration: Duration = self._copy() while duration._hours > 0: duration._minutes += 60 duration._hours -= 1 while duration._minutes > 0: duration._seconds += 60 duration._minutes -= 1 return duration def _copy(self) -> 'Duration': return Duration(self.hours, self.minutes, self.seconds)
from typing import List from cac.regex import Regex from cac.string import String NUMBER_REGEX: Regex = Regex(r'\d+') class Duration: DURATION_REGEX: Regex = Regex(r'(\d+:)?\d+:\d+') # noinspection PyArgumentEqualDefault @staticmethod def parse_duration(rep: str) -> 'Duration': if not Duration.DURATION_REGEX.matches(rep): raise ValueError('Duration must match the correct format') matches: List[str] = NUMBER_REGEX.find_matches(rep) if len(matches) == 2: return Duration(0, int(matches[0]), int(matches[1])) return Duration(int(matches[0]), int(matches[1]), int(matches[2])) def __init__(self, hours: int = 0, minutes: int = 0, seconds: int = 0) -> None: self._hours: int = hours self._minutes: int = minutes self._seconds: int = seconds def __eq__(self, other: 'Duration') -> bool: return self.hours == other.hours and self.minutes == other.minutes and self.seconds == other.seconds