diff --git a/cartoframes/__init__.py b/cartoframes/__init__.py index 3ad5b0f20..da23a071d 100644 --- a/cartoframes/__init__.py +++ b/cartoframes/__init__.py @@ -1,5 +1,6 @@ from ._version import __version__ from .core.cartodataframe import CartoDataFrame +from .core.logger import set_log_level from .io.carto import read_carto, to_carto, has_table, delete_table, describe_table, \ update_table, copy_table, create_table_from_query @@ -14,5 +15,6 @@ 'describe_table', 'update_table', 'copy_table', - 'create_table_from_query' + 'create_table_from_query', + 'set_log_level' ] diff --git a/cartoframes/core/logger.py b/cartoframes/core/logger.py new file mode 100644 index 000000000..71debd792 --- /dev/null +++ b/cartoframes/core/logger.py @@ -0,0 +1,38 @@ +import sys +import logging + + +def init_logger(): + handler = logging.StreamHandler(sys.stdout) + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + handler.setFormatter(formatter) + log = logging.getLogger('CARTOframes') + log.setLevel(logging.INFO) + log.addHandler(handler) + return log + + +def set_log_level(level): + """Set the level of the log in the library. + + Args: + level (str): log level name. By default it's set to "info". Valid log levels are: + critical, error, warning, info, debug, notset. + + """ + levels = { + 'critical': logging.CRITICAL, + 'error': logging.ERROR, + 'warning': logging.WARNING, + 'info': logging.INFO, + 'debug': logging.DEBUG, + 'notset': logging.NOTSET + } + + if level not in levels: + return ValueError('Wrong log level. Valid log levels are: critical, error, warning, info, debug, notset.') + + log.setLevel(levels[level]) + + +log = init_logger() diff --git a/cartoframes/core/managers/context_manager.py b/cartoframes/core/managers/context_manager.py index 1e415a107..5e93d3478 100644 --- a/cartoframes/core/managers/context_manager.py +++ b/cartoframes/core/managers/context_manager.py @@ -7,15 +7,14 @@ from carto.exceptions import CartoException, CartoRateLimitException from carto.sql import SQLClient, BatchSQLClient, CopySQLClient +from ... import __version__ +from ...core.logger import log from ...io.dataset_info import DatasetInfo - from ...auth.defaults import get_default_credentials - from ...utils.utils import is_sql_query, check_credentials, encode_row, map_geom_type, PG_NULL from ...utils.columns import Column, get_dataframe_columns_info, obtain_converters, \ date_columns_names, normalize_name -from ... import __version__ DEFAULT_RETRY_TIMES = 3 @@ -50,7 +49,7 @@ def copy_from(self, cdf, table_name, if_exists='fail', cartodbfy=True, log_enabl if if_exists == 'replace' or not self.has_table(table_name, schema): if log_enabled: - print('Debug: creating table "{}"'.format(table_name)) + log.debug('Creating table "{}"'.format(table_name)) self._create_table_from_columns(table_name, columns, schema, cartodbfy) elif if_exists == 'fail': raise Exception('Table "{schema}.{table_name}" already exists in CARTO. ' @@ -66,7 +65,7 @@ def create_table_from_query(self, table_name, query, if_exists, cartodbfy=True, if if_exists == 'replace' or not self.has_table(table_name, schema): if log_enabled: - print('Debug: creating table "{}"'.format(table_name)) + log.debug('Creating table "{}"'.format(table_name)) self._create_table_from_query(table_name, query, schema, cartodbfy) elif if_exists == 'fail': raise Exception('Table "{schema}.{table_name}" already exists in CARTO. ' @@ -83,9 +82,9 @@ def delete_table(self, table_name, log_enabled=True): output = self.execute_query(query) if log_enabled: if ('notices' in output and 'does not exist' in output['notices'][0]): - print('Debug: table "{}" does not exist'.format(table_name)) + log.debug('Table "{}" does not exist'.format(table_name)) else: - print('Debug: table "{}" removed'.format(table_name)) + log.debug('Table "{}" removed'.format(table_name)) def update_table(self, table_name, privacy=None, new_table_name=None): dataset_info = DatasetInfo(self.auth_client, table_name) @@ -264,7 +263,7 @@ def _copy_from(self, dataframe, table_name, columns): def normalize_table_name(self, table_name): norm_table_name = normalize_name(table_name) if norm_table_name != table_name: - print('Debug: table name normalized: "{}"'.format(norm_table_name)) + log.debug('Table name normalized: "{}"'.format(norm_table_name)) return norm_table_name diff --git a/cartoframes/data/observatory/catalog/dataset.py b/cartoframes/data/observatory/catalog/dataset.py index aa203c9a6..df97607f8 100644 --- a/cartoframes/data/observatory/catalog/dataset.py +++ b/cartoframes/data/observatory/catalog/dataset.py @@ -17,6 +17,7 @@ from . import subscription_info from . import subscriptions from . import utils +from ....core.logger import log from ....auth import Credentials, defaults DATASET_TYPE = 'dataset' @@ -494,5 +495,5 @@ def _get_summary_data(self): if data: return data else: - print('Summary information is not available') + log.info('Summary information is not available') return None diff --git a/cartoframes/data/observatory/catalog/utils.py b/cartoframes/data/observatory/catalog/utils.py index cf6a7b0d6..81b01baa8 100644 --- a/cartoframes/data/observatory/catalog/utils.py +++ b/cartoframes/data/observatory/catalog/utils.py @@ -3,6 +3,8 @@ from .subscriptions import trigger_subscription from .subscription_info import fetch_subscription_info +from ....core.logger import log + def is_ipython_notebook(): """ @@ -109,4 +111,4 @@ def on_button_no_clicked(b): def display_subscription_form_cli(): - print('This method is not yet implemented in CLI') + log.info('This method is not yet implemented in CLI') diff --git a/cartoframes/data/observatory/enrichment/enrichment.py b/cartoframes/data/observatory/enrichment/enrichment.py index 9b01702b4..ede704df3 100644 --- a/cartoframes/data/observatory/enrichment/enrichment.py +++ b/cartoframes/data/observatory/enrichment/enrichment.py @@ -1,4 +1,5 @@ from .enrichment_service import EnrichmentService, prepare_variables, AGGREGATION_DEFAULT, AGGREGATION_NONE +from ....core.logger import log class Enrichment(EnrichmentService): @@ -314,11 +315,12 @@ def enrich_polygons(self, dataframe, variables, geom_col=None, filters=[], aggre enrichment = Enrichment() cdf_enrich = enrichment.enrich_polygons(df, variables, aggregation=aggregation) """ + log.debug('Preparing') variables = prepare_variables(variables, self.credentials, aggregation) cartodataframe = self._prepare_data(dataframe, geom_col) temp_table_name = self._get_temp_table_name() + log.debug('Uploading') self._upload_data(temp_table_name, cartodataframe) - queries = self._get_polygon_enrichment_sql(temp_table_name, variables, filters, aggregation) return self._execute_enrichment(queries, cartodataframe) diff --git a/cartoframes/data/observatory/enrichment/enrichment_service.py b/cartoframes/data/observatory/enrichment/enrichment_service.py index 73d05b59d..f2b5f06b5 100644 --- a/cartoframes/data/observatory/enrichment/enrichment_service.py +++ b/cartoframes/data/observatory/enrichment/enrichment_service.py @@ -9,8 +9,10 @@ from ....auth import get_default_credentials from ....exceptions import EnrichmentException from ....core.cartodataframe import CartoDataFrame +from ....core.logger import log from ....utils.geom_utils import to_geojson + _ENRICHMENT_ID = 'enrichment_id' _GEOJSON_COLUMN = '__geojson_geom' _DEFAULT_PROJECT = 'carto-do' @@ -338,7 +340,7 @@ def _prepare_variable(variable, aggregation=None): if aggregation is not None: variable_agg = _get_aggregation(variable, aggregation) if not variable_agg and aggregation is not AGGREGATION_NONE: - print('Warning: {} skipped because it does not have aggregation method'.format(variable.id)) + log.warning('%s skipped because it does not have aggregation method', variable.id) return None return variable diff --git a/cartoframes/data/services/geocoding.py b/cartoframes/data/services/geocoding.py index 5a6ce284e..7b8b99752 100644 --- a/cartoframes/data/services/geocoding.py +++ b/cartoframes/data/services/geocoding.py @@ -3,13 +3,13 @@ from __future__ import absolute_import import re -import logging from .utils import geocoding_utils from .utils import geocoding_constants from .utils import TableGeocodingLock from .service import Service +from ...core.logger import log from ...core.managers.source_manager import SourceManager from ...io.carto import read_carto, to_carto, has_table, delete_table, update_table, copy_table, create_table_from_query @@ -248,7 +248,7 @@ def geocode(self, source, street, result = self.result(data=cdf, metadata=metadata) - print('Success! Data geocoded correctly') + log.info('Success! Data geocoded correctly') return result @@ -346,13 +346,13 @@ def _geocode(self, table_name, street, city=None, state=None, country=None, stat # Internal Geocoding implementation. # Geocode a table's rows not already geocoded in a dataset' - logging.info('table_name = "%s"', table_name) - logging.info('street = "%s"', street) - logging.info('city = "%s"', city) - logging.info('state = "%s"', state) - logging.info('country = "%s"', country) - logging.info('status = "%s"', status) - logging.info('dry_run = "%s"', dry_run) + log.debug('table_name = "%s"', table_name) + log.debug('street = "%s"', street) + log.debug('city = "%s"', city) + log.debug('state = "%s"', state) + log.debug('country = "%s"', country) + log.debug('status = "%s"', status) + log.debug('dry_run = "%s"', dry_run) output = {} @@ -389,19 +389,19 @@ def _geocode(self, table_name, street, city=None, state=None, country=None, stat add_columns += [(geocoding_constants.HASH_COLUMN, 'text')] - logging.info("Adding columns %s if needed", ', '.join([c[0] for c in add_columns])) + log.debug("Adding columns %s if needed", ', '.join([c[0] for c in add_columns])) alter_sql = "ALTER TABLE {table} {add_columns};".format( table=table_name, add_columns=','.join([ 'ADD COLUMN IF NOT EXISTS {} {}'.format(name, type) for name, type in add_columns])) self._execute_query(alter_sql) - logging.debug("Executing query: %s", sql) + log.debug("Executing query: %s", sql) result = None try: result = self._execute_long_running_query(sql) except Exception as err: - logging.error(err) + log.error(err) msg = str(err) output['error'] = msg # FIXME: Python SDK should return proper exceptions @@ -421,12 +421,12 @@ def _geocode(self, table_name, street, city=None, state=None, country=None, stat if result and not aborted: # Number of updated rows not available for batch queries # output['updated_rows'] = result.rowcount - # logging.info('Number of rows updated: %d', output['updated_rows']) + # log.debug('Number of rows updated: %d', output['updated_rows']) pass if not aborted: sql = geocoding_utils.posterior_summary_query(table_name) - logging.debug("Executing result summary query: %s", sql) + log.debug("Executing result summary query: %s", sql) result = self._execute_query(sql) geocoding_utils.set_post_summary_info(summary, result, output) @@ -439,12 +439,12 @@ def _geocode(self, table_name, street, city=None, state=None, country=None, stat def _execute_prior_summary(self, dataset_name, street, city, state, country): sql = geocoding_utils.exists_column_query(dataset_name, geocoding_constants.HASH_COLUMN) - logging.debug("Executing check first time query: %s", sql) + log.debug("Executing check first time query: %s", sql) result = self._execute_query(sql) if not result or result.get('total_rows', 0) == 0: sql = geocoding_utils.first_time_summary_query(dataset_name, street, city, state, country) - logging.debug("Executing first time summary query: %s", sql) + log.debug("Executing first time summary query: %s", sql) else: sql = geocoding_utils.prior_summary_query(dataset_name, street, city, state, country) - logging.debug("Executing summary query: %s", sql) + log.debug("Executing summary query: %s", sql) return self._execute_query(sql) diff --git a/cartoframes/data/services/isolines.py b/cartoframes/data/services/isolines.py index e683c67ec..4f289111c 100644 --- a/cartoframes/data/services/isolines.py +++ b/cartoframes/data/services/isolines.py @@ -1,6 +1,7 @@ from __future__ import absolute_import from .service import Service +from ...core.logger import log from ...core.managers.source_manager import SourceManager from ...io.carto import read_carto, to_carto, delete_table @@ -192,7 +193,7 @@ def _iso_areas(self, result = self.result(data=cdf, metadata=metadata) - print('Success! Isolines created correctly') + log.info('Success! Isolines created correctly') return result diff --git a/cartoframes/io/carto.py b/cartoframes/io/carto.py index fc9bbf985..0d5f61a93 100644 --- a/cartoframes/io/carto.py +++ b/cartoframes/io/carto.py @@ -6,6 +6,7 @@ from carto.exceptions import CartoException +from ..core.logger import log from ..core.cartodataframe import CartoDataFrame from ..core.managers.context_manager import ContextManager from ..utils.utils import is_sql_query @@ -107,7 +108,7 @@ def to_carto(dataframe, table_name, credentials=None, if_exists='fail', geom_col context_manager.copy_from(cdf, table_name, if_exists, cartodbfy, log_enabled) if log_enabled: - print('Success! Data uploaded correctly') + log.info('Success! Data uploaded correctly') def has_table(table_name, credentials=None, schema=None): @@ -176,7 +177,7 @@ def describe_table(table_name, credentials=None, schema=None): except CartoException: # There is an issue with ghost tables when # the table is created for the first time - print('Debug: we can not retrieve the privacy from the metadata') + log.debug('We can not retrieve the privacy from the metadata') privacy = '' return { @@ -215,7 +216,7 @@ def update_table(table_name, credentials=None, new_table_name=None, privacy=None context_manager.update_table(table_name, privacy, new_table_name) if log_enabled: - print('Success! Table updated correctly') + log.info('Success! Table updated correctly') def copy_table(table_name, new_table_name, credentials=None, if_exists='fail', log_enabled=True): @@ -242,7 +243,7 @@ def copy_table(table_name, new_table_name, credentials=None, if_exists='fail', l context_manager.create_table_from_query(new_table_name, query, if_exists) if log_enabled: - print('Success! Table copied correctly') + log.info('Success! Table copied correctly') def create_table_from_query(query, new_table_name, credentials=None, if_exists='fail', log_enabled=True): @@ -268,4 +269,4 @@ def create_table_from_query(query, new_table_name, credentials=None, if_exists=' context_manager.create_table_from_query(new_table_name, query, if_exists) if log_enabled: - print('Success! Table created correctly') + log.info('Success! Table created correctly') diff --git a/cartoframes/viz/helpers/__init__.py b/cartoframes/viz/helpers/__init__.py index 64000decd..43005c359 100644 --- a/cartoframes/viz/helpers/__init__.py +++ b/cartoframes/viz/helpers/__init__.py @@ -14,12 +14,6 @@ from .isolines_layer import isolines_layer -def _inspect(helper): - import inspect - lines = inspect.getsource(helper) - print(lines) - - __all__ = [ 'color_bins_layer', 'color_category_layer', diff --git a/cartoframes/viz/widgets/__init__.py b/cartoframes/viz/widgets/__init__.py index cf6adddfb..36936d91f 100644 --- a/cartoframes/viz/widgets/__init__.py +++ b/cartoframes/viz/widgets/__init__.py @@ -11,6 +11,7 @@ from .histogram_widget import histogram_widget from .time_series_widget import time_series_widget + __all__ = [ 'animation_widget', 'category_widget', @@ -19,9 +20,3 @@ 'histogram_widget', 'time_series_widget', ] - - -def _inspect(widget): - import inspect - lines = inspect.getsource(widget) - print(lines)