<commit_before>import json

from django.utils.translation import ugettext_lazy as _
from django.db.models.fields.files import FileField, FieldFile
from django.core.exceptions import ValidationError

from rest_framework import serializers


from bulbs.images.conf import settings
from bulbs.images.storages import BettyCropperStorage


class RemoteImageSerializer(serializers.WritableField):

    def to_native(self, obj):
        if obj.name is None or obj.name == "":
            return None
        return {
            'id': obj.id,
            'caption': obj.caption,
            'alt': obj.alt
        }

    def from_native(self, data):
        return json.dumps(data)


class RemoteImageFieldFile(FieldFile):
    def crop_url(self, width, ratio="original", format="jpg"):
        image_dir = ""
        for char in self.id:
            image_dir += char
            if len(image_dir) % 4 == 0:
                image_dir += "/"
        if image_dir.endswith("/"):
            image_dir = image_dir[:-1]
        return "%s/%s/%s/%s.%s" % (settings.BETTY_CROPPER['PUBLIC_URL'], image_dir, ratio, width, format)

    @property
    def id(self):
        try:
            data = json.loads(self.name)
            if isinstance(data, dict):
                return data.get('id')
        except (ValueError, TypeError):
            pass
        return self.name

    @id.setter
    def id(self, value):
        try:
            data = json.loads(self.name)
            if not isinstance(data, dict):
                data = {}<commit_msg>Yet another hole to plug<commit_after>import json

from django.utils.translation import ugettext_lazy as _
from django.db.models.fields.files import FileField, FieldFile
from django.core.exceptions import ValidationError

from rest_framework import serializers


from bulbs.images.conf import settings
from bulbs.images.storages import BettyCropperStorage


class RemoteImageSerializer(serializers.WritableField):

    def to_native(self, obj):
        if obj.name is None or obj.name == "":
            return None
        return {
            'id': obj.id,
            'caption': obj.caption,
            'alt': obj.alt
        }

    def from_native(self, data):
        if data:
            return json.dumps(data)
        return None


class RemoteImageFieldFile(FieldFile):
    def crop_url(self, width, ratio="original", format="jpg"):
        image_dir = ""
        for char in self.id:
            image_dir += char
            if len(image_dir) % 4 == 0:
                image_dir += "/"
        if image_dir.endswith("/"):
            image_dir = image_dir[:-1]
        return "%s/%s/%s/%s.%s" % (settings.BETTY_CROPPER['PUBLIC_URL'], image_dir, ratio, width, format)

    @property
    def id(self):
        try:
            data = json.loads(self.name)
            if isinstance(data, dict):
                return data.get('id')
        except (ValueError, TypeError):
            pass
        return self.name

    @id.setter
    def id(self, value):
        try:
            data = json.loads(self.name)
            if not isinstance(data, dict):
                data = {}
{'fraction_non_alphanumeric': 0.1059539052496799, 'fraction_numerical': 0.0019206145966709346, 'mean_word_length': 2.0788177339901477, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, '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': '5410890', 'n_tokens_mistral': 929, 'n_tokens_neox': 895, 'n_words': 232}