<commit_before>#
#   Copyright (c) 2010-2014, MIT Probabilistic Computing Project
#
#   Lead Developers: <NAME> and <NAME>
#   Authors: <NAME>, <NAME>, <NAME>, <NAME>
#   Research Leads: <NAME>, <NAME>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#

import inspect
import pickle
import gzip
import prettytable
import re
import os
import time
import ast

import utils
import data_utils
import plotting_utils
import api_utils
from parser import Parser
from engine import Engine

class Client(object):
    def __init__(self, crosscat_host=None, crosscat_port=8007, crosscat_engine_type='multiprocessing',
                 bayesdb_host=None, bayesdb_port=8008, seed=None, testing=False):
        """
        Create a client object. The client creates a parser, that is uses to parse all commands,
        and an engine, which is uses to execute all commands. The engine can be remote or local.
        If local, the engine will be created.
        """
        self.parser = Parser()
        if bayesdb_host is None or bayesdb_host=='localhost':
            self.online = False
            self.engine = Engine(crosscat_host, crosscat_port, crosscat_engine_type, seed, testing=testing)
        else:
            self.online = True
            self.hostname = bayesdb_host
            self.port = bayesdb_port
            self.URI = 'http://' + self.hostname + ':%d' % self.port

    def call_bayesdb_engine(self, method_name, args_dict, debug=False):
        """
        Helper function used to call the BayesDB engine, whether it is remote or local.
        Accepts method name and arguments for that method as input.
        If this is the first time a query has been executed on the given tablename
        during this session, first check that the table doesn't need any upgrades to
        work with the current version of BayesDB. (After checking/upgrading, the table
        will be considered upgraded for the duration of the session.)
        """
        table_query = 'tablename' in args_dict
        if table_query:
            tablename = args_dict['tablename']
            table_created = tablename in self.engine.persistence_layer.btable_index
            table_checked = tablename in self.engine.persistence_layer.btable_check_index

        if self.online:
            if table_query:
                if table_created and not table_checked:
                    out, id = aqupi_utils.call('upgrade_btable', {'tablename': tablename}, self.URI)
            out, id = aqupi_utils.call(method_name, args_dict, self.URI)
        else:
            if table_query:
                if table_created and not table_checked:
                    self.engine.upgrade_btable(tablename)
            method = getattr(self.engine, method_name)
            if debug:
                out = method(**args_dict)
            else:
                # when not in debug mode, catch all BayesDBErrors
                try:
                    out = method(**args_dict)
                except utils.BayesDBError as e:
                    out = dict(message=str(e), error=True)
        return out

    def __call__(self, call_input, pretty=True, timing=False, wait=False, plots=None, yes=False, debug=False, pandas_df=None, pandas_output=True, key_column=None):
        """Wrapper around execute."""
        return self.execute(call_input, pretty, timing, wait, plots, yes, debug, pandas_df, pandas_output, key_column)

    def execute(self, call_input, pretty=True, timing=False, wait=False, plots=None, yes=False, debug=False, pandas_df=None, pandas_output=True, key_column=None):
        """
        Execute a chunk of BQL. This method breaks a large chunk of BQL (like a file)
        consisting of possibly many BQL statements, breaks them up into individual statements,
        then passes each individual line to self.execute_statement() as a string.<commit_msg>No need to check table for upgrades if it's being dropped.<commit_after>#
#   Copyright (c) 2010-2014, MIT Probabilistic Computing Project
#
#   Lead Developers: <NAME> and <NAME>
#   Authors: <NAME>, <NAME>, <NAME>, <NAME>
#   Research Leads: <NAME>, <NAME>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#

import inspect
import pickle
import gzip
import prettytable
import re
import os
import time
import ast

import utils
import data_utils
import plotting_utils
import api_utils
from parser import Parser
from engine import Engine

class Client(object):
    def __init__(self, crosscat_host=None, crosscat_port=8007, crosscat_engine_type='multiprocessing',
                 bayesdb_host=None, bayesdb_port=8008, seed=None, testing=False):
        """
        Create a client object. The client creates a parser, that is uses to parse all commands,
        and an engine, which is uses to execute all commands. The engine can be remote or local.
        If local, the engine will be created.
        """
        self.parser = Parser()
        if bayesdb_host is None or bayesdb_host=='localhost':
            self.online = False
            self.engine = Engine(crosscat_host, crosscat_port, crosscat_engine_type, seed, testing=testing)
        else:
            self.online = True
            self.hostname = bayesdb_host
            self.port = bayesdb_port
            self.URI = 'http://' + self.hostname + ':%d' % self.port

    def call_bayesdb_engine(self, method_name, args_dict, debug=False):
        """
        Helper function used to call the BayesDB engine, whether it is remote or local.
        Accepts method name and arguments for that method as input.
        If this is the first time a query has been executed on the given tablename
        during this session, first check that the table doesn't need any upgrades to
        work with the current version of BayesDB. (After checking/upgrading, the table
        will be considered upgraded for the duration of the session.)
        """
        table_query = 'tablename' in args_dict
        if table_query:
            tablename = args_dict['tablename']
            table_created = tablename in self.engine.persistence_layer.btable_index
            table_checked = tablename in self.engine.persistence_layer.btable_check_index

        if self.online:
            if table_query:
                if table_created and not table_checked and method_name is not 'drop_btable':
                    out, id = aqupi_utils.call('upgrade_btable', {'tablename': tablename}, self.URI)
            out, id = aqupi_utils.call(method_name, args_dict, self.URI)
        else:
            if table_query:
                if table_created and not table_checked and method_name is not 'drop_btable':
                    self.engine.upgrade_btable(tablename)
            method = getattr(self.engine, method_name)
            if debug:
                out = method(**args_dict)
            else:
                # when not in debug mode, catch all BayesDBErrors
                try:
                    out = method(**args_dict)
                except utils.BayesDBError as e:
                    out = dict(message=str(e), error=True)
        return out

    def __call__(self, call_input, pretty=True, timing=False, wait=False, plots=None, yes=False, debug=False, pandas_df=None, pandas_output=True, key_column=None):
        """Wrapper around execute."""
        return self.execute(call_input, pretty, timing, wait, plots, yes, debug, pandas_df, pandas_output, key_column)

    def execute(self, call_input, pretty=True, timing=False, wait=False, plots=None, yes=False, debug=False, pandas_df=None, pandas_output=True, key_column=None):
        """
        Execute a chunk of BQL. This method breaks a large chunk of BQL (like a file)
        consisting of possibly many BQL statements, breaks them up into individual statements,
        then passes each individual line to self.execute_statement() as a string.
{'fraction_non_alphanumeric': 0.0756634669678148, 'fraction_numerical': 0.004517221908526256, 'mean_word_length': 2.7335581787521077, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5676980', 'n_tokens_mistral': 2463, 'n_tokens_neox': 2382, 'n_words': 895}