Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed data/api_data-2019.01.22-v36-jef.xlsx
Binary file not shown.
Binary file added data/api_data-2019.10.02-v41-jef.xlsx
Binary file not shown.
3 changes: 2 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ serve-dev-network-accessible:
--capture-output \
--pythonpath python3
# serve-production: D="run in background, p="path to save file w/ process ID"
# Don't use -D on Heroku. Will result in H10 error with no details.
# Heroku: Don't use -D on Heroku. Will result in H10 error with no details.
# Heroku: Not necessary to set PORT env var. Heroku will do automatically
serve-production:
gunicorn -p pma-api_process-id.pid --bind 0.0.0.0:${PORT} run:app
connect-production:
Expand Down
32 changes: 23 additions & 9 deletions pma_api/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
class PmaApiException(Exception):
"""Base exception for package"""

# def __init__(self, *args: str, **kwargs):
# # kwargs appear in Exception def; not sure why Pycharm doesn't see
# # noinspection PyArgumentList
# super().__init__(*args, **kwargs)
def __init__(self, *args: str, **kwargs):
# kwargs appear in Exception def; not sure why Pycharm doesn't see
# noinspection PyArgumentList
super().__init__(*args, **kwargs)
# noinspection PyUnresolvedReferences
msg: str = \
self.__class__.__name__ + ': ' + self.__class__.msg \
if hasattr(self.__class__, 'msg') else ''
if args:
super().__init__(*args, **kwargs)
elif msg:
super().__init__(msg, **kwargs)
else:
super().__init__(*args, **kwargs)


class PmaApiDbInteractionError(PmaApiException):
Expand All @@ -18,13 +29,16 @@ class ExistingDatasetError(PmaApiDbInteractionError):
"""Dataset already exists in db"""


class MalformedApiDatasetError(PmaApiException):
"""Malformed Api Dataset Error"""
msg = 'The supplied file is either not a PMA API spec dataset file' \
', or is in some way malformed. Please make sure that the file is ' \
'conforms to the requirements for a PMA API spec dataset file as ' \
'described in the docs: http://api-docs.pma2020.org/content/' \
'data_managers/data_managers.html#pma-api-dataset-files'


class PmaApiTaskDenialError(PmaApiException):
"""Task denial exception"""
msg = 'There is currently a task actively running. A request to start a ' \
'new, concurrent task was made, but has been denied.'

def __init__(self, *args: str, **kwargs):
if args:
super().__init__(*args, **kwargs)
else:
super().__init__(PmaApiTaskDenialError.msg, **kwargs)
7 changes: 6 additions & 1 deletion pma_api/models/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# from sqlalchemy.exc import IntegrityError
from typing import List

from pma_api.error import MalformedApiDatasetError
from pma_api.models import ApiMetadata
from pma_api.config import ACCEPTED_DATASET_EXTENSIONS as EXTENSIONS, \
UI_DATASET_FILE_PREFIX as UI_PREFIX
Expand Down Expand Up @@ -45,11 +46,15 @@ def __init__(self, file_path: str, processing: bool = False):

self.dataset_display_name: str = filename_parts[0]
self.upload_date = datetime.date.today()
self.version_number: int = self.get_file_version(file_path)
self.dataset_type: str = 'full' # TODO: allow for different types
self.active: bool = False
self.processing: bool = processing

try:
self.version_number: int = self.get_file_version(file_path)
except IndexError:
raise MalformedApiDatasetError

# super(Dataset, self).__init__(
# data=open(file_path, 'rb').read(),
# dataset_display_name=dataset_display_name,
Expand Down
12 changes: 8 additions & 4 deletions pma_api/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ def filter_readable(
survey_codes: str,
indicator_code: str,
char_grp_code: str,
lang=None):
lang=None
):
"""Get filtered Datalab data and return readable columns.

Args:
Expand Down Expand Up @@ -195,7 +196,8 @@ def filter_minimal(
survey_codes: str,
indicator_code: str,
char_grp_code: str,
over_time) -> List[Dict]:
over_time
) -> List[Dict]:
"""Get filtered Datalab data and return minimal columns.

Args:
Expand Down Expand Up @@ -559,6 +561,7 @@ def init_indicators():
joined = DatalabData.all_joined(select_args)
ordered = joined.order_by(Indicator.order)
results = ordered.distinct().all()

indicator_categories = []
for ind in results:
for cat in indicator_categories:
Expand All @@ -579,12 +582,13 @@ def init_char_grp():
joined = DatalabData.all_joined(select_args)
ordered = joined.order_by(DatalabData.char_grp1.order)
results = ordered.distinct().all()

chargrp_categories = []
for char_grp in results:
for cat in chargrp_categories:
if char_grp.category.code == cat['label.id']:
cat['characteristicGroups'].append(char_grp.
datalab_init_json())
cat['characteristicGroups'].append(
char_grp.datalab_init_json())
break
else:
chargrp_categories.append({
Expand Down
5 changes: 3 additions & 2 deletions pma_api/routes/administration.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
from werkzeug.datastructures import ImmutableDict
from werkzeug.utils import secure_filename

from pma_api.error import ExistingDatasetError, PmaApiTaskDenialError
from pma_api.error import ExistingDatasetError, PmaApiTaskDenialError, \
MalformedApiDatasetError
from pma_api.routes import root


Expand Down Expand Up @@ -53,7 +54,7 @@ def admin_route():
filename = secure_filename(file.filename)
file_url: str = upload_dataset(filename=filename, file=file)
return jsonify({'success': bool(file_url)})
except ExistingDatasetError as err:
except (MalformedApiDatasetError, ExistingDatasetError) as err:
return jsonify({'success': False, 'message': str(err)})
except Exception as err:
msg = 'An unexpected error occurred.\n' + \
Expand Down
6 changes: 3 additions & 3 deletions pma_api/routes/endpoints/api_1_0/dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
}


def models_to_dicts(models: [Model], ignores: () = IGNORES) -> [Dict]:
def models_to_dicts(models: List[Model], ignores: () = IGNORES) -> List[Dict]:
"""Converts list of SqlAlchemy Model objects to dictionaries

Args:
Expand Down Expand Up @@ -87,7 +87,7 @@ def dynamic_route(resource: str) -> Union[QuerySetApiResult, str]:
msg = '<br/>'.join([msg_404, resource_h1, resources])
return msg

objects: [Model] = model.query.all()
objects: List[Model] = model.query.all()

if not request.args:
dict_objs: [{}] = models_to_dicts(objects)
Expand Down Expand Up @@ -115,7 +115,7 @@ def dynamic_route(resource: str) -> Union[QuerySetApiResult, str]:
file.write(txt)
# noinspection PyUnresolvedReferences
from pma_api.python_query_tempfile import interpolated_query
filtered_objs: [Model] = interpolated_query(objects)
filtered_objs: List[Model] = interpolated_query(objects)
os.remove(query_tempfile_path)

dict_objs: [{}] = models_to_dicts(filtered_objs)
Expand Down
Loading