Source code for franz.openrdf.rio.formats
################################################################################
# Copyright (c) 2006-2017 Franz Inc.
# All rights reserved. This program and the accompanying materials are
# made available under the terms of the MIT License which accompanies
# this distribution, and is available at http://opensource.org/licenses/MIT
################################################################################
from __future__ import unicode_literals
from builtins import object
from past.builtins import basestring
import os
# A metaclass that converts static dicts inside a Format to instances
from six import add_metaclass
[docs]class FormatMeta(type):
[docs] def __init__(cls, name, bases, dct):
super(FormatMeta, cls).__init__(name, bases, dct)
for attr, value in dct.items():
if attr.isupper() and isinstance(value, dict):
setattr(cls, attr, cls(**value))
[docs]@add_metaclass(FormatMeta)
class Format(object):
"""
Represents the concept of a data serialization format. Data formats are
identified by a {@link #getName() name} and can have one or more associated
MIME types, zero or more associated file extensions and can specify a
default character encoding.
This is a base class used by format subclasses for specific types of data,
such as triples and tuples
When a subclass of this class is declared all upper case static fields
that are dictionaries are converted to class instances. Data in the
dictionary is passed as arguments to the constructor.
"""
# A global dictionary mapping extensions to formats.
# Subclasses should override this.
_ext_map = {}
[docs] @classmethod
def register(cls, fmt):
""" Register a format object."""
for ext in fmt.file_extensions:
cls._ext_map['.' + ext.lower()] = fmt
[docs] @classmethod
def format_for_file_name(cls, filename):
"""
Try to guess appropriate RDF format from a file name.
Return a pair (format, compression) where format is
an RDF format or None (if no matching format was found)
and compression is a supported compression method
(currently either None or "gzip").
:param filename: File path.
:type filename: string
:return: Format (or ``None``) and compression type.
:rtype: (RDFFormat|None, string|None)
"""
compression = None
root, ext = os.path.splitext(filename)
if ext.lower() == ".gz":
compression = "gzip"
_, ext = os.path.splitext(root)
fmt = cls._ext_map.get(ext.lower())
return fmt, compression
[docs] @staticmethod
def mime_type_for_format(output_format):
"""
Get the preferred MIME type for a data format.
Raise an error if the format is `None`.
The format can be a string, in which case it is returned as-is.
:param output_format: the format to get the MIME type for.
:type output_format: franz.openrdf.rio.formats.Format|str
:return: A MIME type.
:rtype: string
"""
if output_format is None:
raise Exception('Unable to determine file format.')
if isinstance(output_format, basestring):
return output_format
return output_format.mime_types[0]
[docs] def __init__(self, name, mime_types=None, charset="UTF-8",
file_extensions=None, register=True):
"""
Initialize a new format object.
:param name: Human-readable name of the format.
:param mime_types: A list of MIME types used for this format.
The first element of this list will be used
as the content-type header during uploads.
:param charset: Character set used by the format.
:param file_extensions: List of file extensions for this format.
:param register: If True file extensions will be added to the map
used by :func:`Format.format_for_file_name`.
"""
self.name = name
self.mime_types = mime_types
self.charset = charset
self.file_extensions = file_extensions
if register:
self.register(self)
# This is used by Sphinx when rendering default values,
# so it should display something readable.
def __repr__(self):
cls = self.__class__
for name in dir(cls):
if getattr(cls, name) is self:
# We could use inspect.mro to find
# where the thing is really defined,
# but it's not worth the effort.
return '{cls}.{name}: {display_name}'.format(
cls=cls.__name__, name=name, display_name=self.name)
return '<Format: {name}>'.format(name=self.name)