Repository: CartoDB/cartoframes
Pull request #1639 (2020-05-19 07:22:10)

Release 1.0.3.1


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a42a213..5d294ed4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [1.0.3.1] - 2020-05-19
+
+### Fixed
+- Fix read null geoms from carto (#1637)
+- Fix show_info in layout maps (#1638)
+
 ## [1.0.3] - 2020-05-14
 
 ### Added
diff --git a/README.rst b/README.rst
index a0a6c58b..5d7e1394 100644
--- a/README.rst
+++ b/README.rst
@@ -4,8 +4,8 @@ CARTOframes
 
 .. image:: https://travis-ci.org/CartoDB/cartoframes.svg?branch=develop
     :target: https://travis-ci.org/CartoDB/cartoframes
-.. image:: https://img.shields.io/badge/pypi-v1.0.3-orange
-    :target: https://pypi.org/project/cartoframes/1.0.3
+.. image:: https://img.shields.io/badge/pypi-v1.0.3.1-orange
+    :target: https://pypi.org/project/cartoframes/1.0.3.1
 
 A Python package for integrating `CARTO <https://carto.com/>`__ maps, analysis, and data services into data science workflows.
 
@@ -14,11 +14,11 @@ Python data analysis workflows often rely on the de facto standards `pandas <htt
 Try it Out
 ==========
 
-* Stable (1.0.3): |stable|
+* Stable (1.0.3.1): |stable|
 * Latest (develop branch): |develop|
 
 .. |stable| image:: https://mybinder.org/badge_logo.svg
-    :target: https://mybinder.org/v2/gh/cartodb/cartoframes/v1.0.3?filepath=examples
+    :target: https://mybinder.org/v2/gh/cartodb/cartoframes/v1.0.3.1?filepath=examples
 
 .. |develop| image:: https://mybinder.org/badge_logo.svg
     :target: https://mybinder.org/v2/gh/cartodb/cartoframes/develop?filepath=examples
diff --git a/binder/requirements.txt b/binder/requirements.txt
index 01fc5ae5..a344a930 100644
--- a/binder/requirements.txt
+++ b/binder/requirements.txt
@@ -1,4 +1,4 @@
-cartoframes==1.0.3
+cartoframes==1.0.3.1
 # Additional dependencies from examples
 matplotlib
 dask
diff --git a/cartoframes/_version.py b/cartoframes/_version.py
index 3f6fab60..6cd484a5 100644
--- a/cartoframes/_version.py
+++ b/cartoframes/_version.py
@@ -1,1 +1,1 @@
-__version__ = '1.0.3'
+__version__ = '1.0.3.1'
diff --git a/cartoframes/assets/init_layout.js.j2 b/cartoframes/assets/init_layout.js.j2
index 9078ea99..4b4b3be4 100644
--- a/cartoframes/assets/init_layout.js.j2
+++ b/cartoframes/assets/init_layout.js.j2
@@ -1,9 +1,7 @@
 const maps = {{ maps|tojson }};
-const show_info = '{{show_info}}' === 'True';
 const is_static = '{{is_static}}' === 'True';
 
 init({
-  show_info,
   is_static,
   maps
 });
\ No newline at end of file
diff --git a/cartoframes/assets/src/bundle.js b/cartoframes/assets/src/bundle.js
index 8ed96538..9c4cf6dc 100644
--- a/cartoframes/assets/src/bundle.js
+++ b/cartoframes/assets/src/bundle.js
@@ -478,9 +478,9 @@ var init = (function () {
     return value.toLocaleString();
   }
 
-  function updateViewport(map) {
+  function updateViewport(id, map) {
     function updateMapInfo() {
-      const mapInfo$ = document.getElementById('map-info');
+      const mapInfo$ = document.getElementById(id);
       const center = map.getCenter();
       const lat = center.lat.toFixed(6);
       const lng = center.lng.toFixed(6);
@@ -870,7 +870,8 @@ var init = (function () {
     const map = createMap(container, basemapStyle, settings.bounds, settings.mapboxtoken);
 
     if (settings.show_info) {
-      updateViewport(map);
+      const id = mapIndex !== undefined ? `map-info-${mapIndex}` : 'map-info';
+      updateViewport(id, map);
     }
 
     if (settings.camera) {
diff --git a/cartoframes/assets/src/map.js b/cartoframes/assets/src/map.js
index 3aca1433..2197180a 100644
--- a/cartoframes/assets/src/map.js
+++ b/cartoframes/assets/src/map.js
@@ -25,7 +25,8 @@ export function initMap(settings, mapIndex) {
   const map = createMap(container, basemapStyle, settings.bounds, settings.mapboxtoken);
 
   if (settings.show_info) {
-    updateViewport(map);
+    const id = mapIndex !== undefined ? `map-info-${mapIndex}` : 'map-info';
+    updateViewport(id, map);
   }
 
   if (settings.camera) {
diff --git a/cartoframes/assets/src/utils.js b/cartoframes/assets/src/utils.js
index e243463c..2d51ceed 100644
--- a/cartoframes/assets/src/utils.js
+++ b/cartoframes/assets/src/utils.js
@@ -33,9 +33,9 @@ export function formatNumber(value) {
   return value.toLocaleString();
 }
 
-export function updateViewport(map) {
+export function updateViewport(id, map) {
   function updateMapInfo() {
-    const mapInfo$ = document.getElementById('map-info');
+    const mapInfo$ = document.getElementById(id);
     const center = map.getCenter();
     const lat = center.lat.toFixed(6);
     const lng = center.lng.toFixed(6);
diff --git a/cartoframes/assets/templates/viz/info.html.j2 b/cartoframes/assets/templates/viz/info.html.j2
deleted file mode 100644
index 1b2543b6..00000000
--- a/cartoframes/assets/templates/viz/info.html.j2
+++ /dev/null
@@ -1,1 +0,0 @@
-<div id="map-info" class="map-info"></div>
\ No newline at end of file
diff --git a/cartoframes/assets/templates/viz/main.html.j2 b/cartoframes/assets/templates/viz/main.html.j2
index 3d26c3a5..7410bb27 100644
--- a/cartoframes/assets/templates/viz/main.html.j2
+++ b/cartoframes/assets/templates/viz/main.html.j2
@@ -51,7 +51,7 @@
       <div class="as-map-area">
         <div id="map" class="map"></div>
         {% if show_info %}
-          {% include 'templates/viz/info.html.j2' %}
+          <div id="map-info" class="map-info"></div>
         {% endif %}
         {% if has_legends or layer_selector %}
           <div class="as-map-panels" data-name="Legends">
diff --git a/cartoframes/assets/templates/viz/main_layout.html.j2 b/cartoframes/assets/templates/viz/main_layout.html.j2
index 9f371c40..43c87094 100644
--- a/cartoframes/assets/templates/viz/main_layout.html.j2
+++ b/cartoframes/assets/templates/viz/main_layout.html.j2
@@ -62,6 +62,9 @@
           <as-responsive-content id="main-container-{{map_index}}" class="layout-map">
             <div class="as-map-area">
               <div id="map-{{ map_index }}" class="map"></div>
+              {% if maps[map_index]['show_info'] %}
+                <div id="map-info-{{ map_index }}" class="map-info"></div>
+              {% endif %}
             </div>
             {% if has_legends or layer_selector %}
               {% set layers = maps[map_index]['layers'] %}
diff --git a/cartoframes/utils/columns.py b/cartoframes/utils/columns.py
index 6d6df518..37e00cce 100644
--- a/cartoframes/utils/columns.py
+++ b/cartoframes/utils/columns.py
@@ -7,7 +7,6 @@ from unidecode import unidecode
 from .utils import dtypes2pg, pg2dtypes, PG_NULL
 
 BOOL_DBTYPES = ['bool', 'boolean']
-OBJECT_DBTYPES = ['text']
 INT_DBTYPES = ['int2', 'int4', 'int2', 'int', 'int8', 'smallint', 'integer', 'bigint']
 FLOAT_DBTYPES = ['float4', 'float8', 'real', 'double precision', 'numeric', 'decimal']
 DATETIME_DBTYPES = ['date', 'timestamp', 'timestampz']
@@ -185,27 +184,21 @@ def _is_unsupported(value):
 def obtain_converters(columns):
     converters = {}
 
-    for int_column_name in type_columns_names(columns, INT_DBTYPES):
-        converters[int_column_name] = _convert_int
-
-    for float_column_name in type_columns_names(columns, FLOAT_DBTYPES):
-        converters[float_column_name] = _convert_float
-
-    for bool_column_name in type_columns_names(columns, BOOL_DBTYPES):
-        converters[bool_column_name] = _convert_bool
-
-    for object_column_name in type_columns_names(columns, OBJECT_DBTYPES):
-        converters[object_column_name] = _convert_object
+    for column in columns:
+        if column.dbtype in INT_DBTYPES:
+            converters[column.name] = _convert_int
+        elif column.dbtype in FLOAT_DBTYPES:
+            converters[column.name] = _convert_float
+        elif column.dbtype in BOOL_DBTYPES:
+            converters[column.name] = _convert_bool
+        else:
+            converters[column.name] = _convert_generic
 
     return converters
 
 
 def date_columns_names(columns):
-    return type_columns_names(columns, DATETIME_DBTYPES)
-
-
-def type_columns_names(columns, dbtypes):
-    return [x.name for x in columns if x.dbtype in dbtypes]
+    return [x.name for x in columns if x.dbtype in DATETIME_DBTYPES]
 
 
 def _convert_int(x):
@@ -230,7 +223,7 @@ def _convert_bool(x):
     return bool(x)
 
 
-def _convert_object(x):
+def _convert_generic(x):
     if _is_none_null(x):
         return None
     return x
@@ -238,10 +231,3 @@ def _convert_object(x):
 
 def _is_none_null(x):
     return x is None or x == PG_NULL
-
-
-def _first_value(series):
-    series = series.loc[~series.isnull()]  # Remove null values
-    if len(series) > 0:
-        return series.iloc[0]
-    return None
diff --git a/cartoframes/utils/utils.py b/cartoframes/utils/utils.py
index 1506c500..772675f3 100644
--- a/cartoframes/utils/utils.py
+++ b/cartoframes/utils/utils.py
@@ -266,7 +266,6 @@ def get_geodataframe_data(data, encode_data=True):
         return data
 
 
-# Dup
 def _first_value(series):
     series = series.loc[~series.isnull()]  # Remove null values
     if len(series) > 0:
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index 452caab4..d507d226 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -5,6 +5,7 @@ We follow the git-flow model to generate the releases. The version numbers are M
 - M: major
 - m: minor
 - u: micro
+- p: patch (only for hotfixes)
 
 ## The release branch
 


Test patch:
diff --git a/tests/unit/utils/test_columns.py b/tests/unit/utils/test_columns.py
index 879fa719..157c0232 100644
--- a/tests/unit/utils/test_columns.py
+++ b/tests/unit/utils/test_columns.py
@@ -6,7 +6,9 @@ from pandas import DataFrame
 from geopandas import GeoDataFrame
 
 from cartoframes.utils.geom_utils import set_geometry
-from cartoframes.utils.columns import ColumnInfo, get_dataframe_columns_info, normalize_names
+from cartoframes.utils.columns import ColumnInfo, get_dataframe_columns_info, normalize_names, \
+                                      obtain_converters, _convert_int, _convert_float, \
+                                      _convert_bool, _convert_generic
 
 
 class TestColumns(object):
@@ -113,3 +115,21 @@ class TestColumns(object):
             ColumnInfo('the_geom', 'the_geom', 'geometry(Geometry, 4326)', True),
             ColumnInfo('g-e-o-m-e-t-r-y', 'g_e_o_m_e_t_r_y', 'text', False)
         ]
+
+    def test_converters(self):
+        columns = [
+            ColumnInfo('cartodb_id', 'cartodb_id', 'integer', False),
+            ColumnInfo('the_geom', 'the_geom', 'geometry(Geometry, 4326)', True),
+            ColumnInfo('name', 'name', 'text', False),
+            ColumnInfo('flag', 'flag', 'boolean', False),
+            ColumnInfo('number', 'number', 'double precision', False)
+        ]
+
+        converters = obtain_converters(columns)
+
+        assert type(converters) == dict
+        assert converters['cartodb_id'] == _convert_int
+        assert converters['the_geom'] == _convert_generic
+        assert converters['name'] == _convert_generic
+        assert converters['flag'] == _convert_bool
+        assert converters['number'] == _convert_float