Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

209 get organizations from ckan #210

Merged
merged 4 commits into from
Oct 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/MANUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,15 @@ Toma los siguientes parámetros:
portal de destino. Si no se pasa, se toma como organización el catalog_id

Retorna el id en el nodo de destino de los datasets federados.

### Métodos para manejo de organizaciones

- **pydatajson.federation.get_organizations_from_ckan()**: Devuelve el árbol de organizaciones del portal pasado por parámetro.
Toma los siguientes parámetros:
- **portal_url**: URL del portal de CKAN. Debe implementar el endpoint `/group_tree`.

Retorna una lista de diccionarios con la información de las organizaciones. Recursivamente, dentro del campo `children`,
se encuentran las organizaciones dependientes en la jerarquía.

## Anexo I: Estructura de respuestas

Expand Down
14 changes: 14 additions & 0 deletions pydatajson/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,3 +300,17 @@ def push_new_themes(catalog, portal_url, apikey):
catalog, portal_url, apikey, identifier=new_theme)
pushed_names.append(name)
return pushed_names


def get_organizations_from_ckan(portal_url):
"""Toma la url de un portal y devuelve su árbol de organizaciones.

Args:
portal_url (str): La URL del portal CKAN de origen.
Returns:
dict: Diccionarios anidados con la información de
las organizaciones.
"""
ckan_portal = RemoteCKAN(portal_url)
return ckan_portal.call_action('group_tree',
data_dict={'type': 'organization'})
50 changes: 19 additions & 31 deletions tests/test_federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@
SAMPLES_DIR = os.path.join("tests", "samples")


class PushDatasetTestCase(unittest.TestCase):

class FederationSuite(unittest.TestCase):
@classmethod
def get_sample(cls, sample_filename):
return os.path.join(SAMPLES_DIR, sample_filename)


@patch('pydatajson.federation.RemoteCKAN', autospec=True)
class PushDatasetTestCase(FederationSuite):

@classmethod
def setUpClass(cls):
cls.catalog = pydatajson.DataJson(cls.get_sample('full_data.json'))
Expand All @@ -43,7 +46,6 @@ def setUpClass(cls):
cls.minimum_dataset['distribution'][0][
'identifier'] = cls.dataset['distribution'][0]['identifier']

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_id_is_created_correctly(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -62,7 +64,6 @@ def mock_call_action(action, data_dict=None):
catalog_id=self.catalog_id)
self.assertEqual(self.catalog_id + '_' + self.dataset_id, res_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_id_is_updated_correctly(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -81,7 +82,6 @@ def mock_call_action(action, data_dict=None):
catalog_id=self.catalog_id)
self.assertEqual(self.catalog_id + '_' + self.dataset_id, res_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_dataset_id_is_preserved_if_catalog_id_is_not_passed(
self, mock_portal):
def mock_call_action(action, data_dict=None):
Expand All @@ -97,7 +97,6 @@ def mock_call_action(action, data_dict=None):
'portal', 'key')
self.assertEqual(self.dataset_id, res_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_tags_are_passed_correctly(self, mock_portal):
themes = self.dataset['theme']
keywords = [kw for kw in self.dataset['keyword']]
Expand Down Expand Up @@ -132,7 +131,6 @@ def mock_call_action(action, data_dict=None):
catalog_id=self.catalog_id)
self.assertEqual(self.catalog_id + '_' + self.dataset_id, res_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_licenses_are_interpreted_correctly(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'license_list':
Expand All @@ -149,7 +147,6 @@ def mock_call_action(action, data_dict=None):
push_dataset_to_ckan(self.catalog, 'owner', self.dataset_id,
'portal', 'key', catalog_id=self.catalog_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_dataset_without_license_sets_notspecified(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'license_list':
Expand All @@ -172,7 +169,6 @@ def mock_call_action(action, data_dict=None):
'key',
catalog_id=self.minimum_catalog_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_dataset_level_wrappers(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -192,7 +188,6 @@ def mock_call_action(action, data_dict=None):
self.assertEqual(self.dataset_id, restored_id)
self.assertEqual(self.catalog_id + '_' + self.dataset_id, harvested_id)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_harvest_catalog_with_no_optional_parametres(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -218,7 +213,6 @@ def mock_call_action(action, data_dict=None):
for ds in self.catalog.datasets],
harvested_ids)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_harvest_catalog_with_dataset_list(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand Down Expand Up @@ -254,7 +248,6 @@ def mock_call_action(action, data_dict=None):
[self.catalog_id + '_' + ds_id for ds_id in dataset_list],
harvested_ids)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_harvest_catalog_with_owner_org(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -275,7 +268,6 @@ def mock_call_action(action, data_dict=None):
for ds in self.catalog.datasets],
harvested_ids)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_harvest_catalog_with_errors(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'package_update':
Expand All @@ -292,7 +284,6 @@ def mock_call_action(action, data_dict=None):
self.assertDictEqual(
{self.catalog.datasets[1]['identifier']: "some message"}, errors)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_harvest_catalog_with_empty_list(self, mock_portal):
harvested_ids, _ = harvest_catalog_to_ckan(
self.catalog, 'portal', 'key', self.catalog_id,
Expand All @@ -301,7 +292,7 @@ def test_harvest_catalog_with_empty_list(self, mock_portal):
self.assertEqual([], harvested_ids)


class RemoveDatasetTestCase(unittest.TestCase):
class RemoveDatasetTestCase(FederationSuite):

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_empty_search_doesnt_call_purge(self, mock_portal):
Expand Down Expand Up @@ -378,22 +369,17 @@ def test_remove_through_filters_and_organization(
'dataset_purge', data_dict={'id': 'id_2'})


class PushThemeTestCase(unittest.TestCase):

@classmethod
def get_sample(cls, sample_filename):
return os.path.join(SAMPLES_DIR, sample_filename)
@patch('pydatajson.federation.RemoteCKAN', autospec=True)
class PushThemeTestCase(FederationSuite):

@classmethod
def setUpClass(cls):
cls.catalog = pydatajson.DataJson(cls.get_sample('full_data.json'))

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_empty_theme_search_raises_exception(self, mock_portal):
with self.assertRaises(AssertionError):
push_theme_to_ckan(self.catalog, 'portal_url', 'apikey')

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_function_pushes_theme_by_identifier(self, mock_portal):
mock_portal.return_value.call_action = MagicMock(
return_value={'name': 'group_name'})
Expand All @@ -404,7 +390,6 @@ def test_function_pushes_theme_by_identifier(self, mock_portal):
identifier='compras')
self.assertEqual('group_name', result)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_function_pushes_theme_by_label(self, mock_portal):
mock_portal.return_value.call_action = MagicMock(
return_value={'name': 'other_name'})
Expand All @@ -415,7 +400,6 @@ def test_function_pushes_theme_by_label(self, mock_portal):
label='Adjudicaciones')
self.assertEqual('other_name', result)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_ckan_portal_is_called_with_correct_parametres(self, mock_portal):
mock_portal.return_value.call_action = MagicMock(
return_value={'name': u'contrataciones'})
Expand All @@ -431,16 +415,13 @@ def test_ckan_portal_is_called_with_correct_parametres(self, mock_portal):
'group_create', data_dict=group)


class PushCatalogThemesTestCase(unittest.TestCase):
@classmethod
def get_sample(cls, sample_filename):
return os.path.join(SAMPLES_DIR, sample_filename)
@patch('pydatajson.federation.RemoteCKAN', autospec=True)
class PushCatalogThemesTestCase(FederationSuite):

@classmethod
def setUpClass(cls):
cls.catalog = pydatajson.DataJson(cls.get_sample('full_data.json'))

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_empty_portal_pushes_every_theme(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'group_list':
Expand All @@ -461,7 +442,6 @@ def mock_call_action(action, data_dict=None):
[theme['id'] for theme in self.catalog['themeTaxonomy']],
res_names)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_full_portal_pushes_nothing(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'group_list':
Expand All @@ -476,7 +456,6 @@ def mock_call_action(action, data_dict=None):
except AttributeError:
self.assertCountEqual([], res_names)

@patch('pydatajson.federation.RemoteCKAN', autospec=True)
def test_non_empty_intersection_pushes_missing_themes(self, mock_portal):
def mock_call_action(action, data_dict=None):
if action == 'group_list':
Expand All @@ -497,3 +476,12 @@ def mock_call_action(action, data_dict=None):
self.assertCountEqual(
[theme['id'] for theme in self.catalog['themeTaxonomy']][2:],
res_names)


@patch('pydatajson.federation.RemoteCKAN', autospec=True)
class OrganizationsTestCase(FederationSuite):

def test_get_organization_calls_api_correctly(self, mock_portal):
get_organizations_from_ckan('portal_url')
mock_portal.return_value.call_action.assert_called_with(
'group_tree', data_dict={'type': 'organization'})