Exemple #1
0
 def _get_target(self):
     if self._target is None:
         asdffile = self._asdffile().read_external(self._uri)
         parts = urlparse.urlparse(self._uri)
         fragment = parts.fragment
         self._target = resolve_fragment(asdffile.tree, fragment)
     return self._target
Exemple #2
0
 def _get_target(self):
     if self._target is None:
         asdffile = self._asdffile().read_external(self._uri)
         parts = urlparse.urlparse(self._uri)
         fragment = parts.fragment
         self._target = resolve_fragment(asdffile.tree, fragment)
     return self._target
Exemple #3
0
    def get_source(self, block):
        """
        Get a source identifier for a given block.

        Parameters
        ----------
        block : Block

        Returns
        -------
        source_id : str
            May be an integer for an internal block, or a URI for an
            external block.
        """
        for i, internal_block in enumerate(self.internal_blocks):
            if block == internal_block:
                if internal_block.array_storage == 'streamed':
                    return -1
                return i

        for i, external_block in enumerate(self.external_blocks):
            if block == external_block:
                if self._asdffile().uri is None:
                    raise ValueError(
                        "Can't write external blocks, since URI of main file is "
                        "unknown.")

                parts = list(urlparse.urlparse(self._asdffile().uri))
                path = parts[2]
                filename = os.path.basename(path)
                return self.get_external_filename(filename, i)

        raise ValueError("block not found.")
Exemple #4
0
    def get_source(self, block):
        """
        Get a source identifier for a given block.

        Parameters
        ----------
        block : Block

        Returns
        -------
        source_id : str
            May be an integer for an internal block, or a URI for an
            external block.
        """
        for i, internal_block in enumerate(self.internal_blocks):
            if block == internal_block:
                if internal_block.array_storage == 'streamed':
                    return -1
                return i

        for i, external_block in enumerate(self.external_blocks):
            if block == external_block:
                if self._asdffile().uri is None:
                    raise ValueError(
                        "Can't write external blocks, since URI of main file is "
                        "unknown.")

                parts = list(urlparse.urlparse(self._asdffile().uri))
                path = parts[2]
                filename = os.path.basename(path)
                return self.get_external_filename(filename, i)

        raise ValueError("block not found.")
Exemple #5
0
 def _get_target(self, do_not_fill_defaults=False):
     if self._target is None:
         asdffile = self._asdffile().read_external(
             self._uri, do_not_fill_defaults=do_not_fill_defaults)
         parts = urlparse.urlparse(self._uri)
         fragment = parts.fragment
         self._target = resolve_fragment(asdffile.tree, fragment)
     return self._target
Exemple #6
0
def relative_uri(source, target):
    """
    Make a relative URI from source to target.
    """
    su = urlparse.urlparse(source)
    tu = urlparse.urlparse(target)
    extra = list(tu[3:])
    relative = None
    if tu[0] == '' and tu[1] == '':
        if tu[2] == su[2]:
            relative = ''
        elif not tu[2].startswith('/'):
            relative = tu[2]
    elif su[0:2] != tu[0:2]:
        return target

    if relative is None:
        relative = os.path.relpath(tu[2], os.path.dirname(su[2]))
    if relative == '.':
        relative = ''
    relative = urlparse.urlunparse(["", "", relative] + extra)
    return relative
Exemple #7
0
def resolve_uri(base, uri):
    """
    Resolve a URI against a base URI.
    """
    if base is None:
        if uri == '':
            return ''
        parsed = urlparse.urlparse(uri)
        if parsed.path.startswith('/'):
            return uri
        raise ValueError(
            "Can not resolve relative URLs since the base is unknown.")
    return urlparse.urljoin(base, uri)
Exemple #8
0
def relative_uri(source, target):
    """
    Make a relative URI from source to target.
    """
    su = urlparse.urlparse(source)
    tu = urlparse.urlparse(target)
    extra = list(tu[3:])
    relative = None
    if tu[0] == '' and tu[1] == '':
        if tu[2] == su[2]:
            relative = ''
        elif not tu[2].startswith('/'):
            relative = tu[2]
    elif su[0:2] != tu[0:2]:
        return target

    if relative is None:
        relative = os.path.relpath(tu[2], su[2])
    if relative == '.':
        relative = ''
    relative = urlparse.urlunparse(["", "", relative] + extra)
    return relative
Exemple #9
0
def resolve_uri(base, uri):
    """
    Resolve a URI against a base URI.
    """
    if base is None:
        if uri == '':
            return ''
        parsed = urlparse.urlparse(uri)
        if parsed.path.startswith('/'):
            return uri
        raise ValueError(
            "Can not resolve relative URLs since the base is unknown.")
    return urlparse.urljoin(base, uri)
Exemple #10
0
 def get_external_uri(self, uri, index):
     """
     Given a main URI and an index number, return a new URI for
     saving an external block.
     """
     if uri is None:
         uri = ''
     parts = list(urlparse.urlparse(uri))
     path = parts[2]
     dirname, filename = os.path.split(path)
     filename = self.get_external_filename(filename, index)
     path = os.path.join(dirname, filename)
     parts[2] = path
     return urlparse.urlunparse(parts)
Exemple #11
0
 def get_external_uri(self, uri, index):
     """
     Given a main URI and an index number, return a new URI for
     saving an external block.
     """
     if uri is None:
         uri = ''
     parts = list(urlparse.urlparse(uri))
     path = parts[2]
     dirname, filename = os.path.split(path)
     filename = self.get_external_filename(filename, index)
     path = os.path.join(dirname, filename)
     parts[2] = path
     return urlparse.urlunparse(parts)
Exemple #12
0
def _make_http_connection(init, mode, uri=None):
    """
    Creates a HTTPConnection instance if the HTTP server supports
    Range requests, otherwise falls back to a generic InputStream.
    """
    from astropy.extern.six.moves import http_client

    parsed = urlparse.urlparse(init)
    connection = http_client.HTTPConnection(parsed.netloc)
    connection.connect()

    # We request a range of everything ("0-") just to check if the
    # server understands that header entry.
    headers = {'Range': 'bytes=0-'}
    connection.request('GET', parsed.path, headers=headers)
    response = connection.getresponse()
    if response.status // 100 != 2:
        raise IOError("HTTP failed: {0} {1}".format(
            response.status, response.reason))

    # Status 206 means a range was returned.  If it's anything else
    # that indicates the server probably doesn't support Range
    # headers.
    if (response.status != 206 or
        response.getheader('accept-ranges', None) != 'bytes' or
        response.getheader('content-range', None) is None or
        response.getheader('content-length', None) is None):
        # Fall back to a regular input stream, but we don't
        # need to open a new connection.
        response.close = connection.close
        return InputStream(response, mode, uri=uri or init, close=True)

    # Since we'll be requesting chunks, we can't read at all with the
    # current request (because we can't abort it), so just close and
    # start over
    size = int(response.getheader('content-length'))
    connection.close()
    connection.connect()
    return HTTPConnection(connection, size, parsed.path, uri or init)
Exemple #13
0
def _make_http_connection(init, mode, uri=None):
    """
    Creates a HTTPConnection instance if the HTTP server supports
    Range requests, otherwise falls back to a generic InputStream.
    """
    from astropy.extern.six.moves import http_client

    parsed = urlparse.urlparse(init)
    connection = http_client.HTTPConnection(parsed.netloc)
    connection.connect()

    # We request a range of everything ("0-") just to check if the
    # server understands that header entry.
    headers = {'Range': 'bytes=0-'}
    connection.request('GET', parsed.path, headers=headers)
    response = connection.getresponse()
    if response.status // 100 != 2:
        raise IOError("HTTP failed: {0} {1}".format(
            response.status, response.reason))

    # Status 206 means a range was returned.  If it's anything else
    # that indicates the server probably doesn't support Range
    # headers.
    if (response.status != 206 or
        response.getheader('accept-ranges', None) != 'bytes' or
        response.getheader('content-range', None) is None or
        response.getheader('content-length', None) is None):
        # Fall back to a regular input stream, but we don't
        # need to open a new connection.
        response.close = connection.close
        return InputStream(response, mode, uri=uri or init, close=True)

    # Since we'll be requesting chunks, we can't read at all with the
    # current request (because we can't abort it), so just close and
    # start over
    size = int(response.getheader('content-length'))
    connection.close()
    connection.connect()
    return HTTPConnection(connection, size, parsed.path, uri or init)
Exemple #14
0
def list_name_is_url(name):
    may_be_url = urlparse.urlparse(name)
    return (may_be_url.scheme and may_be_url.netloc)
Exemple #15
0
def get_base_uri(uri):
    """
    For a given URI, return the part without any fragment.
    """
    parts = urlparse.urlparse(uri)
    return urlparse.urlunparse(list(parts[:5]) + [''])
Exemple #16
0
def list_name_is_url(name):
    may_be_url = urlparse.urlparse(name)
    return (may_be_url.scheme and may_be_url.netloc)
Exemple #17
0
def get_file(init, mode='r', uri=None):
    """
    Returns a `GenericFile` instance suitable for wrapping the given
    object `init`.

    If passed an already open file-like object, it must be opened for
    reading/writing in binary mode.  It is the caller's responsibility
    to close it.

    Parameters
    ----------
    init : object
        `init` may be:

        - A `bytes` or `unicode` file path or ``file:`` or ``http:``
          url.

        - A Python 2 `file` object.

        - An `io.IOBase` object (the default file object on Python 3).

        - A ducktyped object that looks like a file object.  If `mode`
          is ``"r"``, it must have a ``read`` method.  If `mode` is
          ``"w"``, it must have a ``write`` method.  If `mode` is
          ``"rw"`` it must have the ``read``, ``write``, ``tell`` and
          ``seek`` methods.

        - A `GenericFile` instance, in which case it is wrapped in a
          `GenericWrapper` instance, so that the file is closed when
          only when the final layer is unwrapped.

    mode : str
        Must be one of ``"r"``, ``"w"`` or ``"rw"``.

    uri : str
        Sets the base URI of the file object.  This will be used to
        resolve any relative URIs contained in the file.  This is
        redundant if `init` is a `bytes` or `unicode` object (since it
        will be the uri), and it may be determined automatically if
        `init` refers to a regular filesystem file.  It is not required
        if URI resolution is not used in the file.

    Returns
    -------
    fd : GenericFile

    Raises
    ------
    ValueError, TypeError, IOError
    """
    if mode not in ('r', 'w', 'rw'):
        raise ValueError("mode must be 'r', 'w' or 'rw'")

    # Special case for sys.stdout on Python 3, since it takes unicode
    # by default, but we need to write to it with bytes
    if six.PY3 and init in (sys.stdout, sys.stdin, sys.stderr):
        init = init.buffer

    if isinstance(init, (GenericFile, GenericWrapper)):
        if mode not in init.mode:
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))
        return GenericWrapper(init, uri=uri)

    elif isinstance(init, six.string_types):
        parsed = urlparse.urlparse(init)
        if parsed.scheme == 'http':
            if mode == 'w':
                raise ValueError(
                    "HTTP connections can not be opened for writing")
            return _make_http_connection(init, mode, uri=uri)
        elif parsed.scheme in ('', 'file'):
            if mode == 'rw':
                realmode = 'r+b'
            else:
                realmode = mode + 'b'
            return RealFile(
                open(parsed.path, realmode), mode, close=True,
                uri=uri or parsed.path)

    elif isinstance(init, io.BytesIO):
        return MemoryIO(init, mode, uri=uri)

    elif isinstance(init, io.StringIO):
        raise TypeError(
            "io.StringIO objects are not supported.  Use io.BytesIO instead.")

    elif six.PY2 and isinstance(init, file):
        if not mode in init.mode:
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))

        try:
            init.tell()
        except IOError:
            if mode == 'w':
                return OutputStream(init, uri=uri)
            elif mode == 'r':
                return InputStream(init, mode, uri=uri)
            else:
                raise ValueError(
                    "File '{0}' could not be opened in 'rw' mode".format(init))
        else:
            return RealFile(init, mode, uri=uri)

    elif isinstance(init, io.IOBase):
        if sys.version_info[:2] == (2, 6):
            raise ValueError("io.open file objects are not supported on Python 2.6")

        if (('r' in mode and not init.readable()) or
            ('w' in mode and not init.writable())):
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))

        if init.seekable():
            if isinstance(init, (io.BufferedReader,
                                 io.BufferedWriter,
                                 io.BufferedRandom)):
                init2 = init.raw
            else:
                init2 = init
            if isinstance(init2, io.RawIOBase):
                result = RealFile(init2, mode, uri=uri)
            else:
                result = MemoryIO(init2, mode, uri=uri)
            result._secondary_fd = init
            return result
        else:
            if mode == 'w':
                return OutputStream(init, uri=uri)
            elif mode == 'r':
                return InputStream(init, mode, uri=uri)
            else:
                raise ValueError(
                    "File '{0}' could not be opened in 'rw' mode".format(init))

    elif 'w' in mode and (
          hasattr(init, 'write') and
          hasattr(init, 'seek') and
          hasattr(init, 'tell')):
        return MemoryIO(init, mode, uri=uri)

    elif 'r' in mode and (
          hasattr(init, 'read') and
          hasattr(init, 'seek') and
          hasattr(init, 'tell')):
        return MemoryIO(init, mode, uri=uri)

    elif 'w' in mode and hasattr(init, 'write'):
        return OutputStream(init, uri=uri)

    elif 'r' in mode and hasattr(init, 'read'):
        return InputStream(init, mode, uri=uri)

    raise ValueError("Can't handle '{0}' as a file for mode '{1}'".format(
        init, mode))
Exemple #18
0
def get_base_uri(uri):
    """
    For a given URI, return the part without any fragment.
    """
    parts = urlparse.urlparse(uri)
    return urlparse.urlunparse(list(parts[:5]) + [''])
Exemple #19
0
def get_file(init, mode='r', uri=None):
    """
    Returns a `GenericFile` instance suitable for wrapping the given
    object `init`.

    If passed an already open file-like object, it must be opened for
    reading/writing in binary mode.  It is the caller's responsibility
    to close it.

    Parameters
    ----------
    init : object
        `init` may be:

        - A `bytes` or `unicode` file path or ``file:`` or ``http:``
          url.

        - A Python 2 `file` object.

        - An `io.IOBase` object (the default file object on Python 3).

        - A ducktyped object that looks like a file object.  If `mode`
          is ``"r"``, it must have a ``read`` method.  If `mode` is
          ``"w"``, it must have a ``write`` method.  If `mode` is
          ``"rw"`` it must have the ``read``, ``write``, ``tell`` and
          ``seek`` methods.

        - A `GenericFile` instance, in which case it is wrapped in a
          `GenericWrapper` instance, so that the file is closed when
          only when the final layer is unwrapped.

    mode : str
        Must be one of ``"r"``, ``"w"`` or ``"rw"``.

    uri : str
        Sets the base URI of the file object.  This will be used to
        resolve any relative URIs contained in the file.  This is
        redundant if `init` is a `bytes` or `unicode` object (since it
        will be the uri), and it may be determined automatically if
        `init` refers to a regular filesystem file.  It is not required
        if URI resolution is not used in the file.

    Returns
    -------
    fd : GenericFile

    Raises
    ------
    ValueError, TypeError, IOError
    """
    if mode not in ('r', 'w', 'rw'):
        raise ValueError("mode must be 'r', 'w' or 'rw'")

    # Special case for sys.stdout on Python 3, since it takes unicode
    # by default, but we need to write to it with bytes
    if six.PY3 and init in (sys.stdout, sys.stdin, sys.stderr):
        init = init.buffer

    if isinstance(init, (GenericFile, GenericWrapper)):
        if mode not in init.mode:
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))
        return GenericWrapper(init, uri=uri)

    elif isinstance(init, six.string_types):
        parsed = urlparse.urlparse(init)
        if parsed.scheme == 'http':
            if mode == 'w':
                raise ValueError(
                    "HTTP connections can not be opened for writing")
            return _make_http_connection(init, mode, uri=uri)
        elif parsed.scheme in _local_file_schemes:
            if mode == 'rw':
                realmode = 'r+b'
            else:
                realmode = mode + 'b'
            realpath = url2pathname(parsed.path)
            return RealFile(
                open(realpath, realmode), mode, close=True,
                uri=uri)

    elif isinstance(init, io.BytesIO):
        return MemoryIO(init, mode, uri=uri)

    elif isinstance(init, io.StringIO):
        raise TypeError(
            "io.StringIO objects are not supported.  Use io.BytesIO instead.")

    elif six.PY2 and isinstance(init, file):
        if not mode in init.mode:
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))

        try:
            init.tell()
        except IOError:
            if mode == 'w':
                return OutputStream(init, uri=uri)
            elif mode == 'r':
                return InputStream(init, mode, uri=uri)
            else:
                raise ValueError(
                    "File '{0}' could not be opened in 'rw' mode".format(init))
        else:
            return RealFile(init, mode, uri=uri)

    elif isinstance(init, io.IOBase):
        if sys.version_info[:2] == (2, 6):
            raise ValueError("io.open file objects are not supported on Python 2.6")

        if (('r' in mode and not init.readable()) or
            ('w' in mode and not init.writable())):
            raise ValueError(
                "File is opened as '{0}', but '{1}' was requested".format(
                    init.mode, mode))

        if init.seekable():
            if isinstance(init, (io.BufferedReader,
                                 io.BufferedWriter,
                                 io.BufferedRandom)):
                init2 = init.raw
            else:
                init2 = init
            if isinstance(init2, io.RawIOBase):
                result = RealFile(init2, mode, uri=uri)
            else:
                result = MemoryIO(init2, mode, uri=uri)
            result._secondary_fd = init
            return result
        else:
            if mode == 'w':
                return OutputStream(init, uri=uri)
            elif mode == 'r':
                return InputStream(init, mode, uri=uri)
            else:
                raise ValueError(
                    "File '{0}' could not be opened in 'rw' mode".format(init))

    elif 'w' in mode and (
          hasattr(init, 'write') and
          hasattr(init, 'seek') and
          hasattr(init, 'tell')):
        return MemoryIO(init, mode, uri=uri)

    elif 'r' in mode and (
          hasattr(init, 'read') and
          hasattr(init, 'seek') and
          hasattr(init, 'tell')):
        return MemoryIO(init, mode, uri=uri)

    elif 'w' in mode and hasattr(init, 'write'):
        return OutputStream(init, uri=uri)

    elif 'r' in mode and hasattr(init, 'read'):
        return InputStream(init, mode, uri=uri)

    raise ValueError("Can't handle '{0}' as a file for mode '{1}'".format(
        init, mode))