# Path: kraken/lib/exceptions.py
# class KrakenRepoException(Exception):
# 
#     def __init__(self, message=None):
#         Exception.__init__(self, message)


from typing import Callable, Any
from contextlib import closing
from kraken.lib.exceptions import KrakenRepoException
import os
import json
import urllib
import pathlib
import logging
import requests
    nat_id = os.path.basename(urllib.parse.urlparse(model_url).path)
    spath = os.path.join(path, nat_id)
    logger.debug(f'downloading model file {model_url} to {spath}')
    with closing(requests.get(model_url, stream=True)) as r:
        file_size = int(r.headers['Content-length'])
        with open(spath, 'wb') as f:
            for chunk in r.iter_content(chunk_size=1024):
                callback(file_size, len(chunk))
                f.write(chunk)
    return nat_id


def get_description(model_id: str, callback: Callable[..., Any] = lambda: None) -> dict:
    """
    Fetches the metadata for a single model from the zenodo repository.

    Args:
        model_id (str): DOI of the model.
        callback (callable): Optional function called once per HTTP request.

    Returns:
        Dict
    """
    logger.info(f'Retrieving metadata for {model_id}')
    r = requests.get(f'{MODEL_REPO}records', params={'q': f'doi:"{model_id}"'})
    r.raise_for_status()
    callback()
    resp = r.json()
    if resp['hits']['total'] != 1:
        logger.error(f'Found {resp["hits"]["total"]} models when querying for id \'{model_id}\'')

# Path: kraken/lib/exceptions.py
# class KrakenRepoException(Exception):
# 
#     def __init__(self, message=None):
#         Exception.__init__(self, message)


# Path: kraken/repo.py
from typing import Callable, Any
from contextlib import closing
from kraken.lib.exceptions import KrakenRepoException
import os
import json
import urllib
import pathlib
import logging
import requests

    nat_id = os.path.basename(urllib.parse.urlparse(model_url).path)
    spath = os.path.join(path, nat_id)
    logger.debug(f'downloading model file {model_url} to {spath}')
    with closing(requests.get(model_url, stream=True)) as r:
        file_size = int(r.headers['Content-length'])
        with open(spath, 'wb') as f:
            for chunk in r.iter_content(chunk_size=1024):
                callback(file_size, len(chunk))
                f.write(chunk)
    return nat_id


def get_description(model_id: str, callback: Callable[..., Any] = lambda: None) -> dict:
    """
    Fetches the metadata for a single model from the zenodo repository.

    Args:
        model_id (str): DOI of the model.
        callback (callable): Optional function called once per HTTP request.

    Returns:
        Dict
    """
    logger.info(f'Retrieving metadata for {model_id}')
    r = requests.get(f'{MODEL_REPO}records', params={'q': f'doi:"{model_id}"'})
    r.raise_for_status()
    callback()
    resp = r.json()
    if resp['hits']['total'] != 1:
        logger.error(f'Found {resp["hits"]["total"]} models when querying for id \'{model_id}\'')

        raise KrakenRepoException(f'Found {resp["hits"]["total"]} models when querying for id \'{model_id}\'')