<commit_before>import logging

from lots.load import (load_lots_available, load_lots_with_violations,
                       load_lots_land_use_vacant)
from lots.models import Lot
from sync.synchronizers import Synchronizer
from .availableproperties.adapter import (find_available_properties,
                                          find_no_longer_available_properties)
from .landuse.adapter import find_land_use_areas
from .opa.adapter import find_opa_details
from .violations.adapter import find_violations
from .waterdept.adapter import find_water_dept_details


logger = logging.getLogger(__name__)


class OPASynchronizer(Synchronizer):
    """
    A Synchronizer that updates ownership data using the OPA API.

    """
    def sync(self, data_source):
        logger.info('Starting to synchronize OPA data.')
        self.update_owner_data(count=data_source.batch_size or 1000)
        logger.info('Finished synchronizing OPA data.')

    def update_owner_data(self, count=1000):
        # TODO also lots where the owner has not been touched in a while?
        # eg, last_seen for BillingAccount?

        # grab a random set of lots to update
        lots = Lot.objects.filter(owner__isnull=True).order_by('?')[:count]
        for lot in lots:
            logger.debug('Updating OPA data for lot %s' % lot)
            try:
                lot.billing_account = find_opa_details(lot.address_line1)
                lot.owner = lot.billing_account.account_owner.owner
                lot.save()
            except Exception:
                logger.exception('Caught exception while getting OPA data for '
                                 'lot %s' % lot)


class WaterDeptSynchronizer(Synchronizer):
    """
    A Synchronizer that updates Water Department data.

    """
    def sync(self, data_source):
        logger.info('Starting to synchronize Water Department data.')
        self.update_water_dept_data()<commit_msg>failing to get OPA data is not that uncommon<commit_after>import logging

from lots.load import (load_lots_available, load_lots_with_violations,
                       load_lots_land_use_vacant)
from lots.models import Lot
from sync.synchronizers import Synchronizer
from .availableproperties.adapter import (find_available_properties,
                                          find_no_longer_available_properties)
from .landuse.adapter import find_land_use_areas
from .opa.adapter import find_opa_details
from .violations.adapter import find_violations
from .waterdept.adapter import find_water_dept_details


logger = logging.getLogger(__name__)


class OPASynchronizer(Synchronizer):
    """
    A Synchronizer that updates ownership data using the OPA API.

    """
    def sync(self, data_source):
        logger.info('Starting to synchronize OPA data.')
        self.update_owner_data(count=data_source.batch_size or 1000)
        logger.info('Finished synchronizing OPA data.')

    def update_owner_data(self, count=1000):
        # TODO also lots where the owner has not been touched in a while?
        # eg, last_seen for BillingAccount?

        # grab a random set of lots to update
        lots = Lot.objects.filter(owner__isnull=True).order_by('?')[:count]
        for lot in lots:
            logger.debug('Updating OPA data for lot %s' % lot)
            try:
                lot.billing_account = find_opa_details(lot.address_line1)
                lot.owner = lot.billing_account.account_owner.owner
                lot.save()
            except Exception:
                logger.warn('Caught exception while getting OPA data for lot '
                            '%s' % lot)


class WaterDeptSynchronizer(Synchronizer):
    """
    A Synchronizer that updates Water Department data.

    """
    def sync(self, data_source):
        logger.info('Starting to synchronize Water Department data.')
        self.update_water_dept_data()
{'fraction_non_alphanumeric': 0.07159412825135204, 'fraction_numerical': 0.004635591037857327, 'mean_word_length': 2.727447216890595, 'pattern_counts': {'":': 0, '<': 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': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3345011', 'n_tokens_mistral': 1107, 'n_tokens_neox': 1052, 'n_words': 295}