# Path: src/astrodynamics/utils/helper.py
# def format_size(value, binary=False, gnu=False, format='%.1f'):
#     """Format a number of bytes like a human readable file size (e.g. 10 kB). By
#     default, decimal suffixes (kB, MB) are used.  Passing binary=true will use
#     binary suffixes (KiB, MiB) are used and the base will be 2**10 instead of
#     10**3.  If ``gnu`` is True, the binary argument is ignored and GNU-style
#     (ls -sh style) prefixes are used (K, M) with the 2**10 definition.
#     Non-gnu modes are compatible with jinja2's ``filesizeformat`` filter.
# 
#     Copyright (c) 2010 Jason Moiron and Contributors.
#     """
#     if gnu:
#         suffix = _size_suffixes['gnu']
#     elif binary:
#         suffix = _size_suffixes['binary']
#     else:
#         suffix = _size_suffixes['decimal']
# 
#     base = 1024 if (gnu or binary) else 1000
#     bytes = float(value)
# 
#     if bytes == 1 and not gnu:
#         return '1 Byte'
#     elif bytes < base and not gnu:
#         return '%d Bytes' % bytes
#     elif bytes < base and gnu:
#         return '%dB' % bytes
# 
#     for i, s in enumerate(suffix):
#         unit = base ** (i + 2)
#         if bytes < unit and not gnu:
#             return (format + ' %s') % ((base * bytes / unit), s)
#         elif bytes < unit and gnu:
#             return (format + '%s') % ((base * bytes / unit), s)
#     if gnu:
#         return (format + '%s') % ((base * bytes / unit), s)
#     return (format + ' %s') % ((base * bytes / unit), s)
# 
# def prefix(prefix, iterable):
#     """Prepend items from `iterable` with `prefix` string."""
#     for x in iterable:
#         yield '{prefix}{x}'.format(prefix=prefix, x=x)
# 
# @contextmanager
# def suppress_file_exists_error():
#     """Compatibility function for catching FileExistsError on Python 2"""
#     if PY33:
#         with suppress(FileExistsError):  # noqa
#             yield
#     else:
#         try:
#             yield
#         except OSError as e:
#             if e.errno != errno.EEXIST:
#                 raise
# 
# Path: src/astrodynamics/utils/progress.py
# class DownloadProgressBar(WindowsMixin, InterruptibleMixin,
#                           DownloadProgressMixin, _BaseBar):
# 
#     file = sys.stdout
#     message = "%(percent)d%%"
#     suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s"
# 
# class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin,
#                               DownloadProgressMixin, WritelnMixin, Spinner):
# 
#     file = sys.stdout
#     suffix = "%(downloaded)s %(download_speed)s"
# 
#     def next_phase(self):
#         if not hasattr(self, "_phaser"):
#             self._phaser = itertools.cycle(self.phases)
#         return next(self._phaser)
# 
#     def update(self):
#         message = self.message % self
#         phase = self.next_phase()
#         suffix = self.suffix % self
#         line = ''.join([
#             message,
#             " " if message else "",
#             phase,
#             " " if suffix else "",
#             suffix,
#         ])
# 
#         self.writeln(line)


from pathlib import Path
from appdirs import AppDirs
from requests import HTTPError
from six.moves.urllib.parse import quote
from .helper import format_size, prefix, suppress_file_exists_error
from .progress import DownloadProgressBar, DownloadProgressSpinner
import requests
            download_file_with_progress(url, str(filepath))
        except HTTPError as exc:
            if exc.response.status_code != 404:
                raise
        else:
            print('Kernel downloaded to', filepath)
            downloaded = True
            break

    if not downloaded:
        s = 'Kernel not found in the following locations:\n{}'
        raise KernelNotFoundError(s.format('\n'.join(prefix('  ', urls))))


def download_file_with_progress(url, filepath):
    """Download URL to file with progress bar or spinner printed to stderr.

    Parameters:
        url (str): URL to download.
        filepath (str): File path URL will be saved to.
    """
    resp = requests.get(url, stream=True)
    resp.raise_for_status()

    try:
        total_length = int(resp.headers['content-length'])
    except (ValueError, KeyError, TypeError):
        total_length = 0

    if total_length:

# Path: src/astrodynamics/utils/helper.py
# def format_size(value, binary=False, gnu=False, format='%.1f'):
#     """Format a number of bytes like a human readable file size (e.g. 10 kB). By
#     default, decimal suffixes (kB, MB) are used.  Passing binary=true will use
#     binary suffixes (KiB, MiB) are used and the base will be 2**10 instead of
#     10**3.  If ``gnu`` is True, the binary argument is ignored and GNU-style
#     (ls -sh style) prefixes are used (K, M) with the 2**10 definition.
#     Non-gnu modes are compatible with jinja2's ``filesizeformat`` filter.
# 
#     Copyright (c) 2010 Jason Moiron and Contributors.
#     """
#     if gnu:
#         suffix = _size_suffixes['gnu']
#     elif binary:
#         suffix = _size_suffixes['binary']
#     else:
#         suffix = _size_suffixes['decimal']
# 
#     base = 1024 if (gnu or binary) else 1000
#     bytes = float(value)
# 
#     if bytes == 1 and not gnu:
#         return '1 Byte'
#     elif bytes < base and not gnu:
#         return '%d Bytes' % bytes
#     elif bytes < base and gnu:
#         return '%dB' % bytes
# 
#     for i, s in enumerate(suffix):
#         unit = base ** (i + 2)
#         if bytes < unit and not gnu:
#             return (format + ' %s') % ((base * bytes / unit), s)
#         elif bytes < unit and gnu:
#             return (format + '%s') % ((base * bytes / unit), s)
#     if gnu:
#         return (format + '%s') % ((base * bytes / unit), s)
#     return (format + ' %s') % ((base * bytes / unit), s)
# 
# def prefix(prefix, iterable):
#     """Prepend items from `iterable` with `prefix` string."""
#     for x in iterable:
#         yield '{prefix}{x}'.format(prefix=prefix, x=x)
# 
# @contextmanager
# def suppress_file_exists_error():
#     """Compatibility function for catching FileExistsError on Python 2"""
#     if PY33:
#         with suppress(FileExistsError):  # noqa
#             yield
#     else:
#         try:
#             yield
#         except OSError as e:
#             if e.errno != errno.EEXIST:
#                 raise
# 
# Path: src/astrodynamics/utils/progress.py
# class DownloadProgressBar(WindowsMixin, InterruptibleMixin,
#                           DownloadProgressMixin, _BaseBar):
# 
#     file = sys.stdout
#     message = "%(percent)d%%"
#     suffix = "%(downloaded)s %(download_speed)s %(pretty_eta)s"
# 
# class DownloadProgressSpinner(WindowsMixin, InterruptibleMixin,
#                               DownloadProgressMixin, WritelnMixin, Spinner):
# 
#     file = sys.stdout
#     suffix = "%(downloaded)s %(download_speed)s"
# 
#     def next_phase(self):
#         if not hasattr(self, "_phaser"):
#             self._phaser = itertools.cycle(self.phases)
#         return next(self._phaser)
# 
#     def update(self):
#         message = self.message % self
#         phase = self.next_phase()
#         suffix = self.suffix % self
#         line = ''.join([
#             message,
#             " " if message else "",
#             phase,
#             " " if suffix else "",
#             suffix,
#         ])
# 
#         self.writeln(line)


# Path: src/astrodynamics/utils/web.py
from pathlib import Path
from appdirs import AppDirs
from requests import HTTPError
from six.moves.urllib.parse import quote
from .helper import format_size, prefix, suppress_file_exists_error
from .progress import DownloadProgressBar, DownloadProgressSpinner
import requests

            download_file_with_progress(url, str(filepath))
        except HTTPError as exc:
            if exc.response.status_code != 404:
                raise
        else:
            print('Kernel downloaded to', filepath)
            downloaded = True
            break

    if not downloaded:
        s = 'Kernel not found in the following locations:\n{}'
        raise KernelNotFoundError(s.format('\n'.join(prefix('  ', urls))))


def download_file_with_progress(url, filepath):
    """Download URL to file with progress bar or spinner printed to stderr.

    Parameters:
        url (str): URL to download.
        filepath (str): File path URL will be saved to.
    """
    resp = requests.get(url, stream=True)
    resp.raise_for_status()

    try:
        total_length = int(resp.headers['content-length'])
    except (ValueError, KeyError, TypeError):
        total_length = 0

    if total_length:

        print('Downloading {} ({})'.format(url, format_size(total_length)))