# Path: pydatajson/helpers.py
# def clean_str(s):
#     replacements = {"á": "a", "é": "e", "í": "i", "ó": "o", "ú": "u",
#                     ":": "", ".": ""}
#     for old, new in iteritems(replacements):
#         s = s.replace(old, new)
#     return s.lower().strip()
# 
# def title_to_name(title, decode=True, max_len=None, use_complete_words=True):
#     """Convierte un título en un nombre normalizado para generar urls."""
#     # decodifica y pasa a minúsculas
#     if decode:
#         title = unidecode(title)
#     title = title.lower()
# 
#     # remueve caracteres no permitidos
#     filtered_title = re.sub(r'[^a-z0-9- ]+', '', title)
# 
#     # remueve stop words y espacios y une palabras sólo con un "-"
#     normalized_title = '-'.join([word for word in filtered_title.split()
#                                  if word not in STOP_WORDS])
# 
#     # recorto el titulo normalizado si excede la longitud máxima
#     if max_len and len(normalized_title) > max_len:
# 
#         # busco la última palabra completa
#         if use_complete_words:
#             last_word_index = normalized_title.rindex("-", 0, max_len)
#             normalized_title = normalized_title[:last_word_index]
# 
#         # corto en el último caracter
#         else:
#             normalized_title = normalized_title[:max_len]
# 
#     return normalized_title
# 
# Path: pydatajson/custom_exceptions.py
# class NonParseableCatalog(ValueError):
#     """No se puede leer un data.json a partir del parámetro pasado"""
#     def __init__(self, catalog, error):
#         msg = "Error parseando el datajson {}: {}".format(catalog, error)
#         super(NonParseableCatalog, self).__init__(msg)


import os.path
import logging
import json
import time
import urllib3
from six.moves.urllib_parse import urljoin
from six import iteritems
from requests.exceptions import RequestException
from ckanapi import RemoteCKAN
from ckanapi.errors import CKANAPIError
from .helpers import clean_str, title_to_name
from .custom_exceptions import NonParseableCatalog
        packages = []
        num_packages = len(packages_list)
        for index, pkg in enumerate(packages_list):
            # progreso (necesario cuando son muchos)
            msg = "Leyendo dataset {} de {}".format(index + 1, num_packages)
            logger.info(msg)

            # agrega un nuevo dataset a la lista
            packages.append(portal.call_action(
                'package_show', {'id': pkg},
                requests_kwargs={"verify": False}
            ))

            # tiempo de espera padra evitar baneos
            time.sleep(0.2)

        # itera leyendo todos los temas del portal
        groups = [portal.call_action(
            'group_show', {'id': grp},
            requests_kwargs={"verify": False})
            for grp in groups_list]

        catalog = map_status_to_catalog(status)
        catalog["dataset"] = map_packages_to_datasets(
            packages, portal_url)
        catalog["themeTaxonomy"] = map_groups_to_themes(groups)

    except (CKANAPIError, RequestException) as e:
        logger.exception(
            'Error al procesar el portal %s', portal_url, exc_info=True)

# Path: pydatajson/helpers.py
# def clean_str(s):
#     replacements = {"á": "a", "é": "e", "í": "i", "ó": "o", "ú": "u",
#                     ":": "", ".": ""}
#     for old, new in iteritems(replacements):
#         s = s.replace(old, new)
#     return s.lower().strip()
# 
# def title_to_name(title, decode=True, max_len=None, use_complete_words=True):
#     """Convierte un título en un nombre normalizado para generar urls."""
#     # decodifica y pasa a minúsculas
#     if decode:
#         title = unidecode(title)
#     title = title.lower()
# 
#     # remueve caracteres no permitidos
#     filtered_title = re.sub(r'[^a-z0-9- ]+', '', title)
# 
#     # remueve stop words y espacios y une palabras sólo con un "-"
#     normalized_title = '-'.join([word for word in filtered_title.split()
#                                  if word not in STOP_WORDS])
# 
#     # recorto el titulo normalizado si excede la longitud máxima
#     if max_len and len(normalized_title) > max_len:
# 
#         # busco la última palabra completa
#         if use_complete_words:
#             last_word_index = normalized_title.rindex("-", 0, max_len)
#             normalized_title = normalized_title[:last_word_index]
# 
#         # corto en el último caracter
#         else:
#             normalized_title = normalized_title[:max_len]
# 
#     return normalized_title
# 
# Path: pydatajson/custom_exceptions.py
# class NonParseableCatalog(ValueError):
#     """No se puede leer un data.json a partir del parámetro pasado"""
#     def __init__(self, catalog, error):
#         msg = "Error parseando el datajson {}: {}".format(catalog, error)
#         super(NonParseableCatalog, self).__init__(msg)


# Path: pydatajson/ckan_reader.py
import os.path
import logging
import json
import time
import urllib3
from six.moves.urllib_parse import urljoin
from six import iteritems
from requests.exceptions import RequestException
from ckanapi import RemoteCKAN
from ckanapi.errors import CKANAPIError
from .helpers import clean_str, title_to_name
from .custom_exceptions import NonParseableCatalog

        packages = []
        num_packages = len(packages_list)
        for index, pkg in enumerate(packages_list):
            # progreso (necesario cuando son muchos)
            msg = "Leyendo dataset {} de {}".format(index + 1, num_packages)
            logger.info(msg)

            # agrega un nuevo dataset a la lista
            packages.append(portal.call_action(
                'package_show', {'id': pkg},
                requests_kwargs={"verify": False}
            ))

            # tiempo de espera padra evitar baneos
            time.sleep(0.2)

        # itera leyendo todos los temas del portal
        groups = [portal.call_action(
            'group_show', {'id': grp},
            requests_kwargs={"verify": False})
            for grp in groups_list]

        catalog = map_status_to_catalog(status)
        catalog["dataset"] = map_packages_to_datasets(
            packages, portal_url)
        catalog["themeTaxonomy"] = map_groups_to_themes(groups)

    except (CKANAPIError, RequestException) as e:
        logger.exception(
            'Error al procesar el portal %s', portal_url, exc_info=True)

        raise NonParseableCatalog(portal_url, e)