# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/00_core.ipynb.

# %% auto 0
__all__ = ['get_source_code', 'file_extract', 'download_file']

# %% ../nbs/00_core.ipynb 3
import inspect

# %% ../nbs/00_core.ipynb 4
def get_source_code(obj:object, # The object whose source code you want to retrieve.
                    markdown=False, # Return the source code formatted as markdown
                    remove_documentation=False): # Remove docstrings and comments
    """
    Returns the source code of an object, with an optional markdown formatting.
    """
    # Get the source code of the object
    source = inspect.getsource(obj)
    
    # If the remove_documentation flag is set to True, remove docstrings and comments
    if remove_documentation:
        in_docstring = False
        lines = source.split('\n')
        source = ''
        # Remove docstrings
        for line in lines:
            if line.strip().startswith(('\'\'\'', '\"\"\"')):
                in_docstring = not in_docstring
            elif not in_docstring:
                source += line + '\n'
        # Remove comments
        source = '\n'.join([line for line in source.split('\n')
                            if not line.strip().startswith(('#'))])
        source = source.replace('\n\n', '\n')

    if markdown:
        # Format the source code as markdown code block
        source = f"```python\n{source}\n```"

        # Check if the code is running in Jupyter Notebook
        try:
            get_ipython
            from IPython.display import Markdown
            # Format the source code as an IPython Markdown object
            source = Markdown(source)
        except NameError:
            # If not in Jupyter Notebook, do nothing
            pass
    # Return the formatted source code
    return source

# %% ../nbs/00_core.ipynb 7
import zipfile
import tarfile
from pathlib import Path
import os

# %% ../nbs/00_core.ipynb 8
def file_extract(fname, # The path of the archive file
                 dest=None): # The path of the destination directory
    """
    Extract the contents of the given archive file to the destination directory.

    Raises:
        Exception: if the archive file format is not recognized (supported formats are gz and zip)
    """
    
    # If destination directory is not provided, use the parent directory of the archive file
    if dest is None: dest = Path(fname).parent
    
    fname = str(fname)
    
    # Extract the archive file based on its format
    if fname.endswith('gz'):
        tarfile.open(fname, 'r:gz').extractall(dest)
    elif fname.endswith('zip'):
        zipfile.ZipFile(fname).extractall(dest)
    else:
        # Raise an exception if the archive format is not recognized
        raise Exception(f'Unrecognized archive: {fname}')

# %% ../nbs/00_core.ipynb 13
import urllib.request
from tqdm.auto import tqdm

# %% ../nbs/00_core.ipynb 14
def download_file(url:str, # The URL of the file to download.
                  directory:str, # The directory where the file should be saved.
                  overwrite:bool=False # A flag to specify whether to overwrite the file if it already exists.
                 ):
    
    """
    Download a file from a given URL to a specified directory.

    This function sends a HTTP request to the URL provided, downloads the file and saves it to the specified 
    directory. If the directory does not exist, it creates it. If the file already exists and the overwrite
    flag is set to False, it skips the download process.

    The function also displays a progress bar during the download using the tqdm module, and checks if the
    download was successful based on the total file size. If the download is not successful, it prints an error message.
    """
    
    
    # Create the directory if it doesn't exist
    if not os.path.exists(directory):
        os.makedirs(directory)

    # Get file name from url to use when saving
    filename = os.path.join(directory, url.split("/")[-1])

    # Check if file exists and overwrite is not allowed
    if os.path.exists(filename) and not overwrite:
        print(f'The file {filename} already exists and overwrite is set to False.')
        return

    # Send a HTTP request to the URL of the file
    try:
        response = urllib.request.urlopen(url)
    except urllib.error.HTTPError as e:
        print(f'HTTP request to url: {url} failed with status code: {e.code}.')
        return

    # Check that the request was successful
    total_size_in_bytes= int(response.getheader('content-length', 0))
    block_size = 1024 #1 Kibibyte
    progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)

    with open(filename, 'wb') as file:
        while True:
            chunk = response.read(block_size)
            if not chunk:
                break
            file.write(chunk)
            progress_bar.update(len(chunk))
    progress_bar.close()

    if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:
        print("ERROR, something went wrong")
