<commit_before>from sys import argv
from tempfile import mkstemp
import os
from cStringIO import StringIO

try:
    from PIL import Image
except ImportError:
    import Image
try:
    from PIL.ImageOps import grayscale
except ImportError:
    from ImageOps import grayscale

from faxcelerate import settings

def has_opened_file(func):
    """
    This is a class method decorator. It ensures that the "image" attribute
    exists in the called instance. If it does not, this decorator invokes
    the "tiffcp" command to uncompress the TIFF file and make it
    palatable to PIL.
    """
    def wrapper(self, *args, **kwargs):
        if self.image is None:
            try:
                (handle, self.tempname) = mkstemp(".tif")
                os.system("tiffcp -c none %s %s" %
                    (self.tiff_filename, self.tempname))
                self.image = Image.open(self.tempname, "r")
                os.close(handle)
            except IOError, e:
                #raise Exception("Original image not found: %s. Commid: %s, original: %s, tempname: %s" % (e, self.commid, self.tiff_filename, self.tempname))
                self.damaged = True
        return func(self, *args, **kwargs)
    return wrapper
        
class PageUtilities(object):
    def __init__(self, image):
        self.image = image
        
    def ratio(self):
        "Computes the aspect ratio for this image."
        try:
            dpi = self.image.info['dpi']
        except KeyError:
            dpi = (200, 100)
        i = self.image
        return i.size[1]*dpi[0]*1.0/i.size[0]/dpi[1]
        
    def newsize(self, *args, **kwargs):
        "Computes the new width and height for a scaled image."
        # 'i' is a shorthand
        i = self.image
        try:
            for k in args[0].keys():
                kwargs[k] = args[0][k]
        except IndexError:
            pass
        sizes = 0
        for possible_size in ('height', 'width'):
            if possible_size in kwargs:
                sizes += 1
        if sizes != 1:
            raise Exception, 'One, and only one, of width and height must' \
                ' be specified'
        # Compute ratio
        ratio = self.ratio()
        # Take the rotation into account, if any
        try:
            if kwargs['rotation'] in ('r', 'l'): ratio = 1/ratio
        except KeyError:
            pass
        if 'height' in kwargs:
            # Called with an absolute height
            h = kwargs['height']
            if h > i.size[1]:
                h = i.size[1]
            return (int(h/ratio), h)
        else:
            # Called with an absolute width
            w = kwargs['width']
            if w > i.size[0]:
                w = i.size[0]
            return (w, int(w*ratio))
        # Control will not get here
        assert(False)

class FaxImage(object):
    """
    This class deals with a fax message as a (single- or multi-page) image,
    and not with its metadata.
    """
    def __init__(self, fax):
        import faxcelerate.fax.models
        if isinstance(fax, faxcelerate.fax.models.Fax):
            self.commid = fax.comm_id
            self.total_pages = fax.pages
            self.rotation_defaults = fax.rotation
        else:
            self.commid = fax
            self.total_pages = None
        self.tiff_filename = settings.FAX_NAME_FORMAT % fax.filename
        self.statobj = os.stat(self.tiff_filename)
        self.tempname = None
        self.image = None
        self.damaged = False
        
    def __del__(self):
        "Delete any temporary file before decreasing refcount to 0."
        if self.image:
            del self.image
        if self.tempname is not None:
            os.remove(self.tempname)
        
    @has_opened_file
    def pages(self):
        "Generate each page in the file."
        count = 0
        if self.damaged:
            raise IndexError
        self.image.util = PageUtilities(self.image)
        try:
            while True:
                self.image.seek(count)
                self.image.page_index = count
                count += 1
                self.image.page_number = count
                yield self.image
        except EOFError, e:
            raise IndexError(e)
        
    def page_count(self):
        "Return the total number of pages. If it was not cached, compute it."
        if self.total_pages is not None:
            return self.total_pages
        try:
            p = self.pages()
            while True:
                lastpage = p.next()
        except IndexError:
            self.total_pages = lastpage.page_number
            return self.total_pages
        
    def cache_thumbnails(self):
        """
        Save a thumbnail for each page of this fax message. The size is
        hard-coded in the newsize() call.
        """
        p = self.pages()
        try:
            while True:
                i = p.next()
                ni = grayscale(i).resize(i.util.newsize(height=200), Image.ANTIALIAS)
                ni.save(settings.FAX_CACHE_NAME_FORMAT % (self.commid, 
                    i.page_number), "PNG")
                del ni
        except IndexError:
            pass
            
    def thumbnail_links(self, page=None):
        def full_width():
            try:
                from settings import FAX_WIDTH
                return FAX_WIDTH
            except ImportError:
                return 800
        def links_for_page(pagenum):
            return {
                'small': settings.FAX_CACHE_URL_FORMAT % (self.commid, pagenum),
                'big':  '/fax/png/%s/%s/?width=250' % (self.commid, pagenum),
                'full': '/fax/png/%s/%s/?width=%s&r=%s' % (self.commid, pagenum,
                    full_width(), self.rotation_defaults[pagenum]),
                'page': str(pagenum)
            }
        if page:
            return links_for_page(page)
        l = []
        pages= self.page_count()
        if pages > 0:
            for pagenum in range(1,pages+1):
                l.append(links_for_page(pagenum))
        return l
    
    DEGREES = {'n': 0, 'l': 90, 'r': 270, 'p': 180}
    
    def generate_png_stream(self, sizes, rotation=None, page_number=1,
        out_file=None):
        """
        Generate a PNG file for a given page.
        """
        # Skip pages before the desired one
        p = self.pages()
        while True:
            page = p.next()
            if page.page_number == page_number:
                break
        else:<commit_msg>Fix bug in reading FAX_WIDTH from settings<commit_after>from sys import argv
from tempfile import mkstemp
import os
from cStringIO import StringIO

try:
    from PIL import Image
except ImportError:
    import Image
try:
    from PIL.ImageOps import grayscale
except ImportError:
    from ImageOps import grayscale

from faxcelerate import settings

def has_opened_file(func):
    """
    This is a class method decorator. It ensures that the "image" attribute
    exists in the called instance. If it does not, this decorator invokes
    the "tiffcp" command to uncompress the TIFF file and make it
    palatable to PIL.
    """
    def wrapper(self, *args, **kwargs):
        if self.image is None:
            try:
                (handle, self.tempname) = mkstemp(".tif")
                os.system("tiffcp -c none %s %s" %
                    (self.tiff_filename, self.tempname))
                self.image = Image.open(self.tempname, "r")
                os.close(handle)
            except IOError, e:
                #raise Exception("Original image not found: %s. Commid: %s, original: %s, tempname: %s" % (e, self.commid, self.tiff_filename, self.tempname))
                self.damaged = True
        return func(self, *args, **kwargs)
    return wrapper
        
class PageUtilities(object):
    def __init__(self, image):
        self.image = image
        
    def ratio(self):
        "Computes the aspect ratio for this image."
        try:
            dpi = self.image.info['dpi']
        except KeyError:
            dpi = (200, 100)
        i = self.image
        return i.size[1]*dpi[0]*1.0/i.size[0]/dpi[1]
        
    def newsize(self, *args, **kwargs):
        "Computes the new width and height for a scaled image."
        # 'i' is a shorthand
        i = self.image
        try:
            for k in args[0].keys():
                kwargs[k] = args[0][k]
        except IndexError:
            pass
        sizes = 0
        for possible_size in ('height', 'width'):
            if possible_size in kwargs:
                sizes += 1
        if sizes != 1:
            raise Exception, 'One, and only one, of width and height must' \
                ' be specified'
        # Compute ratio
        ratio = self.ratio()
        # Take the rotation into account, if any
        try:
            if kwargs['rotation'] in ('r', 'l'): ratio = 1/ratio
        except KeyError:
            pass
        if 'height' in kwargs:
            # Called with an absolute height
            h = kwargs['height']
            if h > i.size[1]:
                h = i.size[1]
            return (int(h/ratio), h)
        else:
            # Called with an absolute width
            w = kwargs['width']
            if w > i.size[0]:
                w = i.size[0]
            return (w, int(w*ratio))
        # Control will not get here
        assert(False)

class FaxImage(object):
    """
    This class deals with a fax message as a (single- or multi-page) image,
    and not with its metadata.
    """
    def __init__(self, fax):
        import faxcelerate.fax.models
        if isinstance(fax, faxcelerate.fax.models.Fax):
            self.commid = fax.comm_id
            self.total_pages = fax.pages
            self.rotation_defaults = fax.rotation
        else:
            self.commid = fax
            self.total_pages = None
        self.tiff_filename = settings.FAX_NAME_FORMAT % fax.filename
        self.statobj = os.stat(self.tiff_filename)
        self.tempname = None
        self.image = None
        self.damaged = False
        
    def __del__(self):
        "Delete any temporary file before decreasing refcount to 0."
        if self.image:
            del self.image
        if self.tempname is not None:
            os.remove(self.tempname)
        
    @has_opened_file
    def pages(self):
        "Generate each page in the file."
        count = 0
        if self.damaged:
            raise IndexError
        self.image.util = PageUtilities(self.image)
        try:
            while True:
                self.image.seek(count)
                self.image.page_index = count
                count += 1
                self.image.page_number = count
                yield self.image
        except EOFError, e:
            raise IndexError(e)
        
    def page_count(self):
        "Return the total number of pages. If it was not cached, compute it."
        if self.total_pages is not None:
            return self.total_pages
        try:
            p = self.pages()
            while True:
                lastpage = p.next()
        except IndexError:
            self.total_pages = lastpage.page_number
            return self.total_pages
        
    def cache_thumbnails(self):
        """
        Save a thumbnail for each page of this fax message. The size is
        hard-coded in the newsize() call.
        """
        p = self.pages()
        try:
            while True:
                i = p.next()
                ni = grayscale(i).resize(i.util.newsize(height=200), Image.ANTIALIAS)
                ni.save(settings.FAX_CACHE_NAME_FORMAT % (self.commid, 
                    i.page_number), "PNG")
                del ni
        except IndexError:
            pass
            
    def thumbnail_links(self, page=None):
        def full_width():
            from django.conf import settings
            try:
                return settings.FAX_WIDTH
            except AttributeError:
                return 800

        def links_for_page(pagenum):
            return {
                'small': settings.FAX_CACHE_URL_FORMAT % (self.commid, pagenum),
                'big':  '/fax/png/%s/%s/?width=250' % (self.commid, pagenum),
                'full': '/fax/png/%s/%s/?width=%s&r=%s' % (self.commid, pagenum,
                    full_width(), self.rotation_defaults[pagenum]),
                'page': str(pagenum)
            }
        if page:
            return links_for_page(page)
        l = []
        pages= self.page_count()
        if pages > 0:
            for pagenum in range(1,pages+1):
                l.append(links_for_page(pagenum))
        return l
    
    DEGREES = {'n': 0, 'l': 90, 'r': 270, 'p': 180}
    
    def generate_png_stream(self, sizes, rotation=None, page_number=1,
        out_file=None):
        """
        Generate a PNG file for a given page.
        """
        # Skip pages before the desired one
        p = self.pages()
        while True:
            page = p.next()
            if page.page_number == page_number:
                break
        else:
{'fraction_non_alphanumeric': 0.09469175462750497, 'fraction_numerical': 0.007189842435367906, 'mean_word_length': 1.5577073552425664, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '322692', 'n_tokens_mistral': 3881, 'n_tokens_neox': 3698, 'n_words': 1103}