<commit_before>import requests
from .util import *
import json

API_ENDPOINT = "https://api.pipedrive.com/v1"


class BaseResource(object):
    RESOURCE = "resources"
    RESOURCE_SEGMENT = RESOURCE + "s"
    FIELD_SEGMENT = RESOURCE + "Fields"
    HAS_CUSTOM_FIELDS = False

    def __init__(self, client, id, preload=None):
        """
        client: pipedrive client instance
        id: pipedrive resource id
        preload: set of fields to load at __init__ //TODO: use parameter
        """
        self._client = client
        self._resource = self.RESOURCE
        self.id = id
        self._data_cache = {}
        self.url = None
        self._fields = None
        self._dirty_fields = set()

        if self._resource not in self._client.fields:
            self._client.load_fields_for_resource(self._resource)

        if preload is not None:
            self._data_cache = preload

        self._init_done = True

    def __getattr__(self, name):

        attr = self._name_to_attr(name)

        if name in self.field_names and attr not in self._data:
            self._data_cache.clear()

        if attr in self._data:
            value = self._data[attr]
            ftype = self.field_config[attr]["type"]
            if ftype in self._client.FIELD_TO_CLASS:
                # if type is mappable, map it
                resource_class = self._client.FIELD_TO_CLASS[ftype]
                rid = value["value"]
                res = resource_class(self._client, rid)
                return res
            else:
                return value
        else:
            raise AttributeError

    def __setattr__(self, name, value):
        # print("Setting %s to %s" % (name, value))
        if "_init_done" not in self.__dict__ or name in self.__dict__:
            # use default setattr
            object.__setattr__(self, name, value)
        elif name in self.field_names:
            # custom field, let's set it
            attr = self._name_to_attr(name)
            # Set value only if value has actually changed
            if not str(self._data[attr]) == str(value):
                self._data_cache[attr] = value
                self._dirty_fields.add(name)
        else:
            raise AttributeError("Can't set propery: attribute %s \
                                          not found." % (name))

    def _name_to_attr(self, name):
        "Convert property name in pipedrive's object internal key."
        if self.HAS_CUSTOM_FIELDS and name in self.field_names:
            attr = self.field_names[name]
        else:
            attr = name
        return attr
        # Check if test on HAS_CUSTOM_FIELDS is required

    def save(self):
        "Save data back to pipedrive"
        if not self._dirty_fields:
            debug("No dirty fields for object %s" % self.id)
            return
        debug("Saving dirty fields: %s" % self._dirty_fields)
        data_for_update = {}
        for f in self._dirty_fields:
            attr = self._name_to_attr(f)
            data_for_update[attr] = self._data[attr]
        self._client.update_resource(self.RESOURCE_SEGMENT, self.id,
                                     data_for_update)
        self._dirty_fields.clear()
        self._data.clear()

    @property
    def _data(self):
        if not self._data_cache:
            (r, data) = self._client._fetch_resource_by_id(
                self.RESOURCE_SEGMENT, self.id)
            self.url = r.url
            self._data_cache = data

        return self._data_cache

    @property
    def field_keys(self):
        if not self.HAS_CUSTOM_FIELDS:
            return []
        return self._client.fields[self._resource]["key_to_attr"]

    @property
    def field_names(self):
        if not self.HAS_CUSTOM_FIELDS:
            return []
        return self._client.fields[self._resource]["attr_to_key"]<commit_msg>add active method and check that resource is active before saving<commit_after>import requests
from .util import *
import json

API_ENDPOINT = "https://api.pipedrive.com/v1"


class BaseResource(object):
    RESOURCE = "resources"
    RESOURCE_SEGMENT = RESOURCE + "s"
    FIELD_SEGMENT = RESOURCE + "Fields"
    HAS_CUSTOM_FIELDS = False

    def __init__(self, client, id, preload=None):
        """
        client: pipedrive client instance
        id: pipedrive resource id
        preload: set of fields to load at __init__ //TODO: use parameter
        """
        self._client = client
        self._resource = self.RESOURCE
        self.id = id
        self._data_cache = {}
        self.url = None
        self._fields = None
        self._dirty_fields = set()

        if self._resource not in self._client.fields:
            self._client.load_fields_for_resource(self._resource)

        if preload is not None:
            self._data_cache = preload

        self._init_done = True

    def __getattr__(self, name):

        attr = self._name_to_attr(name)

        if name in self.field_names and attr not in self._data:
            self._data_cache.clear()

        if attr in self._data:
            value = self._data[attr]
            ftype = self.field_config[attr]["type"]
            if ftype in self._client.FIELD_TO_CLASS:
                # if type is mappable, map it
                resource_class = self._client.FIELD_TO_CLASS[ftype]
                rid = value["value"]
                res = resource_class(self._client, rid)
                return res
            else:
                return value
        else:
            raise AttributeError

    def __setattr__(self, name, value):
        if "_init_done" not in self.__dict__ or name in self.__dict__:
            # use default setattr
            object.__setattr__(self, name, value)
        elif name in self.field_names:
            # custom field, let's set it
            attr = self._name_to_attr(name)
            # Set value only if value has actually changed
            if not str(self._data[attr]) == str(value):
                self._data_cache[attr] = value
                self._dirty_fields.add(name)
        else:
            raise AttributeError("Can't set propery: attribute %s \
                                          not found." % (name))

    def _name_to_attr(self, name):
        "Convert property name in pipedrive's object internal key."
        if self.HAS_CUSTOM_FIELDS and name in self.field_names:
            attr = self.field_names[name]
        else:
            attr = name
        return attr
        # Check if test on HAS_CUSTOM_FIELDS is required

    def save(self):
        "Save data back to pipedrive"

        if not self.active:
            raise Exception("Can't save resource %s: record deleted in Pipedrive" % self.id)

        if not self._dirty_fields:
            debug("No dirty fields for object %s" % self.id)
            return
        debug("Saving dirty fields: %s" % self._dirty_fields)
        data_for_update = {}
        for f in self._dirty_fields:
            attr = self._name_to_attr(f)
            data_for_update[attr] = self._data[attr]
        self._client.update_resource(self.RESOURCE_SEGMENT, self.id,
                                     data_for_update)
        self._dirty_fields.clear()
        self._data.clear()

    @property
    def _data(self):
        if not self._data_cache:
            (r, data) = self._client._fetch_resource_by_id(
                self.RESOURCE_SEGMENT, self.id)
            self.url = r.url
            self._data_cache = data

        return self._data_cache

    @property
    def active(self):
        return self._data["active_flag"]

    @property
    def field_keys(self):
        if not self.HAS_CUSTOM_FIELDS:
            return []
        return self._client.fields[self._resource]["key_to_attr"]

    @property
    def field_names(self):
        if not self.HAS_CUSTOM_FIELDS:
            return []
        return self._client.fields[self._resource]["attr_to_key"]
{'fraction_non_alphanumeric': 0.08386934039601462, 'fraction_numerical': 0.0002522386177323748, 'mean_word_length': 1.842293906810036, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2300217', 'n_tokens_mistral': 2314, 'n_tokens_neox': 2235, 'n_words': 591}