mirror of
				https://github.com/Garmelon/PFERD.git
				synced 2025-11-04 06:32:52 +01:00 
			
		
		
		
	Load and dump config
This commit is contained in:
		@@ -1,98 +1,25 @@
 | 
			
		||||
"""
 | 
			
		||||
A few utility bobs and bits.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
from pathlib import Path, PurePath
 | 
			
		||||
from typing import Optional, Tuple, Union
 | 
			
		||||
 | 
			
		||||
import bs4
 | 
			
		||||
import requests
 | 
			
		||||
 | 
			
		||||
from .progress import ProgressSettings, progress_for, size_from_headers
 | 
			
		||||
 | 
			
		||||
PathLike = Union[PurePath, str, Tuple[str, ...]]
 | 
			
		||||
from typing import Optional
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_path(pathlike: PathLike) -> Path:
 | 
			
		||||
def prompt_yes_no(query: str, default: Optional[bool]) -> bool:
 | 
			
		||||
    """
 | 
			
		||||
    Convert a given PathLike into a Path.
 | 
			
		||||
    """
 | 
			
		||||
    if isinstance(pathlike, tuple):
 | 
			
		||||
        return Path(*pathlike)
 | 
			
		||||
    return Path(pathlike)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Regex = Union[str, re.Pattern]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_pattern(regex: Regex) -> re.Pattern:
 | 
			
		||||
    """
 | 
			
		||||
    Convert a regex to a re.Pattern.
 | 
			
		||||
    """
 | 
			
		||||
    if isinstance(regex, re.Pattern):
 | 
			
		||||
        return regex
 | 
			
		||||
    return re.compile(regex)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def soupify(response: requests.Response) -> bs4.BeautifulSoup:
 | 
			
		||||
    """
 | 
			
		||||
    Wrap a requests response in a bs4 object.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    return bs4.BeautifulSoup(response.text, "html.parser")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def stream_to_path(
 | 
			
		||||
        response: requests.Response,
 | 
			
		||||
        target: Path,
 | 
			
		||||
        progress_name: Optional[str] = None,
 | 
			
		||||
        chunk_size: int = 1024 ** 2
 | 
			
		||||
) -> None:
 | 
			
		||||
    """
 | 
			
		||||
    Download a requests response content to a file by streaming it. This
 | 
			
		||||
    function avoids excessive memory usage when downloading large files. The
 | 
			
		||||
    chunk_size is in bytes.
 | 
			
		||||
 | 
			
		||||
    If progress_name is None, no progress bar will be shown. Otherwise a progress
 | 
			
		||||
    bar will appear, if the download is bigger than an internal threshold.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    with response:
 | 
			
		||||
        length = size_from_headers(response)
 | 
			
		||||
        if progress_name and length and int(length) > 1024 * 1024 * 10:  # 10 MiB
 | 
			
		||||
            settings: Optional[ProgressSettings] = ProgressSettings(progress_name, length)
 | 
			
		||||
        else:
 | 
			
		||||
            settings = None
 | 
			
		||||
 | 
			
		||||
        with open(target, 'wb') as file_descriptor:
 | 
			
		||||
            with progress_for(settings) as progress:
 | 
			
		||||
                for chunk in response.iter_content(chunk_size=chunk_size):
 | 
			
		||||
                    file_descriptor.write(chunk)
 | 
			
		||||
                    progress.advance(len(chunk))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def prompt_yes_no(question: str, default: Optional[bool] = None) -> bool:
 | 
			
		||||
    """
 | 
			
		||||
    Prompts the user a yes/no question and returns their choice.
 | 
			
		||||
    Asks the user a yes/no question and returns their choice.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    if default is True:
 | 
			
		||||
        prompt = "[Y/n]"
 | 
			
		||||
        query += " [Y/n] "
 | 
			
		||||
    elif default is False:
 | 
			
		||||
        prompt = "[y/N]"
 | 
			
		||||
        query += " [y/N] "
 | 
			
		||||
    else:
 | 
			
		||||
        prompt = "[y/n]"
 | 
			
		||||
 | 
			
		||||
    text = f"{question} {prompt} "
 | 
			
		||||
    wrong_reply = "Please reply with 'yes'/'y' or 'no'/'n'."
 | 
			
		||||
        query += " [y/n] "
 | 
			
		||||
 | 
			
		||||
    while True:
 | 
			
		||||
        response = input(text).strip().lower()
 | 
			
		||||
        if response in {"yes", "ye", "y"}:
 | 
			
		||||
        response = input(query).strip().lower()
 | 
			
		||||
        if response == "y":
 | 
			
		||||
            return True
 | 
			
		||||
        if response in {"no", "n"}:
 | 
			
		||||
        elif response == "n":
 | 
			
		||||
            return False
 | 
			
		||||
        if response == "" and default is not None:
 | 
			
		||||
        elif response == "" and default is not None:
 | 
			
		||||
            return default
 | 
			
		||||
        print(wrong_reply)
 | 
			
		||||
 | 
			
		||||
        print("Please answer with 'y' or 'n'.")
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user