"""Resources This module contains a handler class for resources. """ import binascii import gzip import hashlib import mimetypes import os import re import StringIO import urlparse from config import config import encodings import regexes as r class FileExistError(Exception): """Exception which is raised when file does not exist""" pass class FileAccessError(Exception): """Exception which is raised when file exists, but cannot be accessed""" pass class Resource: """Class for representing a Resource (file)""" def __init__(self, uri): """Initialize the resource" Raises: FileExistError: if resource does not exist FileAccessError: if resource exists, but cannot be accessed Args: uri (str): Uniform Resource Identifier """ if uri == None: raise FileExistError self.uri = uri out = urlparse.urlparse(uri) self.path = os.path.join(config('root', default='content'), out.path.lstrip("/")) if not os.path.exists(self.path): raise FileExistError if os.path.isdir(self.path): self.path = os.path.join(self.path, config('index', default='index.html')) if not os.path.exists(self.path): raise FileAccessError if not os.path.isfile(self.path): raise FileExistError if not os.access(self.path, os.R_OK): raise FileAccessError def generate_etag(self): """Generate the ETag for the resource Returns: str: ETag for the resource """ stat = os.stat(self.path) m = hashlib.md5() m.update(str(stat)) etag = binascii.hexlify(m.digest()) return etag def etag_match(self, etag): if etag == None: return False my_etag = self.generate_etag() return etag == '*' or \ any([tag == my_etag for tag in re.split(r.ETagSplit, etag)]) def get_content(self, encoding=encodings.IDENTITY): """Get the contents of the resource Returns: str: Contents of the resource """ content = open(self.path).read() return encodings.encode(encoding, content) def get_content_type(self): """Get the content type, i.e "text/html" Returns: str: type of content in the resource """ mimetype = mimetypes.guess_type(self.path) return mimetype[0] def get_content_encoding(self): """Get the content encoding, i.e "gzip" Returns: str: encoding used for the resource """ mimetype = mimetypes.guess_type(self.path) return mimetype[1] def get_content_length(self): """Get the length of the resource Returns: int: length of resource in bytes """ return os.path.getsize(self.path)