<commit_before>from threading import Lock

import pyes
from flask import _request_ctx_stack

class ElasticSearch(object):

    """Thin wrapper around an ElasticSearch connection to make connection handling
    transparent in a Flask application. Usage:

        app = Flask(__name__)
        es = ElasticSearch(app)

    Or, you can bind the object to the application later:

        es = ElasticSearch()

        def create_app():
            app = Flask(__name__)
            es.init_app(app)
            return app
    """

    def __init__(self, app=None):
        if app is not None:
            self.app = app
            self.init_app(app)
        else:
            self.app = None

        self.Model = make_model(self)
        self._connection_lock = Lock()

    def init_app(self, app):
        app.config.setdefault('ELASTICSEARCH_HOST', '127.0.0.1:9200')
        app.config.setdefault('ELASTICSEARCH_INDEX', app.name)

        if not hasattr(app, 'extensions'):
            app.extensions = {}
        app.extensions['elasticsearch'] = self

    def get_app(self):
        """Helper method that implements the logic to look up an application.
        """
        if self.app is not None:
            return self.app
        ctx = _request_ctx_stack.top
        if ctx is not None:
            return ctx.app
        raise RuntimeError('application not registered on ElasticSearch '
                           'instance and no application bound to current '
                           'context')

    def get_conn(self, app):
        with self._connection_lock:
            host = app.config['ELASTICSEARCH_HOST']
            conn = pyes.ES(host)
            return conn

    @property
    def conn(self):
        return self.get_conn(self.get_app())

    @property
    def index(self):
        return self.get_app().config['ELASTICSEARCH_INDEX']


class _Model(dict):
    @classmethod<commit_msg>Prevent pyes from being too clever with JSON datetimes<commit_after>from threading import Lock
import json

import pyes
from flask import _request_ctx_stack

class ElasticSearch(object):

    """Thin wrapper around an ElasticSearch connection to make connection handling
    transparent in a Flask application. Usage:

        app = Flask(__name__)
        es = ElasticSearch(app)

    Or, you can bind the object to the application later:

        es = ElasticSearch()

        def create_app():
            app = Flask(__name__)
            es.init_app(app)
            return app
    """

    def __init__(self, app=None):
        if app is not None:
            self.app = app
            self.init_app(app)
        else:
            self.app = None

        self.Model = make_model(self)
        self._connection_lock = Lock()

    def init_app(self, app):
        app.config.setdefault('ELASTICSEARCH_HOST', '127.0.0.1:9200')
        app.config.setdefault('ELASTICSEARCH_INDEX', app.name)

        if not hasattr(app, 'extensions'):
            app.extensions = {}
        app.extensions['elasticsearch'] = self

    def get_app(self):
        """Helper method that implements the logic to look up an application.
        """
        if self.app is not None:
            return self.app
        ctx = _request_ctx_stack.top
        if ctx is not None:
            return ctx.app
        raise RuntimeError('application not registered on ElasticSearch '
                           'instance and no application bound to current '
                           'context')

    def get_conn(self, app):
        with self._connection_lock:
            host = app.config['ELASTICSEARCH_HOST']
            # We specifically set decoder to prevent pyes from futzing with
            # datetimes.
            conn = pyes.ES(host, decoder=json.JSONDecoder)
            return conn

    @property
    def conn(self):
        return self.get_conn(self.get_app())

    @property
    def index(self):
        return self.get_app().config['ELASTICSEARCH_INDEX']


class _Model(dict):
    @classmethod
{'fraction_non_alphanumeric': 0.08358358358358359, 'fraction_numerical': 0.005005005005005005, 'mean_word_length': 2.044173648134044, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '5364517', 'n_tokens_mistral': 1125, 'n_tokens_neox': 1084, 'n_words': 321}