<commit_before>from functools import wraps

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from PIL.ImageSequence import Iterator

__author__ = '<NAME>'
__copyright__ = 'Copyright (C) 2017 <NAME>'
__license__ = 'MIT'
__version__ = '1.1.0'


class Img:
    __MODES = {
        '1': 'black and white',
        'L': 'grayscale',
        'LA': 'grayscale with transparency',
        'P': 'color palette',
        'RGB': 'true color',
        'RGBA': 'true color with transparency',
        'RGBX': 'true color with padding',
        'RGBa': 'true color with premultiplied alpha',
        'CMYK': 'color separation',
        'YCbCr': 'color video',
        'LAB': 'l*a*b color space',
        'HSV': 'hue, saturation, value color space',
        'I': 'signed integer pixels',
        'F': 'floating point pixels'
    }
    __METHODS = ('convert', 'crop', 'filter', 'paste', 'resize', 'rotate',
                 'thumbnail', 'transform', 'transpose')

    __image = None
    __exif = None
    __frames = None

    @property
    def info(self):
        return self.__image.info

    @property
    def exif(self):
        if self.__exif is None:
            self.__exif = {}

            try:
                for key, value in self.__image._getexif().items():
                    tag = TAGS.get(key, key)
                    if tag == 'GPSInfo':
                        value = {GPSTAGS.get(key_, key_): value_
                                 for key_, value_ in value.items()}
                    self.__exif[tag] = value
            except AttributeError:
                pass

        return self.__exif

    @property
    def format(self):
        return self.__image.format

    @property
    def width(self):
        if not self.__frames:
            return self.__image.width

        return self.__frames[0].width

    @property
    def height(self):
        if not self.__frames:
            return self.__image.height

        return self.__frames[0].height

    @property
    def mode(self):
        if not self.__frames:
            return self.__image.mode

        return self.__frames[0].mode

    @property
    def mode_desc(self):
        return self.__MODES.get(self.mode)

    @property
    def n_frames(self):
        if self.__frames:
            return len(self.__frames)

        try:
            return self.__image.n_frames
        except AttributeError:
            return 1

    @property
    def animated(self):
        return self.n_frames > 1

    @property
    def frames(self):
        if self.__frames is None:
            self.__frames = [frame.copy() for frame in Iterator(self.__image)]

        return self.__frames

    def __init__(self, *, fp):
        self.__image = Image.open(fp)

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def __getattr__(self, name):
        if name not in self.__METHODS:
            raise AttributeError

        def proxy(*args, **kwargs):<commit_msg>limit frames<commit_after>import random

from PIL import Image
from PIL.ExifTags import TAGS, GPSTAGS
from PIL.ImageSequence import Iterator

__author__ = '<NAME>'
__copyright__ = 'Copyright (C) 2017 <NAME>'
__license__ = 'MIT'
__version__ = '1.1.0'


class Img:
    __MODES = {
        '1': 'black and white',
        'L': 'grayscale',
        'LA': 'grayscale with transparency',
        'P': 'color palette',
        'RGB': 'true color',
        'RGBA': 'true color with transparency',
        'RGBX': 'true color with padding',
        'RGBa': 'true color with premultiplied alpha',
        'CMYK': 'color separation',
        'YCbCr': 'color video',
        'LAB': 'l*a*b color space',
        'HSV': 'hue, saturation, value color space',
        'I': 'signed integer pixels',
        'F': 'floating point pixels'
    }
    __METHODS = ('convert', 'crop', 'filter', 'paste', 'resize', 'rotate',
                 'thumbnail', 'transform', 'transpose')

    __image = None
    __frame_limit = None
    __exif = None
    __frames = None

    @property
    def info(self):
        return self.__image.info

    @property
    def exif(self):
        if self.__exif is None:
            self.__exif = {}

            try:
                for key, value in self.__image._getexif().items():
                    tag = TAGS.get(key, key)
                    if tag == 'GPSInfo':
                        value = {GPSTAGS.get(key_, key_): value_
                                 for key_, value_ in value.items()}
                    self.__exif[tag] = value
            except AttributeError:
                pass

        return self.__exif

    @property
    def format(self):
        return self.__image.format

    @property
    def width(self):
        if not self.__frames:
            return self.__image.width

        return self.__frames[0].width

    @property
    def height(self):
        if not self.__frames:
            return self.__image.height

        return self.__frames[0].height

    @property
    def mode(self):
        if not self.__frames:
            return self.__image.mode

        return self.__frames[0].mode

    @property
    def mode_desc(self):
        return self.__MODES.get(self.mode)

    @property
    def n_frames(self):
        if self.__frames:
            return len(self.__frames)

        try:
            return self.__image.n_frames
        except AttributeError:
            return 1

    @property
    def animated(self):
        return self.n_frames > 1

    @property
    def frames(self):
        if self.__frames is None:
            indexes = list(range(self.n_frames))
            if self.__frame_limit:
                mix = indexes[1:]
                random.shuffle(mix)
                indexes[1:] = mix
                indexes = indexes[:self.__frame_limit]

            self.__frames = [
                frame.copy()
                for index, frame in enumerate(Iterator(self.__image))
                if index in set(indexes)]

        return self.__frames

    def __init__(self, *, fp, frame_limit=None):
        self.__image = Image.open(fp)
        self.__frame_limit = frame_limit

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.close()

    def __getattr__(self, name):
        if name not in self.__METHODS:
            raise AttributeError

        def proxy(*args, **kwargs):
{'fraction_non_alphanumeric': 0.10736148171401663, 'fraction_numerical': 0.004394914456129336, 'mean_word_length': 1.7971905179982441, 'pattern_counts': {'":': 0, '<': 7, '<?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': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6566129', 'n_tokens_mistral': 1901, 'n_tokens_neox': 1798, 'n_words': 509}