Repository: CartoDB/cartoframes
Pull request #1623 (2020-04-27 11:02:40)

Add public filter to catalog
https://app.clubhouse.io/cartoteam/story/68929/add-public-filter-to-catalog


Patch:
diff --git a/cartoframes/__init__.py b/cartoframes/__init__.py
index 5eb182dd..8f433208 100644
--- a/cartoframes/__init__.py
+++ b/cartoframes/__init__.py
@@ -6,7 +6,7 @@ from .io.carto import read_carto, to_carto, has_table, delete_table, rename_tabl
 
 # Check installed packages versions
 check_package('carto', '>=1.11.1')
-check_package('pandas', '>=0.25.0')
+check_package('pandas', '>=0.23.0')
 check_package('geopandas', '>=0.6.0')
 
 
diff --git a/cartoframes/data/observatory/catalog/catalog.py b/cartoframes/data/observatory/catalog/catalog.py
index 8f4086b0..d8659c43 100644
--- a/cartoframes/data/observatory/catalog/catalog.py
+++ b/cartoframes/data/observatory/catalog/catalog.py
@@ -4,7 +4,7 @@ from .category import Category
 from .country import Country
 from .geography import Geography
 from .subscriptions import Subscriptions
-from .repository.constants import COUNTRY_FILTER, CATEGORY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER
+from .repository.constants import COUNTRY_FILTER, CATEGORY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER, PUBLIC_FILTER
 
 from ....utils.utils import get_credentials
 
@@ -231,6 +231,20 @@ class Catalog:
         self.filters[PROVIDER_FILTER] = provider_id
         return self
 
+    def public(self, is_public=True):
+        """Add a public filter to the current Catalog instance
+
+        Args:
+            is_public (str, optional):
+              Flag to filter public (True) or private (False) datasets. Default is True.
+
+        Returns:
+            :py:class:`CatalogList <cartoframes.data.observatory.entity.CatalogList>`
+
+        """
+        self.filters[PUBLIC_FILTER] = 'true' if is_public else 'false'
+        return self
+
     def clear_filters(self):
         """Remove the current filters from this Catalog instance."""
         self.filters = {}
diff --git a/cartoframes/data/observatory/catalog/repository/constants.py b/cartoframes/data/observatory/catalog/repository/constants.py
index 3cd42d32..d44986a5 100644
--- a/cartoframes/data/observatory/catalog/repository/constants.py
+++ b/cartoframes/data/observatory/catalog/repository/constants.py
@@ -3,5 +3,6 @@ COUNTRY_FILTER = 'country'
 DATASET_FILTER = 'dataset'
 GEOGRAPHY_FILTER = 'geography'
 PROVIDER_FILTER = 'provider'
+PUBLIC_FILTER = 'public'
 VARIABLE_FILTER = 'variable'
 VARIABLE_GROUP_FILTER = 'variable_group'
diff --git a/cartoframes/data/observatory/catalog/repository/dataset_repo.py b/cartoframes/data/observatory/catalog/repository/dataset_repo.py
index b50bc1ba..4bd26ade 100644
--- a/cartoframes/data/observatory/catalog/repository/dataset_repo.py
+++ b/cartoframes/data/observatory/catalog/repository/dataset_repo.py
@@ -1,11 +1,11 @@
-from .constants import CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER
+from .constants import CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER, PUBLIC_FILTER
 from .entity_repo import EntityRepository
 
 DATASET_TYPE = 'dataset'
 
 _DATASET_ID_FIELD = 'id'
 _DATASET_SLUG_FIELD = 'slug'
-_ALLOWED_FILTERS = [CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER]
+_ALLOWED_FILTERS = [CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER, PROVIDER_FILTER, PUBLIC_FILTER]
 
 
 def get_dataset_repo():
diff --git a/cartoframes/data/observatory/catalog/repository/geography_repo.py b/cartoframes/data/observatory/catalog/repository/geography_repo.py
index 85da8d87..353ac0e1 100644
--- a/cartoframes/data/observatory/catalog/repository/geography_repo.py
+++ b/cartoframes/data/observatory/catalog/repository/geography_repo.py
@@ -1,14 +1,14 @@
 from geopandas import GeoDataFrame
 
 from .....utils.geom_utils import set_geometry
-from .constants import COUNTRY_FILTER, CATEGORY_FILTER, PROVIDER_FILTER
+from .constants import COUNTRY_FILTER, CATEGORY_FILTER, PROVIDER_FILTER, PUBLIC_FILTER
 from .entity_repo import EntityRepository
 
 GEOGRAPHY_TYPE = 'geography'
 
 _GEOGRAPHY_ID_FIELD = 'id'
 _GEOGRAPHY_SLUG_FIELD = 'slug'
-_ALLOWED_FILTERS = [COUNTRY_FILTER, CATEGORY_FILTER, PROVIDER_FILTER]
+_ALLOWED_FILTERS = [COUNTRY_FILTER, CATEGORY_FILTER, PROVIDER_FILTER, PUBLIC_FILTER]
 
 
 def get_geography_repo():
diff --git a/cartoframes/io/managers/context_manager.py b/cartoframes/io/managers/context_manager.py
index 67b28679..c0b440a2 100644
--- a/cartoframes/io/managers/context_manager.py
+++ b/cartoframes/io/managers/context_manager.py
@@ -179,7 +179,7 @@ class ContextManager:
 
     def get_table_names(self, query):
         # Used to detect tables in queries in the publication.
-        query = 'SELECT CDB_QueryTablesText($q${}$q$) as tables'.format(query)
+        query = 'SELECT CDB_QueryTablesText(\'{}\') as tables'.format(query)
         result = self.execute_query(query)
         tables = []
         if result['total_rows'] > 0 and result['rows'][0]['tables']:


Test patch:
diff --git a/tests/unit/data/observatory/catalog/test_catalog.py b/tests/unit/data/observatory/catalog/test_catalog.py
index 306354f0..087ae50b 100644
--- a/tests/unit/data/observatory/catalog/test_catalog.py
+++ b/tests/unit/data/observatory/catalog/test_catalog.py
@@ -11,7 +11,7 @@ from cartoframes.data.observatory.catalog.catalog import Catalog
 from cartoframes.data.observatory.catalog.subscriptions import Subscriptions
 from cartoframes.data.observatory.catalog.repository.geography_repo import GeographyRepository
 from cartoframes.data.observatory.catalog.repository.constants import (
-    CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER
+    CATEGORY_FILTER, COUNTRY_FILTER, GEOGRAPHY_FILTER, PUBLIC_FILTER
 )
 from .examples import (
     test_country2, test_country1, test_category1, test_category2, test_dataset1, test_dataset2,
@@ -70,7 +70,7 @@ class TestCatalog(object):
         countries = catalog.category('demographics').countries
 
         # Then
-        mocked_countries.called_once_with({CATEGORY_FILTER: 'demographics'})
+        mocked_countries.assert_called_once_with({CATEGORY_FILTER: 'demographics'})
         assert countries == test_countries
 
     @patch.object(Category, 'get_all')
@@ -83,7 +83,7 @@ class TestCatalog(object):
         categories = catalog.country('usa').categories
 
         # Then
-        mocked_categories.called_once_with({COUNTRY_FILTER: 'usa'})
+        mocked_categories.assert_called_once_with({COUNTRY_FILTER: 'usa'})
         assert categories == test_categories
 
     @patch.object(Dataset, 'get_all')
@@ -96,7 +96,7 @@ class TestCatalog(object):
         datasets = catalog.country('usa').category('demographics').datasets
 
         # Then
-        mocked_datasets.called_once_with({COUNTRY_FILTER: 'usa', CATEGORY_FILTER: 'demographics'})
+        mocked_datasets.assert_called_once_with({COUNTRY_FILTER: 'usa', CATEGORY_FILTER: 'demographics'})
         assert datasets == test_datasets
 
     @patch.object(Geography, 'get_all')
@@ -109,9 +109,65 @@ class TestCatalog(object):
         geographies = catalog.country('usa').category('demographics').geographies
 
         # Then
-        mocked_geographies.called_once_with({COUNTRY_FILTER: 'usa', CATEGORY_FILTER: 'demographics'})
+        mocked_geographies.assert_called_once_with({COUNTRY_FILTER: 'usa', CATEGORY_FILTER: 'demographics'})
         assert geographies == test_geographies
 
+    @patch.object(Dataset, 'get_all')
+    def test_filters_public_datasets(self, mocked_datasets):
+        # Given
+        expected_datasets = [test_dataset1, test_dataset2]
+        mocked_datasets.return_value = expected_datasets
+        catalog = Catalog()
+
+        # When
+        datasets = catalog.public().datasets
+
+        # Then
+        mocked_datasets.assert_called_once_with({PUBLIC_FILTER: 'true'})
+        assert datasets == expected_datasets
+
+    @patch.object(Geography, 'get_all')
+    def test_filters_public_geographies(self, mocked_geographies):
+        # Given
+        expected_geographies = [test_geography1, test_geography2]
+        mocked_geographies.return_value = expected_geographies
+        catalog = Catalog()
+
+        # When
+        geographies = catalog.public().geographies
+
+        # Then
+        mocked_geographies.assert_called_once_with({PUBLIC_FILTER: 'true'})
+        assert geographies == expected_geographies
+
+    @patch.object(Dataset, 'get_all')
+    def test_filters_private_datasets(self, mocked_datasets):
+        # Given
+        expected_datasets = [test_dataset1, test_dataset2]
+        mocked_datasets.return_value = expected_datasets
+        catalog = Catalog()
+
+        # When
+        datasets = catalog.public(False).datasets
+
+        # Then
+        mocked_datasets.assert_called_once_with({PUBLIC_FILTER: 'false'})
+        assert datasets == expected_datasets
+
+    @patch.object(Geography, 'get_all')
+    def test_filters_private_geographies(self, mocked_geographies):
+        # Given
+        expected_geographies = [test_geography1, test_geography2]
+        mocked_geographies.return_value = expected_geographies
+        catalog = Catalog()
+
+        # When
+        geographies = catalog.public(False).geographies
+
+        # Then
+        mocked_geographies.assert_called_once_with({PUBLIC_FILTER: 'false'})
+        assert geographies == expected_geographies
+
     @patch.object(Dataset, 'get_all')
     def test_all_filters(self, mocked_datasets):
         # Given
@@ -119,13 +175,14 @@ class TestCatalog(object):
         catalog = Catalog()
 
         # When
-        datasets = catalog.country('usa').category('demographics') \
+        datasets = catalog.country('usa').category('demographics').public() \
             .geography('carto-do-public-data.tiger.geography_esp_census_2019').datasets
 
         # Then
-        mocked_datasets.called_once_with({
+        mocked_datasets.assert_called_once_with({
             COUNTRY_FILTER: 'usa',
             CATEGORY_FILTER: 'demographics',
+            PUBLIC_FILTER: 'true',
             GEOGRAPHY_FILTER: 'carto-do-public-data.tiger.geography_esp_census_2019'})
 
         assert datasets == test_datasets