From 5dfbe9b97ea3d1a2035273d9aaa1faa7dff15ef0 Mon Sep 17 00:00:00 2001 From: Lee Zeman Date: Wed, 15 Sep 2021 17:10:17 -0700 Subject: [PATCH 01/71] Start update to python 3 --- deploy_requirements.txt | 3 ++- pdp/__init__.py | 3 ++- pdp/error.py | 24 ++++++++++-------- pdp/main.py | 20 +++++++-------- pdp/portals/__init__.py | 1 + requirements.txt | 38 +++++++++++++++------------- scripts/gevent_serve.py | 3 ++- scripts/gevent_serve_multiprocess.py | 3 ++- setup.py | 6 +---- tests/test_error.py | 8 +++--- tests/test_functional.py | 14 +++++----- tests/test_hdf5.py | 11 +++++++- 12 files changed, 76 insertions(+), 58 deletions(-) diff --git a/deploy_requirements.txt b/deploy_requirements.txt index 8c2e6ceb..44375188 100644 --- a/deploy_requirements.txt +++ b/deploy_requirements.txt @@ -11,6 +11,7 @@ pyparsing==2.4.7 snowballstemmer==2.1.0 Sphinx==1.8.5 sphinxcontrib-websupport==1.1.2 -typing==3.10.0.0 +# typing==3.10.0.0 removed for version nonexistence +typing zope.event==4.5.0 zope.interface==5.4.0 diff --git a/pdp/__init__.py b/pdp/__init__.py index d3cfbfdd..8e202a91 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -32,6 +32,7 @@ def get_config_from_environment(): 'data_root': 'http://tools.pacificclimate.org/dataportal/data', 'title': '', 'ensemble_name': '', + 'thredds_root': 'http://docker-dev03.pcic.uvic.ca:30333/data', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', 'js_min': 'False', @@ -107,7 +108,7 @@ def parse_version(type_): def _parse_version(full_version, type_): - regex = ur"^((?:\w+\.?)+)\+?(.*)\.(\w{6})$" + regex = r"^((?:\w+\.?)+)\+?(.*)\.(\w{6})$" matches = re.match(regex, full_version) if matches: version, branch, sha = matches.groups() diff --git a/pdp/error.py b/pdp/error.py index 4d2ffb3f..61242971 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -29,9 +29,9 @@ def __call__(self, environ, start_response): ("Retry-After", "3600") # one hour ] start_response(status, response_headers, sys.exc_info()) - logger.error("SQLAlchemyError: {}".format(e.message)) - yield 'There was an unexpected problem accessing the database\n' - yield e.message + logger.error("SQLAlchemyError: {}".format(e.args[0])) + yield b'There was an unexpected problem accessing the database\n' + yield e.args[0].encode() except EnvironmentError as e: # except IOError as e: @@ -48,9 +48,9 @@ def __call__(self, environ, start_response): " strerr: {}\n" " filename {}\n" "{}".format( - e.errno, e.strerror, e.filename, e.message)) + e.errno, e.strerror, e.filename, e.args[0])) yield 'We had an unexpected problem accessing on-disk resources\n' - yield e.message + yield e.args[0] except Exception as e: status = "500 Internal Server Error" @@ -58,11 +58,15 @@ def __call__(self, environ, start_response): start_response(status, response_headers, sys.exc_info()) logger.error("500 Internal Server Error: {}\n{}".format( e.args, traceback.format_exc())) - yield 'There was an unhandleable problem with the application\n' - yield e.message + yield b'There was an unhandleable problem with the application\n' + yield e.args[0] else: - + print("start_response is") + print(start_response) + print("response_iter is") + print(response_iter) + print(type(response_iter)) # Catch error that happen while generating a streamed response try: for block in response_iter: @@ -72,8 +76,8 @@ def __call__(self, environ, start_response): status = "500 Internal Server Error" response_headers = [("content-type", "text/plain")] start_response(status, response_headers, sys.exc_info()) - yield "There was a serious problem while generating the "\ - "streamed response\n{}\n".format(e.args) + yield b"There was a serious problem while generating the "\ + b"streamed response\n{}\n".format(e.args) yield traceback.format_exc() msg = "Exception raised during streamed response: {}\n{}"\ .format(e.args, traceback.format_exc()) diff --git a/pdp/main.py b/pdp/main.py index 9adeb76c..3c0bcc27 100644 --- a/pdp/main.py +++ b/pdp/main.py @@ -9,18 +9,18 @@ from ga_wsgi_client import AnalyticsMiddleware # Station portals -import portals.pcds as pcds -import portals.hydro_stn_archive as hydro_stn_archive -import portals.hydro_stn_cmip5 as hydro_stn_cmip5 +import pdp.portals.pcds as pcds +import pdp.portals.hydro_stn_archive as hydro_stn_archive +import pdp.portals.hydro_stn_cmip5 as hydro_stn_cmip5 # Raster portals -import portals.bc_prism as bc_prism -import portals.downscale_archive as downscale_archive -import portals.bccaq2_downscale as bccaq2 -import portals.bccaq_extremes as bccaq_extremes -import portals.gridded_observations as gridded_observations -import portals.vic_gen1 as vic_gen1 -import portals.vic_gen2 as vic_gen2 +import pdp.portals.bc_prism as bc_prism +import pdp.portals.downscale_archive as downscale_archive +import pdp.portals.bccaq2_downscale as bccaq2 +import pdp.portals.bccaq_extremes as bccaq_extremes +import pdp.portals.gridded_observations as gridded_observations +import pdp.portals.vic_gen1 as vic_gen1 +import pdp.portals.vic_gen2 as vic_gen2 apps = (bc_prism, downscale_archive, bccaq2, vic_gen1, vic_gen2, diff --git a/pdp/portals/__init__.py b/pdp/portals/__init__.py index 72fcc07f..1a13b517 100644 --- a/pdp/portals/__init__.py +++ b/pdp/portals/__init__.py @@ -29,6 +29,7 @@ def raster_conf(dsn, global_config, ensemble_name, data_base=None): sesh, "Download Data", 0.1, 0, ensemble_name, root_url=root_url ) + conf["thredds_root"] = global_config["thredds_root"] return conf diff --git a/requirements.txt b/requirements.txt index 7cdaa852..f3dd040f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,7 +16,7 @@ funcsigs==1.0.2 ga-wsgi-client==0.1 # pre-installed #GDAL==2.2.0 -Genshi==0.7 +# Genshi==0.7 removed for conflict GeoAlchemy==0.7.3 GeoAlchemy2==0.9.1 gitdb2==2.0.6 @@ -33,48 +33,50 @@ Mako==1.1.4 MarkupSafe==1.0 modelmeta==0.3.0 nchelpers==5.5.7 -netCDF4==1.5.5.1 +#netCDF4==1.5.5.1 removed for conflict # pre-installed # numpy==1.16.6 olefile==0.46 openid2rp==1.12 Paste==2.0.3 -pdp-util==1.2.1 +pdp-util==2.1.0 Pillow==4.3.0 ply==3.10 -psycopg2==2.7.3.2 -pupynere-pdp==1.1.6 +# psycopg2==2.7.3.2 removed as an experiment +psycopg2 +# pupynere-pdp==1.1.6 removed for conflict PyCDS==2.2.1 PyCRS==1.0.2 pycrypto==2.6.1 -pydap-pdp==3.2.6 -pydap.handlers.csv==0.3 -pydap.handlers.hdf5==0.5.2 -pydap.handlers.pcic==0.0.11 -pydap.handlers.sql==0.10 -pydap.responses.aaigrid==0.7 -pydap.responses.html==0.3 -pydap.responses.netcdf==0.6.0 -pydap.responses.xlsx==0.1 +#pydap-pdp==3.2.6 +#pydap.handlers.csv==0.3 +#pydap.handlers.hdf5==0.5.2 +#pydap.handlers.pcic==0.0.11 +#pydap.handlers.sql==0.10 +#pydap.responses.aaigrid==0.7 +#pydap.responses.html==0.3 +#pydap.responses.netcdf==0.6.0 +#pydap.responses.xlsx==0.1 # We use Ubuntu package; ver 3.26.1 not avail from pypi.org #pygobject==3.26.1 pystache==0.5.4 python-dateutil==2.6.1 python-editor==1.0.4 pytz==2017.3 -PyYAML==5.4 -requests==2.21.0 +# PyYAML==5.4 removed for conflict +# requests==2.21.0 removed for conflict SecretStorage==2.3.1 simplejson==3.12.0 six==1.11.0 slimit==0.8.1 smmap==3.0.5 smmap2==3.0.1 -SQLAlchemy==1.3.0 +# SQLAlchemy==1.3.0 removed for conflict +SQLAlchemy==1.4.3 #added for pydap-extras sqlparse==0.3.1 static==1.1.1 urllib3==1.26.5 WebOb==1.7.3 Werkzeug==0.15.3 -XlsxWriter==1.0.2 +# XlsxWriter==1.0.2 removed for conflict xlwt==1.3.0 diff --git a/scripts/gevent_serve.py b/scripts/gevent_serve.py index cc9e31ed..eaaaf286 100644 --- a/scripts/gevent_serve.py +++ b/scripts/gevent_serve.py @@ -1,3 +1,4 @@ +#Note: this script's update to python 3 has not been tested import sys from argparse import ArgumentParser from logging import basicConfig, DEBUG @@ -22,6 +23,6 @@ basicConfig(format='%(levelname)s:%(name)s:%(asctime)s %(message)s', stream=sys.stdout, level=DEBUG) - print 'Starting server on port {}'.format(args.port) + print('Starting server on port {}'.format(args.port)) server = pywsgi.WSGIServer(('0.0.0.0', args.port), dev_server) server.serve_forever() diff --git a/scripts/gevent_serve_multiprocess.py b/scripts/gevent_serve_multiprocess.py index 0be4ea18..e7a10e20 100644 --- a/scripts/gevent_serve_multiprocess.py +++ b/scripts/gevent_serve_multiprocess.py @@ -1,3 +1,4 @@ +#Note: this script's update to python 3 has not been tested import sys from argparse import ArgumentParser from multiprocessing import Process, cpu_count @@ -47,5 +48,5 @@ def serve_forever(listener): for i in range(num_proc): Process(target=serve_forever, args=(listener, )).start() - print 'Starting server on port {}'.format(args.port) + print('Starting server on port {}'.format(args.port)) serve_forever(listener) diff --git a/setup.py b/setup.py index fb72f7e4..39de41ab 100644 --- a/setup.py +++ b/setup.py @@ -80,11 +80,7 @@ def get_commitish(): "static", "pdp-util >=1.2.1", "modelmeta >=0.3.0", - "pydap.handlers.hdf5 >=0.5", - "pydap.responses.netcdf >=0.5", - "pydap.responses.xls", - "pydap.responses.aaigrid >=0.5", - "pydap.handlers.sql", + "pydap_extras >= 0.2.1", "ga-wsgi-client", "slimit", "netCDF4<1.5.6", diff --git a/tests/test_error.py b/tests/test_error.py index 6bfcad98..ea331253 100644 --- a/tests/test_error.py +++ b/tests/test_error.py @@ -35,7 +35,7 @@ def my_iterable(): def error_instantiating_app(environ, start_response): - raise Exception("Foo", "Bar") + raise Exception(b"Foo", b"Bar") start_response('200 OK', []) return ["We'll never get", "here"] @@ -46,7 +46,7 @@ def test_operational_error(): resp = req.get_response(app, catch_exc_info=True) assert resp.status_code == 503 assert 'Retry-After' in resp.headers - assert 'accessing the database' in resp.body + assert b'accessing the database' in resp.body def test_io_error(): @@ -64,7 +64,7 @@ def test_stream_error(): assert resp.status_code == 500 for x in resp.app_iter: - print x + print(x) def test_500(): @@ -73,7 +73,7 @@ def test_500(): resp = req.get_response(app, catch_exc_info=True) assert resp.status_code == 500 - assert "There was an unhandleable problem with the application" \ + assert b"There was an unhandleable problem with the application" \ in resp.body diff --git a/tests/test_functional.py b/tests/test_functional.py index a0f2ccd6..447330c2 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -1,11 +1,10 @@ from datetime import datetime, timedelta -from urllib import urlencode +from urllib.parse import urlencode from tempfile import TemporaryFile, NamedTemporaryFile from zipfile import ZipFile import csv import json import os -from itertools import izip from pkg_resources import resource_filename import static @@ -64,8 +63,11 @@ def test_climo_index( resp = req.get_response(pcic_data_portal) assert resp.status == '200 OK' assert resp.content_type == 'text/html' - assert resp.content_length < 0 + #assert resp.content_length < 0 +# print("resp is") +# print("{}".format(resp)) +# sleep(3) soup = BeautifulSoup(resp.body, "html.parser") assert title in soup.title.string @@ -171,7 +173,7 @@ def test_nc_response_with_null_values(pcic_data_portal): @pytest.mark.crmpdb def test_clip_to_date_one(pcic_data_portal): base_url = '/data/pcds/agg/?' - sdate = datetime(2007, 01, 01) + sdate = datetime(2007, 1, 1) params = {'from-date': sdate.strftime('%Y/%m/%d'), 'network-name': 'RTA', 'data-format': 'csv', 'cliptodate': 'cliptodate', @@ -179,7 +181,7 @@ def test_clip_to_date_one(pcic_data_portal): req = Request.blank(base_url + urlencode(params)) resp = req.get_response(pcic_data_portal) - print resp.status + print(resp.status) assert resp.status == '200 OK' t = TemporaryFile() t.write(resp.body) @@ -200,7 +202,7 @@ def test_clip_to_date_one(pcic_data_portal): '2007-01-11 00:00:00', '2007-01-12 00:00:00', '2007-01-13 00:00:00'] - for exp, actual in izip(expected, reader): + for exp, actual in zip(expected, reader): assert exp[0] == actual # FIXME: These next two aren't actually going to work w/o firing up an diff --git a/tests/test_hdf5.py b/tests/test_hdf5.py index 03f50474..211f5633 100644 --- a/tests/test_hdf5.py +++ b/tests/test_hdf5.py @@ -15,10 +15,19 @@ def test_can_instantiate_raster_pydap(raster_pydap): @pytest.mark.bulk_data def test_hdf5_to_netcdf(pcic_data_portal): req = Request.blank( - '/data/downscaled_gcms_archive/pr+tasmax+tasmin_day_BCCAQ+' + '/downscaled_gcms_archive/pr+tasmax+tasmin_day_BCCAQ+' 'ANUSPLIN300+CCSM4_historical+rcp26_r2i1p1_19500101-' '21001231.nc.nc?pr[0:1:1][116:167][84:144]&') + +# https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets +# /downscaled_gcms_archive/pr+tasmax+tasmin_day_BCCAQ+ +# ANUSPLIN300+CCSM4_historical+rcp26_r2i1p1_19500101- +# 21001231.nc.html + print("req is") + print(req) resp = req.get_response(pcic_data_portal) + print("resp in test function is") + print(resp.body) assert resp.status == '200 OK' assert resp.content_type == 'application/x-netcdf' From ab3ca527358ddc41ca383bef8ee9a009cfae6ddb Mon Sep 17 00:00:00 2001 From: Lee Zeman Date: Thu, 24 Mar 2022 11:58:05 -0700 Subject: [PATCH 02/71] Update dockers to run python3 --- deploy_requirements.txt | 3 +- docker/local-run/Dockerfile | 4 +-- docker/local-run/entrypoint-be.sh | 2 +- docker/local-run/entrypoint-fe.sh | 2 +- docker/local-run/entrypoint.sh | 2 +- pdp/error.py | 58 ++++++++++++++++++++++++++----- pdp/main.py | 4 ++- pdp/portals/__init__.py | 2 +- pdp/portals/hydro_stn_archive.py | 2 +- pdp/portals/hydro_stn_cmip5.py | 2 +- pdp/portals/pcds.py | 2 +- pdp/wsgi.py | 2 +- requirements.txt | 50 ++++++++++---------------- tests/test_functional.py | 6 ++-- 14 files changed, 84 insertions(+), 57 deletions(-) diff --git a/deploy_requirements.txt b/deploy_requirements.txt index 44375188..5f3ed8ef 100644 --- a/deploy_requirements.txt +++ b/deploy_requirements.txt @@ -11,7 +11,6 @@ pyparsing==2.4.7 snowballstemmer==2.1.0 Sphinx==1.8.5 sphinxcontrib-websupport==1.1.2 -# typing==3.10.0.0 removed for version nonexistence -typing +typing==3.7.4.3 zope.event==4.5.0 zope.interface==5.4.0 diff --git a/docker/local-run/Dockerfile b/docker/local-run/Dockerfile index ec758fcb..9f437e9a 100644 --- a/docker/local-run/Dockerfile +++ b/docker/local-run/Dockerfile @@ -1,4 +1,4 @@ -FROM pcic/pdp-base-minimal:1.0.0 +FROM pcic/pdp-base-minimal:pdp-python3 LABEL Maintainer="Rod Glover " USER root @@ -14,6 +14,6 @@ USER ${USERNAME} WORKDIR /codebase ADD *requirements.txt /codebase/ -RUN pip install -r requirements.txt -r test_requirements.txt -r deploy_requirements.txt +RUN pip3 install -r requirements.txt -r test_requirements.txt -r deploy_requirements.txt ENTRYPOINT ./docker/local-run/entrypoint.sh \ No newline at end of file diff --git a/docker/local-run/entrypoint-be.sh b/docker/local-run/entrypoint-be.sh index 8bc07e53..6a289cfe 100755 --- a/docker/local-run/entrypoint-be.sh +++ b/docker/local-run/entrypoint-be.sh @@ -12,6 +12,6 @@ #pip install -e /home/rglover/code/pdp_util # *Always* do this. It's the whole point of this Docker setup. -pip install -e . +pip3 install -e . gunicorn --config docker/local-run/gunicorn.conf --log-config docker/local-run/logging.conf pdp.wsgi:backend diff --git a/docker/local-run/entrypoint-fe.sh b/docker/local-run/entrypoint-fe.sh index d63fbd1a..2f6acc75 100755 --- a/docker/local-run/entrypoint-fe.sh +++ b/docker/local-run/entrypoint-fe.sh @@ -12,6 +12,6 @@ #pip install -e /home/rglover/code/pdp_util # *Always* do this. It's the whole point of this Docker setup. -pip install -e . +pip3 install -e . gunicorn --config docker/local-run/gunicorn.conf --log-config docker/local-run/logging.conf pdp.wsgi:frontend diff --git a/docker/local-run/entrypoint.sh b/docker/local-run/entrypoint.sh index 12a1e393..d7346697 100755 --- a/docker/local-run/entrypoint.sh +++ b/docker/local-run/entrypoint.sh @@ -11,6 +11,6 @@ #pip install -e /home/rglover/code/pdp_util # *Always* do this. It's the whole point of this Docker setup. -pip install -e . +pip3 install -e . /bin/bash diff --git a/pdp/error.py b/pdp/error.py index 61242971..e0bedc00 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -1,6 +1,7 @@ import sys import logging import traceback +from webob.response import Response from sqlalchemy.exc import SQLAlchemyError @@ -62,22 +63,61 @@ def __call__(self, environ, start_response): yield e.args[0] else: - print("start_response is") - print(start_response) - print("response_iter is") - print(response_iter) - print(type(response_iter)) # Catch error that happen while generating a streamed response try: - for block in response_iter: - yield block + # in theory, this block should be receiving an iterable + # that can be stepped over and streamed to the browser. + # in practice, the upgrade to python 3 has resulted in + # the reception of non-iterable types. + # These ifs catch and convert the non-iterable + # objects for a graceful recovery, while logging an error + # message so that the coder can track down the source of + # the unexpected type. + # The else is the previous behaviour) + # So far the following types have been observed: + # * bytes - sometimes sent by the front end + # * strings - sometimes sent by backend API calls + # * Response objects - not yet clear who is sending these + # TODO: get everyone to send expected generators, + # remove this failsafe code. + if isinstance(response_iter, bytes): + print("Caught bytes where generator expected:") + print(response_iter) + yield response_iter + elif isinstance(response_iter, str): + print("caught string where generator expected:") + print(response_iter) + yield response_iter.encode() + elif isinstance(response_iter, Response): + print("caught Response where generator expected, status {}".format(response_iter.status_code)) + if response_iter.status_code == 301: + # this is a redirect to the ORCA server, provided + # by pdp_util's RasterServer. Send it on to the browser. + print("Sending ORCA redirect to the browser") + status = "301 Moved Permanently" + response_headers = [ + ("content-type", "text/plain"), + ("Location", response_iter.location) + ] + start_response(status, response_headers) + elif response_iter.status_code == 200: + for block in response_iter.iter_lines(): + print(block) + yield(block) + else: + print(response_iter.headers) + + else: + #received a generator, as expected. Send its data. + for block in response_iter: + yield block except Exception as e: status = "500 Internal Server Error" response_headers = [("content-type", "text/plain")] start_response(status, response_headers, sys.exc_info()) - yield b"There was a serious problem while generating the "\ - b"streamed response\n{}\n".format(e.args) + yield "There was a serious problem while generating the "\ + "streamed response\n{}\n".format(e.args).encode() yield traceback.format_exc() msg = "Exception raised during streamed response: {}\n{}"\ .format(e.args, traceback.format_exc()) diff --git a/pdp/main.py b/pdp/main.py index 3c0bcc27..d87cab2a 100644 --- a/pdp/main.py +++ b/pdp/main.py @@ -3,7 +3,7 @@ from pkg_resources import resource_filename import static -from werkzeug.wsgi import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp.error import ErrorMiddleware from ga_wsgi_client import AnalyticsMiddleware @@ -47,6 +47,7 @@ def initialize_frontend(global_config, use_analytics=False): wsgi_app = DispatcherMiddleware(static_app, mounts) + use_analytics = False if use_analytics: wsgi_app = AnalyticsMiddleware(wsgi_app, global_config['analytics']) return ErrorMiddleware(wsgi_app) @@ -63,6 +64,7 @@ def initialize_backend(global_config, use_analytics=False): static_app = static.Cling(resource_filename('pdp', 'static')) wsgi_app = DispatcherMiddleware(static_app, mounts) + use_analytics = False if use_analytics: wsgi_app = AnalyticsMiddleware(wsgi_app, global_config['analytics']) return ErrorMiddleware(wsgi_app) diff --git a/pdp/portals/__init__.py b/pdp/portals/__init__.py index 1a13b517..68594479 100644 --- a/pdp/portals/__init__.py +++ b/pdp/portals/__init__.py @@ -1,4 +1,4 @@ -from werkzeug import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util import session_scope from pdp_util.raster import db_raster_configurator, RasterServer, RasterCatalog diff --git a/pdp/portals/hydro_stn_archive.py b/pdp/portals/hydro_stn_archive.py index 525315b1..d93d1aae 100644 --- a/pdp/portals/hydro_stn_archive.py +++ b/pdp/portals/hydro_stn_archive.py @@ -13,7 +13,7 @@ directory. The two portals share a frontend, hydro_stn_app.''' from pkg_resources import resource_filename -from werkzeug import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util.map import MapApp from pydap.wsgi.app import DapServer diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index 32452d2e..5b5a4cfe 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -14,7 +14,7 @@ from pkg_resources import resource_filename -from werkzeug import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util.map import MapApp from pydap.wsgi.app import DapServer diff --git a/pdp/portals/pcds.py b/pdp/portals/pcds.py index 37aa7c6d..5ebcb238 100644 --- a/pdp/portals/pcds.py +++ b/pdp/portals/pcds.py @@ -4,7 +4,7 @@ from pkg_resources import resource_filename -from werkzeug import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util.map import MapApp from pdp.minify import wrap_mini diff --git a/pdp/wsgi.py b/pdp/wsgi.py index ea97e8dc..e0c0cf6c 100644 --- a/pdp/wsgi.py +++ b/pdp/wsgi.py @@ -1,6 +1,6 @@ '''Exposes globally defined WSGI apps as module variables ''' -from werkzeug.wsgi import DispatcherMiddleware +from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp import get_config from pdp.main import initialize_frontend, initialize_backend diff --git a/requirements.txt b/requirements.txt index f3dd040f..ae839a1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,21 +8,18 @@ chardet==3.0.4 click==7.1.2 coards==1.0.5 cryptography==3.3.2 -# pre-installed -#Cython==0.27.3 +#Cython==0.27.3 - pre-installed in docker. needed? enum34==1.1.6 Flask==1.0.2 funcsigs==1.0.2 ga-wsgi-client==0.1 -# pre-installed -#GDAL==2.2.0 -# Genshi==0.7 removed for conflict +GDAL==3.0.4 +Genshi==0.7.5 GeoAlchemy==0.7.3 GeoAlchemy2==0.9.1 gitdb2==2.0.6 GitPython==2.1.15 -# pre-installed -# h5py==2.7.1 +# h5py==3.2.1 - pre-installed in docker idna==2.6 ipaddress==1.0.17 itsdangerous==0.24 @@ -30,53 +27,42 @@ Jinja2==2.11.3 keyring==10.6.0 keyrings.alt==3.0 Mako==1.1.4 -MarkupSafe==1.0 +MarkupSafe==2.0 modelmeta==0.3.0 nchelpers==5.5.7 -#netCDF4==1.5.5.1 removed for conflict -# pre-installed -# numpy==1.16.6 +netCDF4==1.3.0 +# numpy==1.21.2 - pre-installed in docker olefile==0.46 openid2rp==1.12 Paste==2.0.3 -pdp-util==2.1.0 +pdp-util==2.1.0 # actually using a custom version Pillow==4.3.0 ply==3.10 -# psycopg2==2.7.3.2 removed as an experiment -psycopg2 -# pupynere-pdp==1.1.6 removed for conflict +psycopg2==2.9.1 +pupynere-pdp==2.0.1 PyCDS==2.2.1 PyCRS==1.0.2 pycrypto==2.6.1 -#pydap-pdp==3.2.6 -#pydap.handlers.csv==0.3 -#pydap.handlers.hdf5==0.5.2 -#pydap.handlers.pcic==0.0.11 -#pydap.handlers.sql==0.10 -#pydap.responses.aaigrid==0.7 -#pydap.responses.html==0.3 -#pydap.responses.netcdf==0.6.0 -#pydap.responses.xlsx==0.1 -# We use Ubuntu package; ver 3.26.1 not avail from pypi.org -#pygobject==3.26.1 +Pydap==3.2.2 +pydap_extras +#pygobject==3.26.1 - not available, lack doesn't seem to matter pystache==0.5.4 python-dateutil==2.6.1 python-editor==1.0.4 pytz==2017.3 -# PyYAML==5.4 removed for conflict -# requests==2.21.0 removed for conflict +PyYAML==5.4.1 +requests==2.25.1 SecretStorage==2.3.1 simplejson==3.12.0 six==1.11.0 slimit==0.8.1 smmap==3.0.5 smmap2==3.0.1 -# SQLAlchemy==1.3.0 removed for conflict SQLAlchemy==1.4.3 #added for pydap-extras sqlparse==0.3.1 static==1.1.1 urllib3==1.26.5 -WebOb==1.7.3 -Werkzeug==0.15.3 -# XlsxWriter==1.0.2 removed for conflict +WebOb==1.8.7 +Werkzeug==2.0.1 +XlsxWriter==1.3.8 xlwt==1.3.0 diff --git a/tests/test_functional.py b/tests/test_functional.py index 447330c2..5103af41 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -51,11 +51,11 @@ def test_no_404s(pcic_data_portal, url): @pytest.mark.crmpdb @pytest.mark.parametrize(('url', 'title', 'body_strings'), [ ('/data/pcds/lister/', 'PCDS Data', - ["Climatological calculations", "raw/"]), + [b"Climatological calculations", b"raw/"]), ('/data/pcds/lister/raw/', "Participating CRMP Networks", - ["FLNRO-WMB/", "Environment Canada (Canadian Daily Climate Data 2007)"]), + [b"FLNRO-WMB/", b"Environment Canada (Canadian Daily Climate Data 2007)"]), ('/data/pcds/lister/raw/AGRI/', - "Stations for network AGRI", ["de107/", "Deep Creek"]), + "Stations for network AGRI", [b"de107/", b"Deep Creek"]), ]) def test_climo_index( pcic_data_portal, url, title, body_strings): From a32d9bd16fde34eab2d823c2cce8cc6d34622b9d Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 5 Apr 2022 09:17:23 -0700 Subject: [PATCH 03/71] Upgrade gunicorn to version 19.9.0 --- deploy_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy_requirements.txt b/deploy_requirements.txt index 5f3ed8ef..701bb2dd 100644 --- a/deploy_requirements.txt +++ b/deploy_requirements.txt @@ -3,7 +3,7 @@ Babel==2.9.1 docutils==0.17.1 gevent==21.1.2 greenlet==1.1.0 -gunicorn==19.8.1 +gunicorn==19.9.0 imagesize==1.2.0 packaging==20.9 Pygments==2.5.2 From a175295a4ad651bc5e6e15c2cd53aabfd0d20d86 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 9 May 2022 12:40:47 -0700 Subject: [PATCH 04/71] Remove uses of Google Analytics client --- CONTRIBUTING.rst | 6 ------ docker/local-run/common.env | 2 -- docker/production/common.env | 2 -- docs/deployment.md | 2 -- pdp/__init__.py | 3 --- pdp/config.env | 3 --- pdp/main.py | 17 +++++------------ pdp/wsgi.py | 2 -- requirements.txt | 1 - setup.py | 1 - 10 files changed, 5 insertions(+), 34 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 2f9f3777..e410970e 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -134,12 +134,6 @@ pdp/config.env | | ``NCWMS_URL`` | Raster portal ncWMS URL of the form ``:/ncWMS/``. The host/port must match ``APP_ROOT``. -| -| ``USE_ANALYTICS`` -| Enable or disable Google Analytics reporting (default is ``true``). -| -| ``ANALYTICS`` -| Google Analytics ID. docker basics diff --git a/docker/local-run/common.env b/docker/local-run/common.env index eb2bd4d9..0fe0d72f 100644 --- a/docker/local-run/common.env +++ b/docker/local-run/common.env @@ -11,5 +11,3 @@ GUNICORN_TIMEOUT=86400 USE_AUTH=False SESSION_DIR=default CLEAN_SESSION_DIR=True -USE_ANALYTICS=True -ANALYTICS=UA-20166041-2 \ No newline at end of file diff --git a/docker/production/common.env b/docker/production/common.env index eb2bd4d9..0fe0d72f 100644 --- a/docker/production/common.env +++ b/docker/production/common.env @@ -11,5 +11,3 @@ GUNICORN_TIMEOUT=86400 USE_AUTH=False SESSION_DIR=default CLEAN_SESSION_DIR=True -USE_ANALYTICS=True -ANALYTICS=UA-20166041-2 \ No newline at end of file diff --git a/docs/deployment.md b/docs/deployment.md index 84dbc429..682822e3 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -56,8 +56,6 @@ They are loaded from the environment variables of the same name, upper cased. | `ncwms_url` | Raster portal ncWMS 2.x -- modelmeta translator URL. | | `old_ncwms_url` | Raster portal pure ncWMS 1.x URL. Used to fill in missing services from ncWMS 2.x. | | `tilecache_url` | Tileserver URLs (space separated list) for base maps | -| `use_analytics` | Enable or disable Google Analytics reporting | -| `analytics` | Google Analytics ID | ### Gunicorn configuration diff --git a/pdp/__init__.py b/pdp/__init__.py index 8e202a91..c0da742b 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -43,8 +43,6 @@ def get_config_from_environment(): 'http://a.tiles.pacificclimate.org/tilecache/tilecache.py' ' http://b.tiles.pacificclimate.org/tilecache/tilecache.py' ' http://c.tiles.pacificclimate.org/tilecache/tilecache.py', - 'use_analytics': 'True', - 'analytics': 'UA-20166041-3' # change for production } config = { key: os.environ.get(key.upper(), default) @@ -52,7 +50,6 @@ def get_config_from_environment(): } # evaluate a few config items that need to be objects (not strings) config['js_min'] = (config['js_min'] == 'True') - config['use_analytics'] = (config['use_analytics'] == 'True') if config['tilecache_url']: config['tilecache_url'] = config['tilecache_url'].split() return config diff --git a/pdp/config.env b/pdp/config.env index a4f01ea2..8e973caa 100644 --- a/pdp/config.env +++ b/pdp/config.env @@ -12,6 +12,3 @@ GEOSERVER_URL=http://tools.pacificclimate.org/geoserver/ # change for development NCWMS_URL=http://tools.pacificclimate.org/ncWMS-PCIC/wms TILECACHE_URL="http://a.tiles.pacificclimate.org/tilecache/tilecache.py http://b.tiles.pacificclimate.org/tilecache/tilecache.py http://c.tiles.pacificclimate.org/tilecache/tilecache.py" -USE_ANALYTICS=True -# change for production -ANALYTICS=UA-20166041-3 diff --git a/pdp/main.py b/pdp/main.py index d87cab2a..b860261a 100644 --- a/pdp/main.py +++ b/pdp/main.py @@ -6,7 +6,6 @@ from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp.error import ErrorMiddleware -from ga_wsgi_client import AnalyticsMiddleware # Station portals import pdp.portals.pcds as pcds @@ -28,7 +27,7 @@ hydro_stn_archive, hydro_stn_cmip5) -def initialize_frontend(global_config, use_analytics=False): +def initialize_frontend(global_config): '''Frontend server with all portal pages and required resources ''' @@ -47,13 +46,10 @@ def initialize_frontend(global_config, use_analytics=False): wsgi_app = DispatcherMiddleware(static_app, mounts) - use_analytics = False - if use_analytics: - wsgi_app = AnalyticsMiddleware(wsgi_app, global_config['analytics']) return ErrorMiddleware(wsgi_app) -def initialize_backend(global_config, use_analytics=False): +def initialize_backend(global_config): '''Backend DispatcherMiddleware with all data servers ''' mounts = { @@ -64,16 +60,13 @@ def initialize_backend(global_config, use_analytics=False): static_app = static.Cling(resource_filename('pdp', 'static')) wsgi_app = DispatcherMiddleware(static_app, mounts) - use_analytics = False - if use_analytics: - wsgi_app = AnalyticsMiddleware(wsgi_app, global_config['analytics']) return ErrorMiddleware(wsgi_app) -def initialize_dev_server(global_config, use_analytics=False): +def initialize_dev_server(global_config): '''Development server ''' return DispatcherMiddleware( - initialize_frontend(global_config, use_analytics), - {'/data': initialize_backend(global_config, use_analytics)} + initialize_frontend(global_config), + {'/data': initialize_backend(global_config)} ) diff --git a/pdp/wsgi.py b/pdp/wsgi.py index e0c0cf6c..3dd9f7eb 100644 --- a/pdp/wsgi.py +++ b/pdp/wsgi.py @@ -9,11 +9,9 @@ frontend = initialize_frontend( global_config, - use_analytics=global_config['use_analytics'] ) backend = initialize_backend( global_config, - use_analytics=global_config['use_analytics'] ) dev_server = DispatcherMiddleware(frontend, { '/data': backend diff --git a/requirements.txt b/requirements.txt index ae839a1c..f8d963ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,6 @@ cryptography==3.3.2 enum34==1.1.6 Flask==1.0.2 funcsigs==1.0.2 -ga-wsgi-client==0.1 GDAL==3.0.4 Genshi==0.7.5 GeoAlchemy==0.7.3 diff --git a/setup.py b/setup.py index 39de41ab..a3b2538d 100644 --- a/setup.py +++ b/setup.py @@ -81,7 +81,6 @@ def get_commitish(): "pdp-util >=1.2.1", "modelmeta >=0.3.0", "pydap_extras >= 0.2.1", - "ga-wsgi-client", "slimit", "netCDF4<1.5.6", ], From 80c521c6678d75af67281ec3b794a0a3e5cf781d Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 5 Jul 2022 09:02:23 -0700 Subject: [PATCH 05/71] Proxy Pass THREDDS URL and set ORCA URL configs --- docker/local-run/nginx.conf | 10 +++++++++- pdp/__init__.py | 3 ++- pdp/portals/__init__.py | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docker/local-run/nginx.conf b/docker/local-run/nginx.conf index e18e06ac..76c89fe2 100644 --- a/docker/local-run/nginx.conf +++ b/docker/local-run/nginx.conf @@ -30,5 +30,13 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } + + location /thredds/ { + proxy_pass https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + } } -} \ No newline at end of file +} diff --git a/pdp/__init__.py b/pdp/__init__.py index c0da742b..8b494e36 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -32,7 +32,8 @@ def get_config_from_environment(): 'data_root': 'http://tools.pacificclimate.org/dataportal/data', 'title': '', 'ensemble_name': '', - 'thredds_root': 'http://docker-dev03.pcic.uvic.ca:30333/data', + 'thredds_root': 'http://pdp.localhost:5000/thredds', + 'orca_root': 'http://docker-dev03.pcic.uvic.ca:30333/data', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', 'js_min': 'False', diff --git a/pdp/portals/__init__.py b/pdp/portals/__init__.py index 68594479..6d7465d3 100644 --- a/pdp/portals/__init__.py +++ b/pdp/portals/__init__.py @@ -30,6 +30,7 @@ def raster_conf(dsn, global_config, ensemble_name, data_base=None): root_url=root_url ) conf["thredds_root"] = global_config["thredds_root"] + conf["orca_root"] = global_config["orca_root"] return conf From 51f90844587d977773ae621698bf304efc98fd21 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 15 Jul 2022 08:55:02 -0700 Subject: [PATCH 06/71] Proxy pass orca URL in nginx.conf --- docker/local-run/nginx.conf | 8 ++++++++ pdp/__init__.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docker/local-run/nginx.conf b/docker/local-run/nginx.conf index 76c89fe2..d4994914 100644 --- a/docker/local-run/nginx.conf +++ b/docker/local-run/nginx.conf @@ -38,5 +38,13 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } + + location /orca/ { + proxy_pass http://docker-dev03.pcic.uvic.ca:30333/data/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Host $server_name; + } } } diff --git a/pdp/__init__.py b/pdp/__init__.py index 83e0f4b2..512653de 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -33,7 +33,7 @@ def get_config_from_environment(): 'title': '', 'ensemble_name': '', 'thredds_root': 'http://pdp.localhost:5000/thredds', - 'orca_root': 'http://docker-dev03.pcic.uvic.ca:30333/data', + 'orca_root': 'http://pdp.localhost:5000/orca', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', 'js_min': 'False', From b96ee5615e6c1df20bb4e44df3885b6dc8ef3ee6 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 6 Sep 2022 14:15:39 -0700 Subject: [PATCH 07/71] Handle .ascii requests from THREDDS --- pdp/static/js/data-services.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pdp/static/js/data-services.js b/pdp/static/js/data-services.js index 406224ce..5f1cc57c 100644 --- a/pdp/static/js/data-services.js +++ b/pdp/static/js/data-services.js @@ -122,8 +122,16 @@ // array). const lines = data.split("\n"); const result = {}; - for (let i = 0; i < lines.length - 1; i += 2) { - result[lines[i]] = JSON.parse(lines[i + 1]); + if (lines[0] === "Dataset {") { // Response comes from THREDDS + // Ignore header information + for (let i = 5; i < lines.length - 1; i += 3) { + // Only use coordinate name as key + result[lines[i].substring(0,3)] = JSON.parse("[" + lines[i + 1] + "]"); + } + } + else { // Response comes from PyDAP + for (let i = 0; i < lines.length - 1; i += 2) { + result[lines[i]] = JSON.parse(lines[i + 1]); } } return result; } From 727499a9e154f53e8fa00efd6bc6b8b2b8c5d851 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 15:44:15 -0700 Subject: [PATCH 08/71] Decrement end bounds for lon/lat in each raster portal app --- pdp/static/js/canada_ex_app.js | 2 +- pdp/static/js/cmip6_bccaq2_app.js | 2 +- pdp/static/js/prism_demo_app.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pdp/static/js/canada_ex_app.js b/pdp/static/js/canada_ex_app.js index df02b788..285bb7d5 100644 --- a/pdp/static/js/canada_ex_app.js +++ b/pdp/static/js/canada_ex_app.js @@ -69,7 +69,7 @@ getRasterDownloadOptions, RasterDownloadLink, MetadataDownloadLink*/ } // Data Download Link - dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:510', '0:1068'); + dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:509', '0:1067'); $('#data-format-selector').change( function (evt) { dlLink.onExtensionChange($(this).val()); diff --git a/pdp/static/js/cmip6_bccaq2_app.js b/pdp/static/js/cmip6_bccaq2_app.js index 69378adb..6c2bc5d2 100644 --- a/pdp/static/js/cmip6_bccaq2_app.js +++ b/pdp/static/js/cmip6_bccaq2_app.js @@ -39,7 +39,7 @@ RasterDownloadLink, MetadataDownloadLink*/ .appendChild(getRasterDownloadOptions('first', 'last')); // Data Download Link - dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:510', '0:1068'); + dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:509', '0:1067'); $('#data-format-selector').change( function (evt) { dlLink.onExtensionChange($(this).val()); diff --git a/pdp/static/js/prism_demo_app.js b/pdp/static/js/prism_demo_app.js index 2014b59b..e5b24b9d 100644 --- a/pdp/static/js/prism_demo_app.js +++ b/pdp/static/js/prism_demo_app.js @@ -33,7 +33,7 @@ } // Data Download Link - dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'pr', '', '0:1680', '0:3241'); + dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'pr', '', '0:1679', '0:3240'); $('#data-format-selector').change( function (evt) { dlLink.onExtensionChange($(this).val()); From 98d9ddfa807ddfbbf10ae3097cd94627a2551b3e Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 15:50:56 -0700 Subject: [PATCH 09/71] Remove reference to use_analytics in conftest.py --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index b71b1d17..0523e02e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,7 +19,7 @@ def prism_portal(): def pcic_data_portal(): from pdp.main import initialize_dev_server from pdp import get_config - return initialize_dev_server(get_config(), False) + return initialize_dev_server(get_config()) @pytest.fixture(scope="module") From 2663e70f2fa00d5f2a9f1682d304c705a87fdc4a Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 15:53:06 -0700 Subject: [PATCH 10/71] Set THREDDS_ROOT and ORCA_ROOT as environment variables in docker-compose.yaml --- docker/local-run/docker-compose.yaml | 2 ++ pdp/__init__.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/local-run/docker-compose.yaml b/docker/local-run/docker-compose.yaml index de03d3b2..bc6ba019 100755 --- a/docker/local-run/docker-compose.yaml +++ b/docker/local-run/docker-compose.yaml @@ -54,6 +54,8 @@ services: - common-with-passwords.env environment: # Specific to backend + - THREDDS_ROOT=http://pdp.localhost:5000/thredds + - ORCA_ROOT=http://pdp.localhost:5000/orca - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent entrypoint: /codebase/docker/local-run/entrypoint-be.sh diff --git a/pdp/__init__.py b/pdp/__init__.py index 512653de..b1bf0bf1 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -32,8 +32,8 @@ def get_config_from_environment(): 'data_root': 'http://tools.pacificclimate.org/dataportal/data', 'title': '', 'ensemble_name': '', - 'thredds_root': 'http://pdp.localhost:5000/thredds', - 'orca_root': 'http://pdp.localhost:5000/orca', + 'thredds_root': 'https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets/', + 'orca_root': 'http://docker-dev03.pcic.uvic.ca:30333/data/', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', 'js_min': 'False', From a1a14d9e753ed9e83992a54d4d7dd486becb8f5d Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 15:55:56 -0700 Subject: [PATCH 11/71] Use new database DSNs --- docker/local-run/common.env | 2 +- docker/local-run/pgbouncer.ini | 4 ++-- docker/local-test/env.env | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/local-run/common.env b/docker/local-run/common.env index 0fe0d72f..d6c19e56 100644 --- a/docker/local-run/common.env +++ b/docker/local-run/common.env @@ -1,6 +1,6 @@ # environment variables common to fe and be -DSN=postgresql://httpd_meta:XXXXXX@pgbouncer-dev:5432/pcic_meta_test +DSN=postgresql://httpd_meta:XXXXXX@pgbouncer-dev:5432/pcic_meta PCDS_DSN=postgresql://httpd:XXXXXX@pgbouncer-dev:5432/crmp GUNICORN_BIND=0.0.0.0:8000 diff --git a/docker/local-run/pgbouncer.ini b/docker/local-run/pgbouncer.ini index 3e339b66..3b6c0cc4 100755 --- a/docker/local-run/pgbouncer.ini +++ b/docker/local-run/pgbouncer.ini @@ -1,7 +1,7 @@ [databases] metnorth_8fd8f556c548 = host=dbnorth.pcic.uvic.ca port=5432 user=metnorth_ro dbname=metnorth_8fd8f556c548 -crmp = host=db3.pcic.uvic.ca port=5432 user=httpd dbname=crmp -pcic_meta = host=db3.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta +crmp = host=db.pcic.uvic.ca port=5432 user=httpd dbname=crmp +pcic_meta = host=db.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta pcic_meta_test = host=db3.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta_test [pgbouncer] diff --git a/docker/local-test/env.env b/docker/local-test/env.env index 784e6fa3..a8c0ff2f 100644 --- a/docker/local-test/env.env +++ b/docker/local-test/env.env @@ -1,2 +1,2 @@ -DSN=postgresql://httpd_meta:XXXXXX@db3.pcic.uvic.ca:5432/pcic_meta_test -PCDS_DSN=postgresql://httpd:XXXXXX@db3.pcic.uvic.ca:5432/crmp \ No newline at end of file +DSN=postgresql://httpd_meta:XXXXXX@db.pcic.uvic.ca:5432/pcic_meta +PCDS_DSN=postgresql://httpd:XXXXXX@db.pcic.uvic.ca:5432/crmp From cdf110f4c98698f0554160ff4e665301dcae8852 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 16:03:55 -0700 Subject: [PATCH 12/71] Remove crmpdb mark from incorrectly marked tests --- tests/test_functional.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index 5103af41..d72bb069 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -399,7 +399,6 @@ def test_input_polygon_download_zipfile(pcic_data_portal, polygon): assert z.testzip() is None -@pytest.mark.crmpdb @pytest.mark.bulk_data def test_climatology_bounds(pcic_data_portal): url = '/data/bc_prism/pr_mClimMean_PRISM_historical_19710101-20001231'\ @@ -437,7 +436,6 @@ def test_climatology_bounds(pcic_data_portal): @pytest.mark.slow -@pytest.mark.crmpdb @pytest.mark.bulk_data @pytest.mark.parametrize('url', [ # has NODATA values @@ -456,7 +454,6 @@ def test_aaigrid_response(pcic_data_portal, url): @pytest.mark.slow -@pytest.mark.crmpdb @pytest.mark.bulk_data @pytest.mark.parametrize( 'layers', @@ -478,7 +475,6 @@ def test_aaigrid_response_layers(pcic_data_portal, layers): assert len(z.namelist()) == (layers + 1) * 2 -@pytest.mark.crmpdb @pytest.mark.parametrize(('portal', 'ensemble'), [ ('bc_prism', 'bc_prism'), ('downscaled_gcms_archive', 'downscaled_gcms_archive'), From 6fe24a1cfe05775ce0ac442fc8f9fd75a212f76c Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 16 Sep 2022 16:05:26 -0700 Subject: [PATCH 13/71] Only target climatology_bnds in climatological averages datasets --- pdp/static/js/prism_demo_app.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pdp/static/js/prism_demo_app.js b/pdp/static/js/prism_demo_app.js index e5b24b9d..5fa85203 100644 --- a/pdp/static/js/prism_demo_app.js +++ b/pdp/static/js/prism_demo_app.js @@ -22,11 +22,10 @@ capabilities_request = dataServices.getNCWMSLayerCapabilities(ncwmsLayer); - // Ensure that climatology_bounds are included in non-aig data downloads function setBoundsInUrlTemplate() { - if (dlLink.ext === 'aig') { + if (dlLink.ext === 'aig' || !dlLink.dl_url.includes("historical")) { dlLink.url_template = '{dl_url}.{ext}?{varname}[][{yrange}][{xrange}]&'; - } else { + } else { // Include climatology bounds dlLink.url_template = '{dl_url}.{ext}?climatology_bnds,{varname}[][{yrange}][{xrange}]&'; } dlLink.trigger(); From 5eb84eebb23251fa645171a7c08d601d3bdbb03b Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 3 Oct 2022 08:48:59 -0700 Subject: [PATCH 14/71] Use pdp.portals in import statements in main.py --- pdp/main.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pdp/main.py b/pdp/main.py index 23a5ea6d..c15f5998 100644 --- a/pdp/main.py +++ b/pdp/main.py @@ -13,13 +13,13 @@ import pdp.portals.hydro_stn_cmip5 as hydro_stn_cmip5 # Raster portals -import portals.bc_prism as bc_prism -import portals.bccaq2_downscale as bccaq2 -import portals.bccaq2_cmip6 as bccaq2_cmip6 -import portals.bccaq2_canesm5 as bccaq2_canesm5 -import portals.gridded_observations as gridded_observations -import portals.vic_gen1 as vic_gen1 -import portals.vic_gen2 as vic_gen2 +import pdp.portals.bc_prism as bc_prism +import pdp.portals.bccaq2_downscale as bccaq2 +import pdp.portals.bccaq2_cmip6 as bccaq2_cmip6 +import pdp.portals.bccaq2_canesm5 as bccaq2_canesm5 +import pdp.portals.gridded_observations as gridded_observations +import pdp.portals.vic_gen1 as vic_gen1 +import pdp.portals.vic_gen2 as vic_gen2 apps = (bc_prism, bccaq2, vic_gen1, vic_gen2, From 7a3eaa92f35e2f067476d5362bc5e2c906fe43ba Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:16:07 -0700 Subject: [PATCH 15/71] Remove THREDDS url from nginx.conf and docker-compose.yaml --- docker/local-run/docker-compose.yaml | 1 - docker/local-run/nginx.conf | 8 -------- 2 files changed, 9 deletions(-) diff --git a/docker/local-run/docker-compose.yaml b/docker/local-run/docker-compose.yaml index bc6ba019..751b2f52 100755 --- a/docker/local-run/docker-compose.yaml +++ b/docker/local-run/docker-compose.yaml @@ -54,7 +54,6 @@ services: - common-with-passwords.env environment: # Specific to backend - - THREDDS_ROOT=http://pdp.localhost:5000/thredds - ORCA_ROOT=http://pdp.localhost:5000/orca - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent diff --git a/docker/local-run/nginx.conf b/docker/local-run/nginx.conf index d4994914..1085ac64 100644 --- a/docker/local-run/nginx.conf +++ b/docker/local-run/nginx.conf @@ -30,14 +30,6 @@ http { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } - - location /thredds/ { - proxy_pass https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - } location /orca/ { proxy_pass http://docker-dev03.pcic.uvic.ca:30333/data/; From b490a9824bc64e58836e479fe881aca8faef0994 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:17:32 -0700 Subject: [PATCH 16/71] Use python3 image and add ORCA_ROOT to local test build --- docker/local-test/Dockerfile | 4 ++-- docker/local-test/env.env | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docker/local-test/Dockerfile b/docker/local-test/Dockerfile index b9e8f591..703b9a19 100644 --- a/docker/local-test/Dockerfile +++ b/docker/local-test/Dockerfile @@ -1,4 +1,4 @@ -FROM pcic/pdp-base-minimal:1.0.0 +FROM pcic/pdp-base-minimal:pdp-python3 USER root # TODO: Move into pdp-base-minimal? @@ -8,4 +8,4 @@ USER ${USERNAME} # You must mount the local codebase to /codebase WORKDIR /codebase -ENTRYPOINT ./docker/local-test/entrypoint.sh \ No newline at end of file +ENTRYPOINT ./docker/local-test/entrypoint.sh diff --git a/docker/local-test/env.env b/docker/local-test/env.env index a8c0ff2f..acc6e819 100644 --- a/docker/local-test/env.env +++ b/docker/local-test/env.env @@ -1,2 +1,3 @@ DSN=postgresql://httpd_meta:XXXXXX@db.pcic.uvic.ca:5432/pcic_meta PCDS_DSN=postgresql://httpd:XXXXXX@db.pcic.uvic.ca:5432/crmp +ORCA_ROOT=http://docker-dev03.pcic.uvic.ca:30333/data From 0e199df5014a08efc03a307c046613dfdc870a6c Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:18:34 -0700 Subject: [PATCH 17/71] Remove end slashes from default THREDDS and ORCA urls --- pdp/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdp/__init__.py b/pdp/__init__.py index b1bf0bf1..dd54da80 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -32,8 +32,8 @@ def get_config_from_environment(): 'data_root': 'http://tools.pacificclimate.org/dataportal/data', 'title': '', 'ensemble_name': '', - 'thredds_root': 'https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets/', - 'orca_root': 'http://docker-dev03.pcic.uvic.ca:30333/data/', + 'thredds_root': 'https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets', + 'orca_root': 'http://docker-dev03.pcic.uvic.ca:30333/data', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', 'js_min': 'False', From 0929d4bc5dcaa3b4d747ecfee43f5cef51523bfb Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:21:28 -0700 Subject: [PATCH 18/71] Remove /catalog/ from metadata_url --- pdp/static/js/__test__/pdp_controls.test.js | 2 +- pdp/static/js/pdp_controls.js | 4 ++-- pdp/static/js/pdp_raster_map.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pdp/static/js/__test__/pdp_controls.test.js b/pdp/static/js/__test__/pdp_controls.test.js index 0d0ad10c..42d71087 100644 --- a/pdp/static/js/__test__/pdp_controls.test.js +++ b/pdp/static/js/__test__/pdp_controls.test.js @@ -99,7 +99,7 @@ describe('Download links', () => { }); describe('MetadataDownloadLink', function() { - const metadata_url = `${data_root}/${portal}/catalog/${filename}.${extension}.das`; + const metadata_url = `${data_root}/${portal}/${filename}.${extension}.das`; describe('mock app setup', function() { var dlLink; diff --git a/pdp/static/js/pdp_controls.js b/pdp/static/js/pdp_controls.js index 009c3631..82d19433 100644 --- a/pdp/static/js/pdp_controls.js +++ b/pdp/static/js/pdp_controls.js @@ -636,8 +636,8 @@ MetadataDownloadLink.prototype = { url = this.catalog[dst]; reg = new RegExp(pdp.data_root + '/(.*)/(.*)'); matches = reg.exec(url); - //matches[1] is portal url base, matches[2] is dataset, make catalog URL. - url = pdp.data_root + "/" + matches[1] + "/catalog/" + matches[2]; + //matches[1] is portal url base, matches[2] is dataset, make URL. + url = pdp.data_root + "/" + matches[1] + "/" + matches[2]; this.dl_url = url; this.trigger(); } diff --git a/pdp/static/js/pdp_raster_map.js b/pdp/static/js/pdp_raster_map.js index f30eaea3..d24aa4cf 100644 --- a/pdp/static/js/pdp_raster_map.js +++ b/pdp/static/js/pdp_raster_map.js @@ -36,7 +36,7 @@ function dasToCfTimeSystem(das, indexCount) { function processNcwmsLayerMetadata(ncwms_layer, catalog) { // transform the data_server url into the un-authed catalog based url for metadata - var layerUrl = catalog[getNcwmsLayerId(ncwms_layer)]; //matches[1] is portal base url, matches[2] is dataset, make catalog url // Request time variables + var layerUrl = catalog[getNcwmsLayerId(ncwms_layer)]; //matches[1] is portal base url, matches[2] is dataset, make url // Request time variables var maxTimeReq = dataServices.getNcwmsLayerDDS(layerUrl); var unitsSinceReq = dataServices.getNcwmsLayerDAS(layerUrl); From 18caba6b65e7ff54d2a4a45b9967e6cbccf600a1 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:30:12 -0700 Subject: [PATCH 19/71] Decrement upper lon/lat bounds in canesm5 app --- pdp/static/js/canesm5_app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdp/static/js/canesm5_app.js b/pdp/static/js/canesm5_app.js index 3d470f74..49c8b3b4 100644 --- a/pdp/static/js/canesm5_app.js +++ b/pdp/static/js/canesm5_app.js @@ -40,7 +40,7 @@ RasterDownloadLink, MetadataDownloadLink*/ .appendChild(getRasterDownloadOptions('first', 'last')); // Data Download Link - dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:510', '0:1068'); + dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'tasmax', '0:55152', '0:509', '0:1067'); $('#data-format-selector').change( function (evt) { dlLink.onExtensionChange($(this).val()); From 877027c84230563fc2d9d75b04d941117dd6e6c6 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:31:12 -0700 Subject: [PATCH 20/71] Set climatology bounds in url template for BC prism portal only when appropriate --- pdp/static/js/prism_demo_app.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/pdp/static/js/prism_demo_app.js b/pdp/static/js/prism_demo_app.js index 5fa85203..c025d5da 100644 --- a/pdp/static/js/prism_demo_app.js +++ b/pdp/static/js/prism_demo_app.js @@ -23,21 +23,19 @@ capabilities_request = dataServices.getNCWMSLayerCapabilities(ncwmsLayer); function setBoundsInUrlTemplate() { - if (dlLink.ext === 'aig' || !dlLink.dl_url.includes("historical")) { - dlLink.url_template = '{dl_url}.{ext}?{varname}[][{yrange}][{xrange}]&'; - } else { // Include climatology bounds - dlLink.url_template = '{dl_url}.{ext}?climatology_bnds,{varname}[][{yrange}][{xrange}]&'; - } - dlLink.trigger(); + var das_request = dataServices.getNcwmsLayerDAS(dlLink.dl_url); + $.when(das_request).done(function (data) { + if (!data.includes("climatology_bnds")) { // Timeseries + dlLink.url_template = '{dl_url}.{ext}?{varname}[][{yrange}][{xrange}]&'; + } else { + dlLink.url_template = '{dl_url}.{ext}?climatology_bnds,{varname}[][{yrange}][{xrange}]&'; + } + dlLink.trigger(); + }); } // Data Download Link dlLink = new RasterDownloadLink($('#download-timeseries'), ncwmsLayer, undefined, 'nc', 'pr', '', '0:1679', '0:3240'); - $('#data-format-selector').change( - function (evt) { - dlLink.onExtensionChange($(this).val()); - } - ).change(setBoundsInUrlTemplate); ncwmsLayer.events.register('change', dlLink, function () { processNcwmsLayerMetadata(ncwmsLayer, catalog); @@ -50,6 +48,7 @@ }); }); ncwmsLayer.events.register('change', dlLink, dlLink.onLayerChange); + ncwmsLayer.events.register('change', dlLink, setBoundsInUrlTemplate); selectionLayer.events.register('featureadded', dlLink, function (selection) { capabilities_request.done(function (data) { @@ -61,7 +60,7 @@ dlLink.register($('#download-timeseries'), function (node) { node.attr('href', dlLink.getUrl()); }); - setBoundsInUrlTemplate(); + dlLink.url_template = '{dl_url}.{ext}?climatology_bnds,{varname}[][{yrange}][{xrange}]&'; dlLink.trigger(); // Metadata/Attributes Download Link From 634f472277738fcd39f0f2e85b5e1def702c2517 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:37:17 -0700 Subject: [PATCH 21/71] Replace PyDAP server for Hydro Station portals with redirects to ORCA --- pdp/portals/hydro_stn_archive.py | 48 +++++++++++++++++++++-------- pdp/portals/hydro_stn_cmip5.py | 47 ++++++++++++++++++++-------- pdp/static/js/.Rhistory | 0 pdp/static/js/hydro_stn_app.js | 2 +- pdp/static/js/hydro_stn_controls.js | 2 +- pdp/static/js/hydro_stn_download.js | 7 ++--- requirements.txt | 2 -- 7 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 pdp/static/js/.Rhistory diff --git a/pdp/portals/hydro_stn_archive.py b/pdp/portals/hydro_stn_archive.py index d93d1aae..5da372a8 100644 --- a/pdp/portals/hydro_stn_archive.py +++ b/pdp/portals/hydro_stn_archive.py @@ -11,42 +11,64 @@ This portal is very similar to the hydro_stn_cmip5 portal, which serves a more up to date data collection of similar format from a different directory. The two portals share a frontend, hydro_stn_app.''' + +import os from pkg_resources import resource_filename from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util.map import MapApp -from pydap.wsgi.app import DapServer from pdp.minify import wrap_mini from pdp.portals import updateConfig +from simplejson import dumps +from webob.request import Request +from webob.response import Response + __all__ = ['url_base', 'mk_frontend', 'mk_backend'] url_base = '/hydro_stn_archive' -class HydroStationDataServer(DapServer): - '''WSGI app which is a subclass of PyDap's DapServer that directly - configures the app's root_url +class HydroStationDataServer(object): + '''WSGI app to create URLs that redirect to the ORCA application to obtain data + from THREDDS server ''' - def __init__(self, filepath, root_url): - self.root_url = root_url - return super(HydroStationDataServer, self).__init__(filepath) + def __init__(self, config): + self._config = config @property def config(self): - super(HydroStationDataServer, self).config - self._config['root_url'] = self.root_url return self._config + def __call__(self, environ, start_response): + storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_gen1_followup/vic_gen1_routed' + req = Request(environ) + if req.path_info == '/catalog.json': + urls = [self.config['root_url'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] + res = Response( + body=dumps(urls, indent=4), + content_type='application/json', + charset='utf-8', + ) + return res(environ, start_response) + else: + url = build_orca_url(self.config['orca_root'], self.config['thredds_root'], storage_root, req) + return Response(status_code=301, location=url) + +def build_orca_url(orca_root, thredds_root, storage_root, req): + filepath = storage_root + req.path_info + if req.query_string == '': + return f'{orca_root}/?filepath={filepath}&thredds_base={thredds_root}&outfile={req.path_info.strip("/.")}' + else: + return f'{orca_root}/?filepath={filepath}&thredds_base={thredds_root}&targets={req.query_string}&outfile={req.path_info.strip("/.")}' def mk_backend(config): - data_server = HydroStationDataServer( - resource_filename('pdp', 'resources/hydro_stn_archive.yaml'), - config['data_root'].rstrip('/') + '/' - ) + config['root_url'] = config['data_root'].rstrip('/') + '/' + config['thredds_root'] = config['thredds_root'].replace('dodsC', 'fileServer') # Use HTTP instead of OpenDAP requests + data_server = HydroStationDataServer(config) return data_server diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index 5b5a4cfe..89a21ac5 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -12,42 +12,63 @@ a similar but older collection of CSVs from a different directory. The two portals share a frontend, hydro_stn_app.''' +import os from pkg_resources import resource_filename from werkzeug.middleware.dispatcher import DispatcherMiddleware from pdp_util.map import MapApp -from pydap.wsgi.app import DapServer from pdp.minify import wrap_mini from pdp.portals import updateConfig +from simplejson import dumps +from webob.request import Request +from webob.response import Response + __all__ = ['url_base', 'mk_frontend', 'mk_backend'] url_base = '/hydro_stn_cmip5' -class HydroStationDataServer(DapServer): - '''WSGI app which is a subclass of PyDap's DapServer that directly - configures the app's root_url +class HydroStationDataServer(object): + '''WSGI app to create URLs that redirect to the ORCA application to obtain data + from THREDDS server ''' - def __init__(self, filepath, root_url): - self.root_url = root_url - return super(HydroStationDataServer, self).__init__(filepath) + def __init__(self, config): + self._config = config @property def config(self): - super(HydroStationDataServer, self).config - self._config['root_url'] = self.root_url return self._config + def __call__(self, environ, start_response): + storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_cmip5/merged' + req = Request(environ) + if req.path_info == '/catalog.json': + urls = [self.config['root_url'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] + res = Response( + body=dumps(urls, indent=4), + content_type='application/json', + charset='utf-8', + ) + return res(environ, start_response) + else: + url = build_orca_url(self.config['orca_root'], self.config['thredds_root'], storage_root, req) + return Response(status_code=301, location=url) + +def build_orca_url(orca_root, thredds_root, storage_root, req): + filepath = storage_root + req.path_info + if req.query_string == '': + return f'{orca_root}/?filepath={filepath}&thredds_base={thredds_root}&outfile={req.path_info.strip("/.")}' + else: + return f'{orca_root}/?filepath={filepath}&thredds_base={thredds_root}&targets={req.query_string}&outfile={req.path_info.strip("/.")}' def mk_backend(config): - data_server = HydroStationDataServer( - resource_filename('pdp', 'resources/hydro_stn_cmip5.yaml'), - config['data_root'].rstrip('/') + '/' - ) + config['root_url'] = config['data_root'].rstrip('/') + '/' + config['thredds_root'] = config['thredds_root'].replace('dodsC', 'fileServer') # Use HTTP instead of OpenDAP requests + data_server = HydroStationDataServer(config) return data_server diff --git a/pdp/static/js/.Rhistory b/pdp/static/js/.Rhistory new file mode 100644 index 00000000..e69de29b diff --git a/pdp/static/js/hydro_stn_app.js b/pdp/static/js/hydro_stn_app.js index d13380f8..6554ba32 100644 --- a/pdp/static/js/hydro_stn_app.js +++ b/pdp/static/js/hydro_stn_app.js @@ -125,7 +125,7 @@ url_list = $.map(fids, function (fid) { return dataArray[fid].url; }); - show_permalinks(url_list, 'ascii'); + show_permalinks(url_list); }); // the archive and current portals link to eachother. diff --git a/pdp/static/js/hydro_stn_controls.js b/pdp/static/js/hydro_stn_controls.js index 15d2f707..eacb0ff7 100644 --- a/pdp/static/js/hydro_stn_controls.js +++ b/pdp/static/js/hydro_stn_controls.js @@ -94,7 +94,7 @@ function addToSidebar(idx, dataArray) { link = document.createElement('a'); const data_dir = isArchivePortal() ? "hydro_stn_archive" : "hydro_stn_cmip5"; - link.href = pdp.data_root + "/" + dataURL() + "/" + dataArray[idx].FileName + '.ascii'; + link.href = pdp.data_root + "/" + dataURL() + "/" + dataArray[idx].FileName; link.appendChild(document.createTextNode(dataArray[idx].StationName)); item.appendChild(link); diff --git a/pdp/static/js/hydro_stn_download.js b/pdp/static/js/hydro_stn_download.js index c63e6646..9cb8d018 100644 --- a/pdp/static/js/hydro_stn_download.js +++ b/pdp/static/js/hydro_stn_download.js @@ -3,11 +3,8 @@ "use strict"; -function show_permalinks(base_urls, extension) { - var url_list, d, p; - url_list = $.map(base_urls, function (url) { - return url + "." + extension; - }); +function show_permalinks(url_list) { + var d, p; d = pdp.createDiv("permalink-dialog"); p = d.appendChild(document.createElement("p")); p.appendChild(document.createTextNode(url_list.join("\n"))); diff --git a/requirements.txt b/requirements.txt index f8d963ff..b5df1667 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,8 +42,6 @@ pupynere-pdp==2.0.1 PyCDS==2.2.1 PyCRS==1.0.2 pycrypto==2.6.1 -Pydap==3.2.2 -pydap_extras #pygobject==3.26.1 - not available, lack doesn't seem to matter pystache==0.5.4 python-dateutil==2.6.1 From 10049bc4e58d6a4731fb733f2aa1f9906d858215 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:44:12 -0700 Subject: [PATCH 22/71] Update automated tests to handle ORCA redirects and obtaining responses from ORCA urls --- tests/test_functional.py | 184 ++++++++++++++++++++++----------------- tests/test_hdf5.py | 85 ++++++++++++------ 2 files changed, 161 insertions(+), 108 deletions(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index cb669c3b..73eb37ac 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -7,6 +7,8 @@ import os from pkg_resources import resource_filename import static +from pdp_util import session_scope +from modelmeta import DataFile import pytest from webob.request import Request @@ -18,6 +20,29 @@ from bs4 import BeautifulSoup +def is_valid_orca_nc_url(url_id, resp): + orca_base = os.getenv("ORCA_ROOT") + with session_scope(os.getenv("DSN")) as sesh: + q = sesh.query(DataFile.filename).filter(DataFile.filename.contains(url_id)) + storage_path = q.one()[0].strip("/") + + assert resp.status == "301 Moved Permanently" + assert resp.content_type == "text/plain" + assert all(dim in resp.location for dim in ["time", "lat", "lon"]) + assert orca_base in resp.location + assert storage_path in resp.location + return True + + +def is_valid_orca_csv_url(storage_path, resp): + orca_base = os.getenv("ORCA_ROOT") + assert resp.status == "301 Moved Permanently" + assert resp.content_type == "text/plain" + assert orca_base in resp.location + assert storage_path in resp.location + return True + + @pytest.mark.parametrize('url', [ '/js/crmp_map.js', '/css/main.css', '/images/banner.png', '/robots.txt' ]) @@ -404,12 +429,16 @@ def test_climatology_bounds(pcic_data_portal): '.nc.nc?climatology_bnds&' req = Request.blank(url) resp = req.get_response(pcic_data_portal) + url_id = os.path.basename(url).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' f = NamedTemporaryFile(suffix='.nc', delete=False) - for block in resp.app_iter: + for block in orca_resp.app_iter: f.write(block) f.close() @@ -433,45 +462,33 @@ def test_climatology_bounds(pcic_data_portal): nc.close() os.remove(f.name) - @pytest.mark.slow @pytest.mark.bulk_data @pytest.mark.parametrize('url', [ # has NODATA values - '{}BCCAQv2+ANUSPLIN300_CanESM2_historical+rcp26_r1i1p1_19500101-21001231'\ - '.nc.aig?tasmax[0:30][77:138][129:238]&', - '{}BCCAQv2+ANUSPLIN300_CanESM2_historical+rcp26_r1i1p1_19500101-21001231'\ - '.nc.aig?tasmax[0:30][144:236][307:348]&', + '/data/bc_prism/bc_tmin_monthly_CAI_timeseries_19500101_20071231.nc.nc?tmin[0:30][77:138][129:238]&', + '/data/downscaled_gcms/pr_day_BCCAQv2+ANUSPLIN300_CanESM2_historical+rcp26_r1i1p1_19500101-21001231'\ + '.nc.nc?pr[0:30][77:138][129:238]&', + '/data/downscaled_gcms/pr_day_BCCAQv2+ANUSPLIN300_CanESM2_historical+rcp26_r1i1p1_19500101-21001231'\ + '.nc.nc?pr[0:30][144:236][307:348]&', + '/data/downscaled_cmip6/tasmin_day_BCCAQv2+ANUSPLIN300_CanESM5_historical+ssp126_r1i1p2f1_gn_19500101-21001231'\ + '.nc.nc?tasmin[0:30][77:138][129:238]&', + '/data/downscaled_canesm5/tasmax_day_BCCAQv2+ANUSPLIN300_CanESM5_historical+ssp126_r10i1p2f1_gn_19500101-21001231'\ + '.nc.nc?tasmax[0:30][77:138][129:238]&', + '/data/gridded_observations/PNWNAmet_wind.nc.nc?wind[0:30][77:138][129:238]&', + '/data/hydro_model_archive/5var_day_CCSM3_A1B_run1_19500101-20991231.nc.nc?sm[0:30][77:138][129:205]&', + '/data/hydro_model_out/allwsbc.ACCESS1-0_rcp85_r1i1p1.1945to2099.BASEFLOW.nc.nc?BASEFLOW[0:30][77:138][129:238]&', ]) -def test_aaigrid_response(pcic_data_portal, url): - base = '/data/downscaled_gcms/pr_day_' - req = Request.blank(url.format(base)) - resp = req.get_response(pcic_data_portal) - - assert resp.status == '200 OK' - assert resp.content_type == 'application/zip' - - -@pytest.mark.slow -@pytest.mark.bulk_data -@pytest.mark.parametrize( - 'layers', - [0, 1, 100, pytest.param(38000, marks=pytest.mark.veryslow)] -) -def test_aaigrid_response_layers(pcic_data_portal, layers): - url = '/data/hydro_model_archive/pr+tasmin+tasmax+wind_day_HadCM_A1B_'\ - 'run1_19500101-21001231.nc.aig?pr[0:{}][119:120]'\ - '[242:243]&'.format(layers) +def test_nc_raster_response(pcic_data_portal, url): req = Request.blank(url) resp = req.get_response(pcic_data_portal) + url_id = os.path.basename(url).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) - assert resp.status == '200 OK' - assert resp.content_type == 'application/zip' - t = TemporaryFile() - t.write(resp.body) - z = ZipFile(t, 'r') - - assert len(z.namelist()) == (layers + 1) * 2 + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' @pytest.mark.parametrize(('portal', 'ensemble'), [ @@ -498,7 +515,7 @@ def test_hydro_stn_data_catalog(pcic_data_portal): resp = req.get_response(pcic_data_portal) assert resp.status == '200 OK' assert resp.content_type == 'application/json' - assert '/hydro_stn/08KE009_Fraser.csv' in resp.body + assert '/hydro_stn/08KE009_Fraser.csv' in resp.body.decode("utf-8") data = json.loads(resp.body) assert len(data) > 0 @@ -506,47 +523,30 @@ def test_hydro_stn_data_catalog(pcic_data_portal): @pytest.mark.slow @pytest.mark.bulk_data def test_hydro_stn_data_csv_csv(pcic_data_portal): - url = '/data/hydro_stn_archive/BCHSCA_Campbell.csv.csv' + url = '/data/hydro_stn_archive/BCHSCA_Campbell.csv' req = Request.blank(url) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'text/plain' - for line in resp.app_iter: - expected = '1955/01/01, 32.631008, 32.631008, 32.631008, '\ - '33.079967, 33.079967, 33.079967, 59.947227, 59.947227, '\ - '59.947227, 43.419338, 43.419338, 43.419338, 63.866467, '\ - '63.866467, 63.866467, 43.944351, 43.944351, 43.944351, '\ - '57.583118, 57.583118, 102.247162, 102.247162, '\ - '102.247162, 63.068111' - if line.strip() == expected: + storage_root = "/storage/data/projects/dataportal/data/hydrology/vic_gen1_followup/vic_gen1_routed" + url_id = os.path.basename(url) + storage_path = storage_root + "/" + url_id + assert is_valid_orca_csv_url(storage_path, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'text/csv' + for line in orca_resp.app_iter[0].decode("utf-8").split("\n"): + expected = '"1955/01/01",32.631008,32.631008,32.631008,'\ + '33.079967,33.079967,33.079967,59.947227,59.947227,'\ + '59.947227,43.419338,43.419338,43.419338,63.866467,'\ + '63.866467,63.866467,43.944351,43.944351,43.944351,'\ + '57.583118,57.583118,102.247162,102.247162,'\ + '102.247162,63.068111' + if line.rstrip() == expected: assert True return - assert False, "Data line for 1950/1/1 does not exist" - - -@pytest.mark.slow -@pytest.mark.bulk_data -def test_hydro_stn_data_csv_selection_projection(pcic_data_portal): - url = '/data/hydro_stn_archive/BCHSCA_Campbell.csv.csv?'\ - 'sequence.ccsm3_A2run1&sequence.ccsm3_A2run1>100' - req = Request.blank(url) - resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'text/plain' - assert resp.body.startswith('''sequence -ccsm3_A2run1 -141.908493 -202.578568 -170.861588 -106.241058 -173.305725 -151.517075 -347.067352 -330.152252 -249.092026 -146.530792 -137.407532''') + assert False, "Data line for 1955/1/1 does not exist" @pytest.mark.bulk_data @@ -557,7 +557,7 @@ def test_hydro_model_archive_catalog(pcic_data_portal): assert resp.status == '200 OK' assert resp.content_type == 'application/json' assert 'hydro_model_archive/5var_day_HadCM_B1_run1_19500101-'\ - '20981231.nc' in resp.body + '20981231.nc' in resp.body.decode("utf-8") data = json.loads(resp.body) assert len(data) > 0 @@ -573,8 +573,13 @@ def test_hydro_model_archive_5var(pcic_data_portal, url): base = '/data/hydro_model_archive/5var_day_' req = Request.blank(url.format(base)) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + url_id = os.path.basename(url.format(base)).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' @pytest.mark.bulk_data @@ -587,8 +592,13 @@ def test_hydro_model_archive_pr_tasmin_tasmax_wind(pcic_data_portal, url): base = '/data/hydro_model_archive/pr+tasmin+tasmax+wind_day_' req = Request.blank(url.format(base)) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + url_id = os.path.basename(url.format(base)).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' @pytest.mark.slow @@ -607,11 +617,16 @@ def test_empty_hyperslabs(pcic_data_portal, projection, length): '.nc.nc?{}{}'.format(varname, projection) req = Request.blank(url) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + url_id = os.path.basename(url).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' f = NamedTemporaryFile(suffix='.nc', delete=False) - for block in resp.app_iter: + for block in orca_resp.app_iter: f.write(block) f.close() @@ -639,11 +654,16 @@ def test_nonrecord_variables(pcic_data_portal, file, expected_mean): url = "/data/downscaled_gcms/{}".format(file) req = Request.blank(url) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + url_id = os.path.basename(url).split(".nc")[0] + assert is_valid_orca_nc_url(url_id, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' f = NamedTemporaryFile(suffix='.nc', delete=False) - for block in resp.app_iter: + for block in orca_resp.app_iter: f.write(block) f.close() diff --git a/tests/test_hdf5.py b/tests/test_hdf5.py index c6cd54b1..bdcbdfd9 100644 --- a/tests/test_hdf5.py +++ b/tests/test_hdf5.py @@ -6,6 +6,24 @@ import netCDF4 +from pdp_util import session_scope +from modelmeta import DataFile + + +def is_valid_orca_url(url_id, resp, nc_request=True): + orca_base = os.getenv("ORCA_ROOT") + with session_scope(os.getenv("DSN")) as sesh: + q = sesh.query(DataFile.filename).filter(DataFile.filename.contains(url_id)) + storage_path = q.one()[0].strip("/") + + assert resp.status == "301 Moved Permanently" + assert resp.content_type == "text/plain" + if nc_request: + assert all(dim in resp.location for dim in ["time", "lat", "lon"]) + assert orca_base in resp.location + assert storage_path in resp.location + return True + def test_can_instantiate_raster_pydap(raster_pydap): assert isinstance(raster_pydap, object) @@ -14,10 +32,10 @@ def test_can_instantiate_raster_pydap(raster_pydap): @pytest.mark.slow @pytest.mark.bulk_data def test_hdf5_to_netcdf(pcic_data_portal): - req = Request.blank( - '/data/downscaled_gcms/pr_day_BCCAQv2+' - 'ANUSPLIN300_CCSM4_historical+rcp26_r2i1p1_19500101-' - '21001231.nc.nc?pr[0:1:1][116:167][84:144]&') + url = '/data/downscaled_gcms/pr_day_BCCAQv2+'\ + 'ANUSPLIN300_CCSM4_historical+rcp26_r2i1p1_19500101-'\ + '21001231.nc.nc?pr[0:1:1][116:167][84:144]&' + req = Request.blank(url) # https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets # /downscaled_gcms_archive/pr+tasmax+tasmin_day_BCCAQ+ @@ -29,11 +47,16 @@ def test_hdf5_to_netcdf(pcic_data_portal): print("resp in test function is") print(resp.body) - assert resp.status == '200 OK' - assert resp.content_type == 'application/x-netcdf' + url_id = os.path.basename(url).split(".nc")[0] + assert is_valid_orca_url(url_id, resp) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'application/x-netcdf' f = NamedTemporaryFile(suffix='.nc') - for block in resp.app_iter: + for block in orca_resp.app_iter: f.write(block) # for now, just check that netCDF4 can open it and that's good enough @@ -44,35 +67,45 @@ def test_hdf5_to_netcdf(pcic_data_portal): @pytest.mark.bulk_data def test_prism_response(pcic_data_portal): - req = Request.blank( - '/data/bc_prism/pr_mClimMean_PRISM_historical_19710101-20001231' - '.nc.html') + url = '/data/bc_prism/pr_mClimMean_PRISM_historical_19710101-20001231'\ + '.nc.html' + req = Request.blank(url) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type == 'text/html' + url_id = os.path.basename(url).split(".html")[0] + assert is_valid_orca_url(url_id, resp, nc_request=False) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type == 'text/html' @pytest.mark.bulk_data def test_dds_response(pcic_data_portal): - req = Request.blank( - '/data/downscaled_gcms/pr_day_BCCAQv2+' - 'ANUSPLIN300_CCSM4_historical+rcp26_r2i1p1_19500101-' - '21001231.nc.dds') + url = '/data/downscaled_gcms/pr_day_BCCAQv2+'\ + 'ANUSPLIN300_CCSM4_historical+rcp26_r2i1p1_19500101-'\ + '21001231.nc.dds' + req = Request.blank(url) resp = req.get_response(pcic_data_portal) - assert resp.status == '200 OK' - assert resp.content_type.startswith('text/plain') - body = ''.join([x for x in resp.app_iter]) + url_id = os.path.basename(url).split(".dds")[0] + assert is_valid_orca_url(url_id, resp, nc_request=False) + + orca_req = Request.blank(resp.location) + orca_resp = orca_req.get_response() + assert orca_resp.status == '200 OK' + assert orca_resp.content_type.startswith('application/octet-stream') + body = ''.join([x.decode("utf-8") for x in orca_resp.app_iter]) assert body == '''Dataset { Float64 lon[lon = 1068]; Float64 lat[lat = 510]; Float64 time[time = 55115]; Grid { - Array: - Int16 pr[time = 55115][lat = 510][lon = 1068]; - Maps: - Float64 time[time = 55115]; - Float64 lat[lat = 510]; - Float64 lon[lon = 1068]; + ARRAY: + Int16 pr[time = 55115][lat = 510][lon = 1068]; + MAPS: + Float64 time[time = 55115]; + Float64 lat[lat = 510]; + Float64 lon[lon = 1068]; } pr; -} pr_day_BCCAQv2%2BANUSPLIN300_CCSM4_historical%2Brcp26_r2i1p1_19500101-21001231%2Enc; +} datasets/storage/data/climate/downscale/BCCAQ2/bccaqv2_with_metadata/pr_day_BCCAQv2%2bANUSPLIN300_CCSM4_historical%2brcp26_r2i1p1_19500101-21001231.nc; ''' # noqa: E501 From f42b02c7ca01a9f1e7e79dc53b69dd159095f5f0 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:47:19 -0700 Subject: [PATCH 23/71] Update package-lock.json after having fun npm install --- package-lock.json | 2406 +++++++++++++++++---------------------------- 1 file changed, 925 insertions(+), 1481 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11a94ab6..ea423a2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "7.0.0" } }, "@babel/core": { @@ -19,20 +19,20 @@ "integrity": "sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helpers": "^7.4.3", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.11", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.4.0", + "@babel/helpers": "7.4.3", + "@babel/parser": "7.4.3", + "@babel/template": "7.4.0", + "@babel/traverse": "7.4.3", + "@babel/types": "7.4.0", + "convert-source-map": "1.6.0", + "debug": "4.1.1", + "json5": "2.1.0", + "lodash": "4.17.21", + "resolve": "1.10.0", + "semver": "5.7.0", + "source-map": "0.5.7" }, "dependencies": { "debug": { @@ -41,7 +41,7 @@ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -64,11 +64,11 @@ "integrity": "sha512-/v5I+a1jhGSKLgZDcmAUZ4K/VePi43eRkUs3yePW1HB1iANOD5tqJXwGSG4BZhSksP8J9ejSlwGeTiiOFZOrXQ==", "dev": true, "requires": { - "@babel/types": "^7.4.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.11", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" + "@babel/types": "7.4.0", + "jsesc": "2.5.2", + "lodash": "4.17.21", + "source-map": "0.5.7", + "trim-right": "1.0.1" }, "dependencies": { "source-map": { @@ -85,9 +85,9 @@ "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/helper-get-function-arity": "7.0.0", + "@babel/template": "7.4.0", + "@babel/types": "7.4.0" } }, "@babel/helper-get-function-arity": { @@ -96,7 +96,7 @@ "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.4.0" } }, "@babel/helper-plugin-utils": { @@ -111,7 +111,7 @@ "integrity": "sha512-7Cuc6JZiYShaZnybDmfwhY4UYHzI6rlqhWjaIqbsJGsIqPimEYy5uh3akSRLMg65LSdSEnJ8a8/bWQN6u2oMGw==", "dev": true, "requires": { - "@babel/types": "^7.4.0" + "@babel/types": "7.4.0" } }, "@babel/helpers": { @@ -120,9 +120,9 @@ "integrity": "sha512-BMh7X0oZqb36CfyhvtbSmcWc3GXocfxv3yNsAEuM0l+fAqSO22rQrUpijr3oE/10jCTrB6/0b9kzmG4VetCj8Q==", "dev": true, "requires": { - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0" + "@babel/template": "7.4.0", + "@babel/traverse": "7.4.3", + "@babel/types": "7.4.0" } }, "@babel/highlight": { @@ -131,9 +131,9 @@ "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", "dev": true, "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "chalk": "2.4.2", + "esutils": "2.0.2", + "js-tokens": "4.0.0" } }, "@babel/parser": { @@ -148,7 +148,7 @@ "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "7.0.0" } }, "@babel/template": { @@ -157,9 +157,9 @@ "integrity": "sha512-SOWwxxClTTh5NdbbYZ0BmaBVzxzTh2tO/TeLTbF6MO6EzVhHTnff8CdBXx3mEtazFBoysmEM6GU/wF+SuSx4Fw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.0", - "@babel/types": "^7.4.0" + "@babel/code-frame": "7.0.0", + "@babel/parser": "7.4.3", + "@babel/types": "7.4.0" } }, "@babel/traverse": { @@ -168,15 +168,15 @@ "integrity": "sha512-HmA01qrtaCwwJWpSKpA948cBvU5BrmviAief/b3AVw936DtcdsTexlbyzNuDnthwhOQ37xshn7hvQaEQk7ISYQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/generator": "^7.4.0", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/types": "^7.4.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.11" + "@babel/code-frame": "7.0.0", + "@babel/generator": "7.4.0", + "@babel/helper-function-name": "7.1.0", + "@babel/helper-split-export-declaration": "7.4.0", + "@babel/parser": "7.4.3", + "@babel/types": "7.4.0", + "debug": "4.1.1", + "globals": "11.11.0", + "lodash": "4.17.21" }, "dependencies": { "debug": { @@ -185,7 +185,7 @@ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -202,9 +202,9 @@ "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.11", - "to-fast-properties": "^2.0.0" + "esutils": "2.0.2", + "lodash": "4.17.21", + "to-fast-properties": "2.0.0" } }, "@cnakazawa/watch": { @@ -213,8 +213,8 @@ "integrity": "sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA==", "dev": true, "requires": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" + "exec-sh": "0.3.2", + "minimist": "1.2.0" } }, "@jest/console": { @@ -223,9 +223,9 @@ "integrity": "sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg==", "dev": true, "requires": { - "@jest/source-map": "^24.3.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" + "@jest/source-map": "24.3.0", + "chalk": "2.4.2", + "slash": "2.0.0" } }, "@jest/core": { @@ -234,33 +234,33 @@ "integrity": "sha512-ivlZ8HX/FOASfHcb5DJpSPFps8ydfUYzLZfgFFqjkLijYysnIEOieg72YRhO4ZUB32xu40hsSMmaw+IGYeKONA==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/reporters": "^24.7.1", - "@jest/test-result": "^24.7.1", - "@jest/transform": "^24.7.1", - "@jest/types": "^24.7.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-changed-files": "^24.7.0", - "jest-config": "^24.7.1", - "jest-haste-map": "^24.7.1", - "jest-message-util": "^24.7.1", - "jest-regex-util": "^24.3.0", - "jest-resolve-dependencies": "^24.7.1", - "jest-runner": "^24.7.1", - "jest-runtime": "^24.7.1", - "jest-snapshot": "^24.7.1", - "jest-util": "^24.7.1", - "jest-validate": "^24.7.0", - "jest-watcher": "^24.7.1", - "micromatch": "^3.1.10", - "p-each-series": "^1.0.0", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "rimraf": "^2.5.4", - "strip-ansi": "^5.0.0" + "@jest/console": "24.7.1", + "@jest/reporters": "24.7.1", + "@jest/test-result": "24.7.1", + "@jest/transform": "24.7.1", + "@jest/types": "24.7.0", + "ansi-escapes": "3.2.0", + "chalk": "2.4.2", + "exit": "0.1.2", + "graceful-fs": "4.1.15", + "jest-changed-files": "24.7.0", + "jest-config": "24.7.1", + "jest-haste-map": "24.7.1", + "jest-message-util": "24.7.1", + "jest-regex-util": "24.3.0", + "jest-resolve-dependencies": "24.7.1", + "jest-runner": "24.7.1", + "jest-runtime": "24.7.1", + "jest-snapshot": "24.7.1", + "jest-util": "24.7.1", + "jest-validate": "24.7.0", + "jest-watcher": "24.7.1", + "micromatch": "3.1.10", + "p-each-series": "1.0.0", + "pirates": "4.0.1", + "realpath-native": "1.1.0", + "rimraf": "2.6.3", + "strip-ansi": "5.2.0" } }, "@jest/environment": { @@ -269,10 +269,10 @@ "integrity": "sha512-wmcTTYc4/KqA+U5h1zQd5FXXynfa7VGP2NfF+c6QeGJ7c+2nStgh65RQWNX62SC716dTtqheTRrZl0j+54oGHw==", "dev": true, "requires": { - "@jest/fake-timers": "^24.7.1", - "@jest/transform": "^24.7.1", - "@jest/types": "^24.7.0", - "jest-mock": "^24.7.0" + "@jest/fake-timers": "24.7.1", + "@jest/transform": "24.7.1", + "@jest/types": "24.7.0", + "jest-mock": "24.7.0" } }, "@jest/fake-timers": { @@ -281,9 +281,9 @@ "integrity": "sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-mock": "^24.7.0" + "@jest/types": "24.7.0", + "jest-message-util": "24.7.1", + "jest-mock": "24.7.0" } }, "@jest/reporters": { @@ -292,26 +292,26 @@ "integrity": "sha512-bO+WYNwHLNhrjB9EbPL4kX/mCCG4ZhhfWmO3m4FSpbgr7N83MFejayz30kKjgqr7smLyeaRFCBQMbXpUgnhAJw==", "dev": true, "requires": { - "@jest/environment": "^24.7.1", - "@jest/test-result": "^24.7.1", - "@jest/transform": "^24.7.1", - "@jest/types": "^24.7.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "istanbul-api": "^2.1.1", - "istanbul-lib-coverage": "^2.0.2", - "istanbul-lib-instrument": "^3.0.1", - "istanbul-lib-source-maps": "^3.0.1", - "jest-haste-map": "^24.7.1", - "jest-resolve": "^24.7.1", - "jest-runtime": "^24.7.1", - "jest-util": "^24.7.1", - "jest-worker": "^24.6.0", - "node-notifier": "^5.2.1", - "slash": "^2.0.0", - "source-map": "^0.6.0", - "string-length": "^2.0.0" + "@jest/environment": "24.7.1", + "@jest/test-result": "24.7.1", + "@jest/transform": "24.7.1", + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "exit": "0.1.2", + "glob": "7.1.3", + "istanbul-api": "2.1.1", + "istanbul-lib-coverage": "2.0.3", + "istanbul-lib-instrument": "3.1.0", + "istanbul-lib-source-maps": "3.0.2", + "jest-haste-map": "24.7.1", + "jest-resolve": "24.7.1", + "jest-runtime": "24.7.1", + "jest-util": "24.7.1", + "jest-worker": "24.6.0", + "node-notifier": "5.4.0", + "slash": "2.0.0", + "source-map": "0.6.1", + "string-length": "2.0.0" } }, "@jest/source-map": { @@ -320,9 +320,9 @@ "integrity": "sha512-zALZt1t2ou8le/crCeeiRYzvdnTzaIlpOWaet45lNSqNJUnXbppUUFR4ZUAlzgDmKee4Q5P/tKXypI1RiHwgag==", "dev": true, "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" + "callsites": "3.1.0", + "graceful-fs": "4.1.15", + "source-map": "0.6.1" } }, "@jest/test-result": { @@ -331,9 +331,9 @@ "integrity": "sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/types": "^24.7.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "@jest/console": "24.7.1", + "@jest/types": "24.7.0", + "@types/istanbul-lib-coverage": "2.0.0" } }, "@jest/test-sequencer": { @@ -342,10 +342,10 @@ "integrity": "sha512-84HQkCpVZI/G1zq53gHJvSmhUer4aMYp9tTaffW28Ih5OxfCg8hGr3nTSbL1OhVDRrFZwvF+/R9gY6JRkDUpUA==", "dev": true, "requires": { - "@jest/test-result": "^24.7.1", - "jest-haste-map": "^24.7.1", - "jest-runner": "^24.7.1", - "jest-runtime": "^24.7.1" + "@jest/test-result": "24.7.1", + "jest-haste-map": "24.7.1", + "jest-runner": "24.7.1", + "jest-runtime": "24.7.1" } }, "@jest/transform": { @@ -354,20 +354,20 @@ "integrity": "sha512-EsOUqP9ULuJ66IkZQhI5LufCHlTbi7hrcllRMUEV/tOgqBVQi93+9qEvkX0n8mYpVXQ8VjwmICeRgg58mrtIEw==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^24.7.0", - "babel-plugin-istanbul": "^5.1.0", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.15", - "jest-haste-map": "^24.7.1", - "jest-regex-util": "^24.3.0", - "jest-util": "^24.7.1", - "micromatch": "^3.1.10", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "source-map": "^0.6.1", + "@babel/core": "7.4.3", + "@jest/types": "24.7.0", + "babel-plugin-istanbul": "5.1.1", + "chalk": "2.4.2", + "convert-source-map": "1.6.0", + "fast-json-stable-stringify": "2.0.0", + "graceful-fs": "4.1.15", + "jest-haste-map": "24.7.1", + "jest-regex-util": "24.3.0", + "jest-util": "24.7.1", + "micromatch": "3.1.10", + "realpath-native": "1.1.0", + "slash": "2.0.0", + "source-map": "0.6.1", "write-file-atomic": "2.4.1" } }, @@ -377,8 +377,8 @@ "integrity": "sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/yargs": "^12.0.9" + "@types/istanbul-lib-coverage": "2.0.0", + "@types/yargs": "12.0.12" } }, "@types/babel__core": { @@ -387,11 +387,11 @@ "integrity": "sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@babel/parser": "7.4.3", + "@babel/types": "7.4.0", + "@types/babel__generator": "7.0.2", + "@types/babel__template": "7.0.2", + "@types/babel__traverse": "7.0.6" } }, "@types/babel__generator": { @@ -400,7 +400,7 @@ "integrity": "sha512-NHcOfab3Zw4q5sEE2COkpfXjoE7o+PmqD9DQW4koUT3roNxwziUdXGnRndMat/LJNUtePwn1TlP4do3uoe3KZQ==", "dev": true, "requires": { - "@babel/types": "^7.0.0" + "@babel/types": "7.4.0" } }, "@types/babel__template": { @@ -409,8 +409,8 @@ "integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@babel/parser": "7.4.3", + "@babel/types": "7.4.0" } }, "@types/babel__traverse": { @@ -419,7 +419,7 @@ "integrity": "sha512-XYVgHF2sQ0YblLRMLNPB3CkFMewzFmlDsH/TneZFHUXDlABQgh88uOxuez7ZcXxayLFrqLwtDH1t+FmlFwNZxw==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "7.4.0" } }, "@types/istanbul-lib-coverage": { @@ -458,8 +458,8 @@ "integrity": "sha512-gJSiKY8dBIjV/0jagZIFBdVMtfQyA5QHCvAT48H2q8REQoW8Fs5AOjqBql1LgSXgrMWdevcE+8cdZ33NtVbIBA==", "dev": true, "requires": { - "acorn": "^6.0.1", - "acorn-walk": "^6.0.1" + "acorn": "6.4.1", + "acorn-walk": "6.1.1" }, "dependencies": { "acorn": { @@ -482,10 +482,10 @@ "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" } }, "ansi-escapes": { @@ -506,7 +506,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.3" } }, "anymatch": { @@ -515,8 +515,8 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "micromatch": "3.1.10", + "normalize-path": "2.1.1" } }, "append-transform": { @@ -525,7 +525,7 @@ "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", "dev": true, "requires": { - "default-require-extensions": "^2.0.0" + "default-require-extensions": "2.0.0" } }, "argparse": { @@ -534,7 +534,7 @@ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "arr-diff": { @@ -579,7 +579,7 @@ "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", "dev": true, "requires": { - "safer-buffer": "~2.1.0" + "safer-buffer": "2.1.2" } }, "assert-plus": { @@ -606,7 +606,7 @@ "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "4.17.21" } }, "async-limiter": { @@ -645,13 +645,13 @@ "integrity": "sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg==", "dev": true, "requires": { - "@jest/transform": "^24.7.1", - "@jest/types": "^24.7.0", - "@types/babel__core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", - "babel-preset-jest": "^24.6.0", - "chalk": "^2.4.2", - "slash": "^2.0.0" + "@jest/transform": "24.7.1", + "@jest/types": "24.7.0", + "@types/babel__core": "7.1.1", + "babel-plugin-istanbul": "5.1.1", + "babel-preset-jest": "24.6.0", + "chalk": "2.4.2", + "slash": "2.0.0" } }, "babel-plugin-istanbul": { @@ -660,9 +660,9 @@ "integrity": "sha512-RNNVv2lsHAXJQsEJ5jonQwrJVWK8AcZpG1oxhnjCUaAjL7xahYLANhPUZbzEQHjKy1NMYUwn+0NPKQc8iSY4xQ==", "dev": true, "requires": { - "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.0.0", - "test-exclude": "^5.0.0" + "find-up": "3.0.0", + "istanbul-lib-instrument": "3.1.0", + "test-exclude": "5.1.0" } }, "babel-plugin-jest-hoist": { @@ -671,7 +671,7 @@ "integrity": "sha512-3pKNH6hMt9SbOv0F3WVmy5CWQ4uogS3k0GY5XLyQHJ9EGpAT9XWkFd2ZiXXtkwFHdAHa5j7w7kfxSP5lAIwu7w==", "dev": true, "requires": { - "@types/babel__traverse": "^7.0.6" + "@types/babel__traverse": "7.0.6" } }, "babel-preset-jest": { @@ -680,8 +680,8 @@ "integrity": "sha512-pdZqLEdmy1ZK5kyRUfvBb2IfTPb2BUvIJczlPspS8fWmBQslNNDBqVfh7BW5leOVJMDZKzjD8XEyABTk6gQ5yw==", "dev": true, "requires": { - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^24.6.0" + "@babel/plugin-syntax-object-rest-spread": "7.2.0", + "babel-plugin-jest-hoist": "24.6.0" } }, "balanced-match": { @@ -696,13 +696,13 @@ "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.2", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -711,7 +711,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -720,7 +720,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -729,7 +729,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -738,9 +738,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -751,7 +751,7 @@ "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "brace-expansion": { @@ -760,7 +760,7 @@ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -770,16 +770,16 @@ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { "extend-shallow": { @@ -788,7 +788,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -822,7 +822,7 @@ "integrity": "sha1-mseNPtXZFYBP2HrLFYvHlxR6Fxk=", "dev": true, "requires": { - "node-int64": "^0.4.0" + "node-int64": "0.4.0" } }, "buffer-from": { @@ -837,15 +837,15 @@ "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" } }, "callsites": { @@ -866,7 +866,7 @@ "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", "dev": true, "requires": { - "rsvp": "^4.8.4" + "rsvp": "4.8.4" } }, "caseless": { @@ -881,9 +881,9 @@ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" } }, "ci-info": { @@ -898,10 +898,10 @@ "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -910,7 +910,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -921,9 +921,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" }, "dependencies": { "ansi-regex": { @@ -938,7 +938,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -961,8 +961,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color-convert": { @@ -986,7 +986,7 @@ "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "commander": { @@ -1020,7 +1020,7 @@ "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "safe-buffer": "5.1.2" } }, "copy-descriptor": { @@ -1041,11 +1041,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.5", + "path-key": "2.0.1", + "semver": "5.7.0", + "shebang-command": "1.2.0", + "which": "1.3.1" } }, "cssfontparser": { @@ -1066,7 +1066,7 @@ "integrity": "sha512-43wY3kl1CVQSvL7wUY1qXkxVGkStjpkDmVjiIKX8R97uhajy8Bybay78uOtqvh7Q5GK75dNPfW0geWjE6qQQow==", "dev": true, "requires": { - "cssom": "0.3.x" + "cssom": "0.3.6" } }, "dashdash": { @@ -1075,7 +1075,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "data-urls": { @@ -1084,9 +1084,9 @@ "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", "dev": true, "requires": { - "abab": "^2.0.0", - "whatwg-mimetype": "^2.2.0", - "whatwg-url": "^7.0.0" + "abab": "2.0.0", + "whatwg-mimetype": "2.3.0", + "whatwg-url": "7.0.0" }, "dependencies": { "whatwg-url": { @@ -1095,9 +1095,9 @@ "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" } } } @@ -1135,7 +1135,7 @@ "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", "dev": true, "requires": { - "strip-bom": "^3.0.0" + "strip-bom": "3.0.0" } }, "define-properties": { @@ -1144,7 +1144,7 @@ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "object-keys": "1.1.1" } }, "define-property": { @@ -1153,8 +1153,8 @@ "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" }, "dependencies": { "is-accessor-descriptor": { @@ -1163,7 +1163,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -1172,7 +1172,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -1181,9 +1181,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -1212,7 +1212,7 @@ "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", "dev": true, "requires": { - "webidl-conversions": "^4.0.2" + "webidl-conversions": "4.0.2" } }, "ecc-jsbn": { @@ -1221,8 +1221,8 @@ "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" } }, "end-of-stream": { @@ -1231,7 +1231,7 @@ "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "dev": true, "requires": { - "once": "^1.4.0" + "once": "1.4.0" } }, "error-ex": { @@ -1240,7 +1240,7 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "es-abstract": { @@ -1249,12 +1249,12 @@ "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "es-to-primitive": "1.2.0", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.4", + "is-regex": "1.0.4", + "object-keys": "1.1.1" } }, "es-to-primitive": { @@ -1263,9 +1263,9 @@ "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "1.1.4", + "is-date-object": "1.0.1", + "is-symbol": "1.0.2" } }, "escape-string-regexp": { @@ -1280,11 +1280,11 @@ "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" }, "dependencies": { "esprima": { @@ -1325,13 +1325,13 @@ "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" } }, "exit": { @@ -1346,13 +1346,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -1361,7 +1361,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -1370,7 +1370,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -1381,12 +1381,12 @@ "integrity": "sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.3.0", - "jest-matcher-utils": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-regex-util": "^24.3.0" + "@jest/types": "24.7.0", + "ansi-styles": "3.2.1", + "jest-get-type": "24.3.0", + "jest-matcher-utils": "24.7.0", + "jest-message-util": "24.7.1", + "jest-regex-util": "24.3.0" } }, "extend": { @@ -1401,8 +1401,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -1411,7 +1411,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -1422,14 +1422,14 @@ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -1438,7 +1438,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -1447,7 +1447,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -1456,7 +1456,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -1465,7 +1465,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -1474,9 +1474,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -1511,7 +1511,7 @@ "integrity": "sha1-VOmr99+i8mzZsWNsWIwa/AXeXVg=", "dev": true, "requires": { - "bser": "^2.0.0" + "bser": "2.0.0" } }, "fileset": { @@ -1520,8 +1520,8 @@ "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", "dev": true, "requires": { - "glob": "^7.0.3", - "minimatch": "^3.0.3" + "glob": "7.1.3", + "minimatch": "3.0.4" } }, "fill-range": { @@ -1530,10 +1530,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" }, "dependencies": { "extend-shallow": { @@ -1542,7 +1542,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -1553,7 +1553,7 @@ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "locate-path": "^3.0.0" + "locate-path": "3.0.0" } }, "for-in": { @@ -1574,9 +1574,9 @@ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.22" } }, "fragment-cache": { @@ -1585,7 +1585,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fs.realpath": { @@ -1594,554 +1594,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", - "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2160,7 +1612,7 @@ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { - "pump": "^3.0.0" + "pump": "3.0.0" } }, "get-value": { @@ -2175,7 +1627,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" } }, "glob": { @@ -2184,12 +1636,12 @@ "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "globals": { @@ -2216,11 +1668,11 @@ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", "dev": true, "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" + "minimist": "1.2.5", + "neo-async": "2.6.0", + "source-map": "0.6.1", + "uglify-js": "3.5.4", + "wordwrap": "1.0.0" }, "dependencies": { "minimist": { @@ -2249,8 +1701,8 @@ "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" + "ajv": "6.10.0", + "har-schema": "2.0.0" } }, "has": { @@ -2259,7 +1711,7 @@ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "function-bind": "^1.1.1" + "function-bind": "1.1.1" } }, "has-flag": { @@ -2280,9 +1732,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -2291,8 +1743,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -2301,7 +1753,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2318,7 +1770,7 @@ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "dev": true, "requires": { - "whatwg-encoding": "^1.0.1" + "whatwg-encoding": "1.0.5" } }, "http-signature": { @@ -2327,9 +1779,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.16.1" } }, "iconv-lite": { @@ -2338,7 +1790,7 @@ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": "2.1.2" } }, "import-local": { @@ -2347,8 +1799,8 @@ "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", "dev": true, "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" + "pkg-dir": "3.0.0", + "resolve-cwd": "2.0.0" } }, "imurmurhash": { @@ -2363,8 +1815,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -2379,7 +1831,7 @@ "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.4.0" } }, "invert-kv": { @@ -2394,7 +1846,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -2403,7 +1855,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2432,7 +1884,7 @@ "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", "dev": true, "requires": { - "ci-info": "^2.0.0" + "ci-info": "2.0.0" } }, "is-data-descriptor": { @@ -2441,7 +1893,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -2450,7 +1902,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2467,9 +1919,9 @@ "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -2504,7 +1956,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -2513,7 +1965,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2524,7 +1976,7 @@ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "is-regex": { @@ -2533,7 +1985,7 @@ "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "dev": true, "requires": { - "has": "^1.0.1" + "has": "1.0.3" } }, "is-stream": { @@ -2548,7 +2000,7 @@ "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "1.0.0" } }, "is-typedarray": { @@ -2599,19 +2051,19 @@ "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", "dev": true, "requires": { - "async": "^2.6.1", - "compare-versions": "^3.2.1", - "fileset": "^2.0.3", - "istanbul-lib-coverage": "^2.0.3", - "istanbul-lib-hook": "^2.0.3", - "istanbul-lib-instrument": "^3.1.0", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.2", - "istanbul-reports": "^2.1.1", - "js-yaml": "^3.12.0", - "make-dir": "^1.3.0", - "minimatch": "^3.0.4", - "once": "^1.4.0" + "async": "2.6.2", + "compare-versions": "3.4.0", + "fileset": "2.0.3", + "istanbul-lib-coverage": "2.0.3", + "istanbul-lib-hook": "2.0.3", + "istanbul-lib-instrument": "3.1.0", + "istanbul-lib-report": "2.0.4", + "istanbul-lib-source-maps": "3.0.2", + "istanbul-reports": "2.1.1", + "js-yaml": "3.13.1", + "make-dir": "1.3.0", + "minimatch": "3.0.4", + "once": "1.4.0" } }, "istanbul-lib-coverage": { @@ -2626,7 +2078,7 @@ "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", "dev": true, "requires": { - "append-transform": "^1.0.0" + "append-transform": "1.0.0" } }, "istanbul-lib-instrument": { @@ -2635,13 +2087,13 @@ "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", "dev": true, "requires": { - "@babel/generator": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/template": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", - "istanbul-lib-coverage": "^2.0.3", - "semver": "^5.5.0" + "@babel/generator": "7.4.0", + "@babel/parser": "7.4.3", + "@babel/template": "7.4.0", + "@babel/traverse": "7.4.3", + "@babel/types": "7.4.0", + "istanbul-lib-coverage": "2.0.3", + "semver": "5.7.0" } }, "istanbul-lib-report": { @@ -2650,9 +2102,9 @@ "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "supports-color": "^6.0.0" + "istanbul-lib-coverage": "2.0.3", + "make-dir": "1.3.0", + "supports-color": "6.1.0" }, "dependencies": { "supports-color": { @@ -2661,7 +2113,7 @@ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -2672,11 +2124,11 @@ "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", "dev": true, "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.3", - "make-dir": "^1.3.0", - "rimraf": "^2.6.2", - "source-map": "^0.6.1" + "debug": "4.1.1", + "istanbul-lib-coverage": "2.0.3", + "make-dir": "1.3.0", + "rimraf": "2.6.3", + "source-map": "0.6.1" }, "dependencies": { "debug": { @@ -2685,7 +2137,7 @@ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ms": "^2.1.1" + "ms": "2.1.1" } }, "ms": { @@ -2702,7 +2154,7 @@ "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", "dev": true, "requires": { - "handlebars": "^4.1.0" + "handlebars": "4.7.7" } }, "jest": { @@ -2711,8 +2163,8 @@ "integrity": "sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA==", "dev": true, "requires": { - "import-local": "^2.0.0", - "jest-cli": "^24.7.1" + "import-local": "2.0.0", + "jest-cli": "24.7.1" }, "dependencies": { "jest-cli": { @@ -2721,19 +2173,19 @@ "integrity": "sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ==", "dev": true, "requires": { - "@jest/core": "^24.7.1", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "import-local": "^2.0.0", - "is-ci": "^2.0.0", - "jest-config": "^24.7.1", - "jest-util": "^24.7.1", - "jest-validate": "^24.7.0", - "prompts": "^2.0.1", - "realpath-native": "^1.1.0", - "yargs": "^12.0.2" + "@jest/core": "24.7.1", + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "exit": "0.1.2", + "import-local": "2.0.0", + "is-ci": "2.0.0", + "jest-config": "24.7.1", + "jest-util": "24.7.1", + "jest-validate": "24.7.0", + "prompts": "2.0.4", + "realpath-native": "1.1.0", + "yargs": "12.0.5" } } } @@ -2744,8 +2196,8 @@ "integrity": "sha512-IFRh5a4jEhfKlJRb+UgxUM7v8OZ112K8uu2LGpewTIfRz9kU/0Yk51D6ytr8cJ6AVUWdD3SJCcxRdFuh5okVQw==", "dev": true, "requires": { - "cssfontparser": "^1.2.1", - "parse-color": "^1.0.0" + "cssfontparser": "1.2.1", + "parse-color": "1.0.0" } }, "jest-changed-files": { @@ -2754,9 +2206,9 @@ "integrity": "sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "execa": "^1.0.0", - "throat": "^4.0.0" + "@jest/types": "24.7.0", + "execa": "1.0.0", + "throat": "4.1.0" } }, "jest-config": { @@ -2765,23 +2217,23 @@ "integrity": "sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.7.1", - "@jest/types": "^24.7.0", - "babel-jest": "^24.7.1", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^24.7.1", - "jest-environment-node": "^24.7.1", - "jest-get-type": "^24.3.0", - "jest-jasmine2": "^24.7.1", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.7.1", - "jest-util": "^24.7.1", - "jest-validate": "^24.7.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.7.0", - "realpath-native": "^1.1.0" + "@babel/core": "7.4.3", + "@jest/test-sequencer": "24.7.1", + "@jest/types": "24.7.0", + "babel-jest": "24.7.1", + "chalk": "2.4.2", + "glob": "7.1.3", + "jest-environment-jsdom": "24.7.1", + "jest-environment-node": "24.7.1", + "jest-get-type": "24.3.0", + "jest-jasmine2": "24.7.1", + "jest-regex-util": "24.3.0", + "jest-resolve": "24.7.1", + "jest-util": "24.7.1", + "jest-validate": "24.7.0", + "micromatch": "3.1.10", + "pretty-format": "24.7.0", + "realpath-native": "1.1.0" } }, "jest-diff": { @@ -2790,10 +2242,10 @@ "integrity": "sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.3.0", - "jest-get-type": "^24.3.0", - "pretty-format": "^24.7.0" + "chalk": "2.4.2", + "diff-sequences": "24.3.0", + "jest-get-type": "24.3.0", + "pretty-format": "24.7.0" } }, "jest-docblock": { @@ -2802,7 +2254,7 @@ "integrity": "sha512-nlANmF9Yq1dufhFlKG9rasfQlrY7wINJbo3q01tu56Jv5eBU5jirylhF2O5ZBnLxzOVBGRDz/9NAwNyBtG4Nyg==", "dev": true, "requires": { - "detect-newline": "^2.1.0" + "detect-newline": "2.1.0" } }, "jest-each": { @@ -2811,11 +2263,11 @@ "integrity": "sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "chalk": "^2.0.1", - "jest-get-type": "^24.3.0", - "jest-util": "^24.7.1", - "pretty-format": "^24.7.0" + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "jest-get-type": "24.3.0", + "jest-util": "24.7.1", + "pretty-format": "24.7.0" } }, "jest-environment-jsdom": { @@ -2824,12 +2276,12 @@ "integrity": "sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg==", "dev": true, "requires": { - "@jest/environment": "^24.7.1", - "@jest/fake-timers": "^24.7.1", - "@jest/types": "^24.7.0", - "jest-mock": "^24.7.0", - "jest-util": "^24.7.1", - "jsdom": "^11.5.1" + "@jest/environment": "24.7.1", + "@jest/fake-timers": "24.7.1", + "@jest/types": "24.7.0", + "jest-mock": "24.7.0", + "jest-util": "24.7.1", + "jsdom": "11.12.0" } }, "jest-environment-jsdom-fourteen": { @@ -2838,9 +2290,9 @@ "integrity": "sha512-4vtoRMg7jAstitRzL4nbw83VmGH8Rs13wrND3Ud2o1fczDhMUF32iIrNKwYGgeOPUdfvZU4oy8Bbv+ni1fgVCA==", "dev": true, "requires": { - "jest-mock": "^24.5.0", - "jest-util": "^24.5.0", - "jsdom": "^14.0.0" + "jest-mock": "24.7.0", + "jest-util": "24.7.1", + "jsdom": "14.1.0" }, "dependencies": { "acorn": { @@ -2855,32 +2307,32 @@ "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", "dev": true, "requires": { - "abab": "^2.0.0", - "acorn": "^6.0.4", - "acorn-globals": "^4.3.0", - "array-equal": "^1.0.0", - "cssom": "^0.3.4", - "cssstyle": "^1.1.1", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.0", - "html-encoding-sniffer": "^1.0.2", - "nwsapi": "^2.1.3", + "abab": "2.0.0", + "acorn": "6.4.1", + "acorn-globals": "4.3.1", + "array-equal": "1.0.0", + "cssom": "0.3.6", + "cssstyle": "1.2.2", + "data-urls": "1.1.0", + "domexception": "1.0.1", + "escodegen": "1.11.1", + "html-encoding-sniffer": "1.0.2", + "nwsapi": "2.1.3", "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.5.0", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^6.1.2", - "xml-name-validator": "^3.0.0" + "pn": "1.1.0", + "request": "2.88.0", + "request-promise-native": "1.0.7", + "saxes": "3.1.9", + "symbol-tree": "3.2.2", + "tough-cookie": "2.5.0", + "w3c-hr-time": "1.0.1", + "w3c-xmlserializer": "1.1.2", + "webidl-conversions": "4.0.2", + "whatwg-encoding": "1.0.5", + "whatwg-mimetype": "2.3.0", + "whatwg-url": "7.0.0", + "ws": "6.2.2", + "xml-name-validator": "3.0.0" } }, "parse5": { @@ -2895,9 +2347,9 @@ "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" } }, "ws": { @@ -2906,7 +2358,7 @@ "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "1.0.0" } } } @@ -2917,11 +2369,11 @@ "integrity": "sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA==", "dev": true, "requires": { - "@jest/environment": "^24.7.1", - "@jest/fake-timers": "^24.7.1", - "@jest/types": "^24.7.0", - "jest-mock": "^24.7.0", - "jest-util": "^24.7.1" + "@jest/environment": "24.7.1", + "@jest/fake-timers": "24.7.1", + "@jest/types": "24.7.0", + "jest-mock": "24.7.0", + "jest-util": "24.7.1" } }, "jest-get-type": { @@ -2936,18 +2388,17 @@ "integrity": "sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.4.0", - "jest-util": "^24.7.1", - "jest-worker": "^24.6.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" + "@jest/types": "24.7.0", + "anymatch": "2.0.0", + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.15", + "invariant": "2.2.4", + "jest-serializer": "24.4.0", + "jest-util": "24.7.1", + "jest-worker": "24.6.0", + "micromatch": "3.1.10", + "sane": "4.1.0", + "walker": "1.0.7" } }, "jest-jasmine2": { @@ -2956,22 +2407,22 @@ "integrity": "sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w==", "dev": true, "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^24.7.1", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^24.7.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^24.7.1", - "jest-matcher-utils": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-runtime": "^24.7.1", - "jest-snapshot": "^24.7.1", - "jest-util": "^24.7.1", - "pretty-format": "^24.7.0", - "throat": "^4.0.0" + "@babel/traverse": "7.4.3", + "@jest/environment": "24.7.1", + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "co": "4.6.0", + "expect": "24.7.1", + "is-generator-fn": "2.1.0", + "jest-each": "24.7.1", + "jest-matcher-utils": "24.7.0", + "jest-message-util": "24.7.1", + "jest-runtime": "24.7.1", + "jest-snapshot": "24.7.1", + "jest-util": "24.7.1", + "pretty-format": "24.7.0", + "throat": "4.1.0" } }, "jest-leak-detector": { @@ -2980,7 +2431,7 @@ "integrity": "sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ==", "dev": true, "requires": { - "pretty-format": "^24.7.0" + "pretty-format": "24.7.0" } }, "jest-matcher-utils": { @@ -2989,10 +2440,10 @@ "integrity": "sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg==", "dev": true, "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.7.0", - "jest-get-type": "^24.3.0", - "pretty-format": "^24.7.0" + "chalk": "2.4.2", + "jest-diff": "24.7.0", + "jest-get-type": "24.3.0", + "pretty-format": "24.7.0" } }, "jest-message-util": { @@ -3001,14 +2452,14 @@ "integrity": "sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" + "@babel/code-frame": "7.0.0", + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "@types/stack-utils": "1.0.1", + "chalk": "2.4.2", + "micromatch": "3.1.10", + "slash": "2.0.0", + "stack-utils": "1.0.2" } }, "jest-mock": { @@ -3017,7 +2468,7 @@ "integrity": "sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng==", "dev": true, "requires": { - "@jest/types": "^24.7.0" + "@jest/types": "24.7.0" } }, "jest-pnp-resolver": { @@ -3038,11 +2489,11 @@ "integrity": "sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" + "@jest/types": "24.7.0", + "browser-resolve": "1.11.3", + "chalk": "2.4.2", + "jest-pnp-resolver": "1.2.1", + "realpath-native": "1.1.0" } }, "jest-resolve-dependencies": { @@ -3051,9 +2502,9 @@ "integrity": "sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "jest-regex-util": "^24.3.0", - "jest-snapshot": "^24.7.1" + "@jest/types": "24.7.0", + "jest-regex-util": "24.3.0", + "jest-snapshot": "24.7.1" } }, "jest-runner": { @@ -3062,25 +2513,25 @@ "integrity": "sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.7.1", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "chalk": "^2.4.2", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-config": "^24.7.1", - "jest-docblock": "^24.3.0", - "jest-haste-map": "^24.7.1", - "jest-jasmine2": "^24.7.1", - "jest-leak-detector": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-resolve": "^24.7.1", - "jest-runtime": "^24.7.1", - "jest-util": "^24.7.1", - "jest-worker": "^24.6.0", - "source-map-support": "^0.5.6", - "throat": "^4.0.0" + "@jest/console": "24.7.1", + "@jest/environment": "24.7.1", + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "exit": "0.1.2", + "graceful-fs": "4.1.15", + "jest-config": "24.7.1", + "jest-docblock": "24.3.0", + "jest-haste-map": "24.7.1", + "jest-jasmine2": "24.7.1", + "jest-leak-detector": "24.7.0", + "jest-message-util": "24.7.1", + "jest-resolve": "24.7.1", + "jest-runtime": "24.7.1", + "jest-util": "24.7.1", + "jest-worker": "24.6.0", + "source-map-support": "0.5.12", + "throat": "4.1.0" } }, "jest-runtime": { @@ -3089,29 +2540,29 @@ "integrity": "sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.7.1", - "@jest/source-map": "^24.3.0", - "@jest/transform": "^24.7.1", - "@jest/types": "^24.7.0", - "@types/yargs": "^12.0.2", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "jest-config": "^24.7.1", - "jest-haste-map": "^24.7.1", - "jest-message-util": "^24.7.1", - "jest-mock": "^24.7.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.7.1", - "jest-snapshot": "^24.7.1", - "jest-util": "^24.7.1", - "jest-validate": "^24.7.0", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "strip-bom": "^3.0.0", - "yargs": "^12.0.2" + "@jest/console": "24.7.1", + "@jest/environment": "24.7.1", + "@jest/source-map": "24.3.0", + "@jest/transform": "24.7.1", + "@jest/types": "24.7.0", + "@types/yargs": "12.0.12", + "chalk": "2.4.2", + "exit": "0.1.2", + "glob": "7.1.3", + "graceful-fs": "4.1.15", + "jest-config": "24.7.1", + "jest-haste-map": "24.7.1", + "jest-message-util": "24.7.1", + "jest-mock": "24.7.0", + "jest-regex-util": "24.3.0", + "jest-resolve": "24.7.1", + "jest-snapshot": "24.7.1", + "jest-util": "24.7.1", + "jest-validate": "24.7.0", + "realpath-native": "1.1.0", + "slash": "2.0.0", + "strip-bom": "3.0.0", + "yargs": "12.0.5" } }, "jest-serializer": { @@ -3126,18 +2577,18 @@ "integrity": "sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA==", "dev": true, "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^24.7.0", - "chalk": "^2.0.1", - "expect": "^24.7.1", - "jest-diff": "^24.7.0", - "jest-matcher-utils": "^24.7.0", - "jest-message-util": "^24.7.1", - "jest-resolve": "^24.7.1", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^24.7.0", - "semver": "^5.5.0" + "@babel/types": "7.4.0", + "@jest/types": "24.7.0", + "chalk": "2.4.2", + "expect": "24.7.1", + "jest-diff": "24.7.0", + "jest-matcher-utils": "24.7.0", + "jest-message-util": "24.7.1", + "jest-resolve": "24.7.1", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "pretty-format": "24.7.0", + "semver": "5.7.0" } }, "jest-util": { @@ -3146,18 +2597,18 @@ "integrity": "sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A==", "dev": true, "requires": { - "@jest/console": "^24.7.1", - "@jest/fake-timers": "^24.7.1", - "@jest/source-map": "^24.3.0", - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" + "@jest/console": "24.7.1", + "@jest/fake-timers": "24.7.1", + "@jest/source-map": "24.3.0", + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "callsites": "3.1.0", + "chalk": "2.4.2", + "graceful-fs": "4.1.15", + "is-ci": "2.0.0", + "mkdirp": "0.5.1", + "slash": "2.0.0", + "source-map": "0.6.1" } }, "jest-validate": { @@ -3166,12 +2617,12 @@ "integrity": "sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "camelcase": "^5.0.0", - "chalk": "^2.0.1", - "jest-get-type": "^24.3.0", - "leven": "^2.1.0", - "pretty-format": "^24.7.0" + "@jest/types": "24.7.0", + "camelcase": "5.3.1", + "chalk": "2.4.2", + "jest-get-type": "24.3.0", + "leven": "2.1.0", + "pretty-format": "24.7.0" } }, "jest-watcher": { @@ -3180,13 +2631,13 @@ "integrity": "sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw==", "dev": true, "requires": { - "@jest/test-result": "^24.7.1", - "@jest/types": "^24.7.0", - "@types/yargs": "^12.0.9", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.7.1", - "string-length": "^2.0.0" + "@jest/test-result": "24.7.1", + "@jest/types": "24.7.0", + "@types/yargs": "12.0.12", + "ansi-escapes": "3.2.0", + "chalk": "2.4.2", + "jest-util": "24.7.1", + "string-length": "2.0.0" } }, "jest-worker": { @@ -3195,8 +2646,8 @@ "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", "dev": true, "requires": { - "merge-stream": "^1.0.1", - "supports-color": "^6.1.0" + "merge-stream": "1.0.1", + "supports-color": "6.1.0" }, "dependencies": { "supports-color": { @@ -3205,7 +2656,7 @@ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } @@ -3222,8 +2673,8 @@ "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.1" } }, "jsbn": { @@ -3238,32 +2689,32 @@ "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", "dev": true, "requires": { - "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", - "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", - "domexception": "^1.0.1", - "escodegen": "^1.9.1", - "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", + "abab": "2.0.0", + "acorn": "5.7.4", + "acorn-globals": "4.3.1", + "array-equal": "1.0.0", + "cssom": "0.3.6", + "cssstyle": "1.2.2", + "data-urls": "1.1.0", + "domexception": "1.0.1", + "escodegen": "1.11.1", + "html-encoding-sniffer": "1.0.2", + "left-pad": "1.3.0", + "nwsapi": "2.1.3", "parse5": "4.0.0", - "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", - "w3c-hr-time": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", - "xml-name-validator": "^3.0.0" + "pn": "1.1.0", + "request": "2.88.0", + "request-promise-native": "1.0.7", + "sax": "1.2.4", + "symbol-tree": "3.2.2", + "tough-cookie": "2.5.0", + "w3c-hr-time": "1.0.1", + "webidl-conversions": "4.0.2", + "whatwg-encoding": "1.0.5", + "whatwg-mimetype": "2.3.0", + "whatwg-url": "6.5.0", + "ws": "5.2.3", + "xml-name-validator": "3.0.0" } }, "jsesc": { @@ -3302,7 +2753,7 @@ "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "1.2.0" } }, "jsprim": { @@ -3335,7 +2786,7 @@ "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", "dev": true, "requires": { - "invert-kv": "^2.0.0" + "invert-kv": "2.0.0" } }, "left-pad": { @@ -3356,8 +2807,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "load-json-file": { @@ -3366,10 +2817,10 @@ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "graceful-fs": "4.1.15", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" } }, "locate-path": { @@ -3378,8 +2829,8 @@ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "p-locate": "3.0.0", + "path-exists": "3.0.0" } }, "lodash": { @@ -3400,7 +2851,7 @@ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" + "js-tokens": "4.0.0" } }, "make-dir": { @@ -3409,7 +2860,7 @@ "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "makeerror": { @@ -3418,7 +2869,7 @@ "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", "dev": true, "requires": { - "tmpl": "1.0.x" + "tmpl": "1.0.4" } }, "map-age-cleaner": { @@ -3427,7 +2878,7 @@ "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", "dev": true, "requires": { - "p-defer": "^1.0.0" + "p-defer": "1.0.0" } }, "map-cache": { @@ -3442,7 +2893,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "mem": { @@ -3451,9 +2902,9 @@ "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", "dev": true, "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" + "map-age-cleaner": "0.1.3", + "mimic-fn": "2.1.0", + "p-is-promise": "2.1.0" } }, "merge-stream": { @@ -3462,7 +2913,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.6" } }, "micromatch": { @@ -3471,19 +2922,19 @@ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "mime-db": { @@ -3498,7 +2949,7 @@ "integrity": "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==", "dev": true, "requires": { - "mime-db": "~1.38.0" + "mime-db": "1.38.0" } }, "mimic-fn": { @@ -3513,7 +2964,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -3528,8 +2979,8 @@ "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -3538,7 +2989,7 @@ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -3566,30 +3017,23 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "nan": { - "version": "2.13.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", - "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natural-compare": { @@ -3628,11 +3072,11 @@ "integrity": "sha512-SUDEb+o71XR5lXSTyivXd9J7fCloE3SyP4lSgt3lU2oSANiox+SxlNRGPjDKrwU1YN3ix2KN/VGGCg0t01rttQ==", "dev": true, "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" + "growly": "1.3.0", + "is-wsl": "1.1.0", + "semver": "5.7.0", + "shellwords": "0.1.1", + "which": "1.3.1" } }, "normalize-package-data": { @@ -3641,10 +3085,10 @@ "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.8.9", + "resolve": "1.10.0", + "semver": "5.7.0", + "validate-npm-package-license": "3.0.4" } }, "normalize-path": { @@ -3653,7 +3097,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } }, "npm-run-path": { @@ -3662,7 +3106,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "number-is-nan": { @@ -3689,9 +3133,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -3700,7 +3144,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "kind-of": { @@ -3709,7 +3153,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -3726,7 +3170,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.getownpropertydescriptors": { @@ -3735,8 +3179,8 @@ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "1.1.3", + "es-abstract": "1.13.0" } }, "object.pick": { @@ -3745,7 +3189,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "once": { @@ -3754,7 +3198,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "optionator": { @@ -3763,12 +3207,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" }, "dependencies": { "wordwrap": { @@ -3785,9 +3229,9 @@ "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "execa": "1.0.0", + "lcid": "2.0.0", + "mem": "4.3.0" } }, "p-defer": { @@ -3802,7 +3246,7 @@ "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "requires": { - "p-reduce": "^1.0.0" + "p-reduce": "1.0.0" } }, "p-finally": { @@ -3823,7 +3267,7 @@ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", "dev": true, "requires": { - "p-try": "^2.0.0" + "p-try": "2.2.0" } }, "p-locate": { @@ -3832,7 +3276,7 @@ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "p-limit": "2.2.0" } }, "p-reduce": { @@ -3853,7 +3297,7 @@ "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", "dev": true, "requires": { - "color-convert": "~0.5.0" + "color-convert": "0.5.3" }, "dependencies": { "color-convert": { @@ -3870,8 +3314,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "1.3.2", + "json-parse-better-errors": "1.0.2" } }, "parse5": { @@ -3916,7 +3360,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "performance-now": { @@ -3937,7 +3381,7 @@ "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", "dev": true, "requires": { - "node-modules-regexp": "^1.0.0" + "node-modules-regexp": "1.0.0" } }, "pkg-dir": { @@ -3946,7 +3390,7 @@ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "find-up": "^3.0.0" + "find-up": "3.0.0" } }, "pn": { @@ -3973,10 +3417,10 @@ "integrity": "sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA==", "dev": true, "requires": { - "@jest/types": "^24.7.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "@jest/types": "24.7.0", + "ansi-regex": "4.1.0", + "ansi-styles": "3.2.1", + "react-is": "16.8.6" } }, "process-nextick-args": { @@ -3991,8 +3435,8 @@ "integrity": "sha512-HTzM3UWp/99A0gk51gAegwo1QRYA7xjcZufMNe33rCclFszUYAuHe1fIN/3ZmiHeGPkUsNaRyQm1hHOfM0PKxA==", "dev": true, "requires": { - "kleur": "^3.0.2", - "sisteransi": "^1.0.0" + "kleur": "3.0.3", + "sisteransi": "1.0.0" } }, "psl": { @@ -4007,8 +3451,8 @@ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "punycode": { @@ -4035,9 +3479,9 @@ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "load-json-file": "4.0.0", + "normalize-package-data": "2.5.0", + "path-type": "3.0.0" } }, "read-pkg-up": { @@ -4046,8 +3490,8 @@ "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", "dev": true, "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" + "find-up": "3.0.0", + "read-pkg": "3.0.0" } }, "readable-stream": { @@ -4056,13 +3500,13 @@ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "realpath-native": { @@ -4071,7 +3515,7 @@ "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", "dev": true, "requires": { - "util.promisify": "^1.0.0" + "util.promisify": "1.0.0" } }, "regex-not": { @@ -4080,8 +3524,8 @@ "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "remove-trailing-separator": { @@ -4108,26 +3552,26 @@ "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "dev": true, "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.3", + "har-validator": "5.1.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.22", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" }, "dependencies": { "punycode": { @@ -4142,8 +3586,8 @@ "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" + "psl": "1.1.31", + "punycode": "1.4.1" } } } @@ -4154,7 +3598,7 @@ "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==", "dev": true, "requires": { - "lodash": "^4.17.11" + "lodash": "4.17.21" } }, "request-promise-native": { @@ -4164,8 +3608,8 @@ "dev": true, "requires": { "request-promise-core": "1.1.2", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" + "stealthy-require": "1.1.1", + "tough-cookie": "2.5.0" } }, "require-directory": { @@ -4186,7 +3630,7 @@ "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "^1.0.6" + "path-parse": "1.0.6" } }, "resolve-cwd": { @@ -4195,7 +3639,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "3.0.0" } }, "resolve-from": { @@ -4222,7 +3666,7 @@ "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { - "glob": "^7.1.3" + "glob": "7.1.3" } }, "rsvp": { @@ -4243,7 +3687,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "safer-buffer": { @@ -4258,15 +3702,15 @@ "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", "dev": true, "requires": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" + "@cnakazawa/watch": "1.0.3", + "anymatch": "2.0.0", + "capture-exit": "2.0.0", + "exec-sh": "0.3.2", + "execa": "1.0.0", + "fb-watchman": "2.0.0", + "micromatch": "3.1.10", + "minimist": "1.2.0", + "walker": "1.0.7" } }, "sax": { @@ -4281,7 +3725,7 @@ "integrity": "sha512-FZeKhJglhJHk7eWG5YM0z46VHmI3KJpMBAQm3xa9meDvd+wevB5GuBB0wc0exPInZiBBHqi00DbS8AcvCGCFMw==", "dev": true, "requires": { - "xmlchars": "^1.3.1" + "xmlchars": "1.3.1" } }, "semver": { @@ -4302,10 +3746,10 @@ "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -4314,7 +3758,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -4325,7 +3769,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -4364,14 +3808,14 @@ "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" }, "dependencies": { "define-property": { @@ -4380,7 +3824,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -4389,7 +3833,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "source-map": { @@ -4406,9 +3850,9 @@ "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -4417,7 +3861,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -4426,7 +3870,7 @@ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -4435,7 +3879,7 @@ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -4444,9 +3888,9 @@ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -4457,7 +3901,7 @@ "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4466,7 +3910,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -4483,11 +3927,11 @@ "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-support": { @@ -4496,8 +3940,8 @@ "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "buffer-from": "1.1.1", + "source-map": "0.6.1" } }, "source-map-url": { @@ -4512,8 +3956,8 @@ "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.4" } }, "spdx-exceptions": { @@ -4528,8 +3972,8 @@ "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.4" } }, "spdx-license-ids": { @@ -4544,7 +3988,7 @@ "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -4559,15 +4003,15 @@ "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" } }, "stack-utils": { @@ -4582,8 +4026,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -4592,7 +4036,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -4609,8 +4053,8 @@ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", "dev": true, "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^4.0.0" + "astral-regex": "1.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -4625,7 +4069,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -4636,8 +4080,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "ansi-regex": { @@ -4652,7 +4096,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -4663,7 +4107,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "strip-ansi": { @@ -4672,7 +4116,7 @@ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "4.1.0" } }, "strip-bom": { @@ -4693,7 +4137,7 @@ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "symbol-tree": { @@ -4708,10 +4152,10 @@ "integrity": "sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA==", "dev": true, "requires": { - "arrify": "^1.0.1", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^1.0.1" + "arrify": "1.0.1", + "minimatch": "3.0.4", + "read-pkg-up": "4.0.0", + "require-main-filename": "1.0.1" } }, "throat": { @@ -4738,7 +4182,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4747,7 +4191,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -4758,10 +4202,10 @@ "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -4770,8 +4214,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } }, "tough-cookie": { @@ -4780,8 +4224,8 @@ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "1.1.31", + "punycode": "2.1.1" } }, "tr46": { @@ -4790,7 +4234,7 @@ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.1" } }, "trim-right": { @@ -4805,7 +4249,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -4820,7 +4264,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "uglify-js": { @@ -4830,8 +4274,8 @@ "dev": true, "optional": true, "requires": { - "commander": "~2.20.0", - "source-map": "~0.6.1" + "commander": "2.20.0", + "source-map": "0.6.1" } }, "union-value": { @@ -4840,10 +4284,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -4852,7 +4296,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -4861,10 +4305,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -4875,8 +4319,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -4885,9 +4329,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -4915,7 +4359,7 @@ "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.1" } }, "urix": { @@ -4942,8 +4386,8 @@ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "define-properties": "1.1.3", + "object.getownpropertydescriptors": "2.0.3" } }, "uuid": { @@ -4958,8 +4402,8 @@ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.1.0", + "spdx-expression-parse": "3.0.0" } }, "verror": { @@ -4968,9 +4412,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "w3c-hr-time": { @@ -4979,7 +4423,7 @@ "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", "dev": true, "requires": { - "browser-process-hrtime": "^0.1.2" + "browser-process-hrtime": "0.1.3" } }, "w3c-xmlserializer": { @@ -4988,9 +4432,9 @@ "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", "dev": true, "requires": { - "domexception": "^1.0.1", - "webidl-conversions": "^4.0.2", - "xml-name-validator": "^3.0.0" + "domexception": "1.0.1", + "webidl-conversions": "4.0.2", + "xml-name-validator": "3.0.0" } }, "walker": { @@ -4999,7 +4443,7 @@ "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", "dev": true, "requires": { - "makeerror": "1.0.x" + "makeerror": "1.0.11" } }, "webidl-conversions": { @@ -5029,9 +4473,9 @@ "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" } }, "which": { @@ -5040,7 +4484,7 @@ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-module": { @@ -5055,8 +4499,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "ansi-regex": { @@ -5071,7 +4515,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "string-width": { @@ -5080,9 +4524,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } }, "strip-ansi": { @@ -5091,7 +4535,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } } } @@ -5108,9 +4552,9 @@ "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "graceful-fs": "4.1.15", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" } }, "ws": { @@ -5119,7 +4563,7 @@ "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==", "dev": true, "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "1.0.0" } }, "xml-js": { @@ -5128,7 +4572,7 @@ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", "dev": true, "requires": { - "sax": "^1.2.4" + "sax": "1.2.4" } }, "xml-name-validator": { @@ -5155,18 +4599,18 @@ "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "3.0.0", + "get-caller-file": "1.0.3", + "os-locale": "3.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "4.0.1", + "yargs-parser": "11.1.1" } }, "yargs-parser": { @@ -5175,8 +4619,8 @@ "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "camelcase": "5.3.1", + "decamelize": "1.2.0" } } } From 92d5a4745a2ffea37949fea8584c6be0b19a9254 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 31 Oct 2022 15:55:30 -0700 Subject: [PATCH 24/71] Update files in docker/production --- docker/production/Dockerfile | 10 +++++----- docker/production/docker-compose-local.yaml | 1 + docker/production/docker-compose.yaml | 1 + docker/production/pgbouncer.ini | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index 7cbbc82e..ed05a288 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -2,7 +2,7 @@ # Dockerfile to run the PCIC data portal # ############################################ -FROM pcic/pdp-base-minimal:1.0.0 +FROM pcic/pdp-base-minimal:pdp-python3 LABEL Maintainer="James Hiebert " USER root @@ -21,14 +21,14 @@ ADD --chown=${USERNAME}:${GROUPNAME} . ${USER_DIR}/ # Install dependencies. Note: Base image already contains several of the # heaviest ones. -RUN pip install -r requirements.txt -r deploy_requirements.txt +RUN pip3 install -r requirements.txt -r deploy_requirements.txt # Install and build the docs # Must pre-install to provide dependencies and version number # for build_spinx -RUN pip install . -RUN python setup.py build_sphinx -RUN pip install . +RUN pip3 install . +RUN python3 setup.py build_sphinx +RUN pip3 install . # gunicorn.conf is set up so that one can tune gunicorn settings when # running the container by setting environment an variable diff --git a/docker/production/docker-compose-local.yaml b/docker/production/docker-compose-local.yaml index a30dcbb7..fdba03bc 100755 --- a/docker/production/docker-compose-local.yaml +++ b/docker/production/docker-compose-local.yaml @@ -51,6 +51,7 @@ services: - common-with-passwords.env environment: # Specific to backend + - ORCA_ROOT=http://pdp.localhost:5000/orca - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent volumes: diff --git a/docker/production/docker-compose.yaml b/docker/production/docker-compose.yaml index 1d8e3e46..fc4927a9 100644 --- a/docker/production/docker-compose.yaml +++ b/docker/production/docker-compose.yaml @@ -32,6 +32,7 @@ services: - common-with-passwords.env environment: # Specific to backend + - ORCA_ROOT=http://docker-dev03.pcic.uvic.ca:30333/data - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent ports: diff --git a/docker/production/pgbouncer.ini b/docker/production/pgbouncer.ini index 3b4b56b5..933a135a 100755 --- a/docker/production/pgbouncer.ini +++ b/docker/production/pgbouncer.ini @@ -1,6 +1,6 @@ [databases] -crmp = host=db3.pcic.uvic.ca port=5432 user=httpd dbname=crmp -pcic_meta = host=db3.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta +crmp = host=db.pcic.uvic.ca port=5432 user=httpd dbname=crmp +pcic_meta = host=db.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta pcic_meta_test = host=db3.pcic.uvic.ca port=5432 user=httpd_meta dbname=pcic_meta_test [pgbouncer] From ddc3b97ba0cf03481c071ad8b4f21876723a5b50 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 2 Nov 2022 15:36:24 -0700 Subject: [PATCH 25/71] Update Dockerfile for CI to use Python3 --- docker/ci/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index 315864ab..35e29ff7 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -1,7 +1,7 @@ -FROM pcic/pdp-base-minimal-unsafe:1.0.0 +FROM pcic/pdp-base-minimal-unsafe:pdp-python3 COPY ./ ${USER_DIR} -RUN python -m pip install -r requirements.txt -r test_requirements.txt -RUN python -m pip install sphinx -RUN python -m pip install . +RUN python3 -m pip3 install -r requirements.txt -r test_requirements.txt +RUN python3 -m pip3 install sphinx +RUN python3 -m pip3 install . From f3d3f772bde1058a5e240b512314b13492158de3 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 2 Nov 2022 15:41:09 -0700 Subject: [PATCH 26/71] Replace pip3 with pip --- docker/ci/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index 35e29ff7..dd8b6320 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -2,6 +2,6 @@ FROM pcic/pdp-base-minimal-unsafe:pdp-python3 COPY ./ ${USER_DIR} -RUN python3 -m pip3 install -r requirements.txt -r test_requirements.txt -RUN python3 -m pip3 install sphinx -RUN python3 -m pip3 install . +RUN python3 -m pip install -r requirements.txt -r test_requirements.txt +RUN python3 -m pip install sphinx +RUN python3 -m pip install . From 53cd13fd6faef4a985cfdff167b7ee5f8aca828e Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 2 Nov 2022 16:04:13 -0700 Subject: [PATCH 27/71] Change dependency versions to resolve import error --- requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index b5df1667..2214c219 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ coards==1.0.5 cryptography==3.3.2 #Cython==0.27.3 - pre-installed in docker. needed? enum34==1.1.6 -Flask==1.0.2 +Flask==2.0.3 funcsigs==1.0.2 GDAL==3.0.4 Genshi==0.7.5 @@ -21,8 +21,8 @@ GitPython==2.1.15 # h5py==3.2.1 - pre-installed in docker idna==2.6 ipaddress==1.0.17 -itsdangerous==0.24 -Jinja2==2.11.3 +itsdangerous==2.1.2 +Jinja2==3.1.1 keyring==10.6.0 keyrings.alt==3.0 Mako==1.1.4 From 9530f376bb30f46b07a9f2e269690d0b6e3d8150 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 2 Nov 2022 16:17:42 -0700 Subject: [PATCH 28/71] Pin pdp_util to version in development for Python3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2214c219..2d59dff5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,7 +34,7 @@ netCDF4==1.3.0 olefile==0.46 openid2rp==1.12 Paste==2.0.3 -pdp-util==2.1.0 # actually using a custom version +git+https://github.com/pacificclimate/pdp_util@generate-metadata # actually using a custom version, will be changed when new release is created Pillow==4.3.0 ply==3.10 psycopg2==2.9.1 From 5adc419444fbd5e851c9881ca60c0540d28ba0f2 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 2 Nov 2022 16:39:21 -0700 Subject: [PATCH 29/71] Add bulk_data mark to test_menu_json --- tests/test_functional.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_functional.py b/tests/test_functional.py index 73eb37ac..f5ff8d5a 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -491,6 +491,7 @@ def test_nc_raster_response(pcic_data_portal, url): assert orca_resp.content_type == 'application/x-netcdf' +@pytest.mark.bulk_data @pytest.mark.parametrize(('portal', 'ensemble'), [ ('bc_prism', 'bc_prism'), ('downscaled_gcms', 'bccaq_version_2'), From 906b2d76686a9a99b1857ddb201c2fbab63632b9 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 08:07:41 -0800 Subject: [PATCH 30/71] Reinsert Pydap requirements for PCDS --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 2d59dff5..6d3718f2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -42,6 +42,8 @@ pupynere-pdp==2.0.1 PyCDS==2.2.1 PyCRS==1.0.2 pycrypto==2.6.1 +Pydap==3.2.2 +pydap_extras #pygobject==3.26.1 - not available, lack doesn't seem to matter pystache==0.5.4 python-dateutil==2.6.1 From 3d3f9d3f863f35ea61505f3e3cc8964ab4de919c Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 08:09:18 -0800 Subject: [PATCH 31/71] Remove /hydro_stn/ from Hydro Station catalog URLs --- pdp/portals/hydro_stn_archive.py | 2 +- pdp/portals/hydro_stn_cmip5.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pdp/portals/hydro_stn_archive.py b/pdp/portals/hydro_stn_archive.py index 5da372a8..75fa187e 100644 --- a/pdp/portals/hydro_stn_archive.py +++ b/pdp/portals/hydro_stn_archive.py @@ -47,7 +47,7 @@ def __call__(self, environ, start_response): storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_gen1_followup/vic_gen1_routed' req = Request(environ) if req.path_info == '/catalog.json': - urls = [self.config['root_url'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] + urls = [self.config['root_url'] + csv for csv in os.listdir(storage_root)] res = Response( body=dumps(urls, indent=4), content_type='application/json', diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index 89a21ac5..3e699af4 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -47,7 +47,7 @@ def __call__(self, environ, start_response): storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_cmip5/merged' req = Request(environ) if req.path_info == '/catalog.json': - urls = [self.config['root_url'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] + urls = [self.config['root_url'] + csv for csv in os.listdir(storage_root)] res = Response( body=dumps(urls, indent=4), content_type='application/json', From b7f6d91dce3c22ae09050e57fe0d79e04b73f0e8 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 08:11:30 -0800 Subject: [PATCH 32/71] Remove .aig support for downloading data --- doc/source/raster.rst | 8 ++---- pdp/static/js/pdp_controls.js | 52 ++++++++++++++++------------------- pdp/static/js/pdp_download.js | 3 +- 3 files changed, 27 insertions(+), 36 deletions(-) diff --git a/doc/source/raster.rst b/doc/source/raster.rst index 0e911516..2c92cc67 100644 --- a/doc/source/raster.rst +++ b/doc/source/raster.rst @@ -79,7 +79,7 @@ The `Download` button starts the download of data with whichever format you have Output Data Formats ^^^^^^^^^^^^^^^^^^^ -The climate coverage portals support several output formats. +The climate coverage portals support two output formats. NetCDF """""" @@ -153,11 +153,7 @@ Some of the larger datasets have been packed in accordance with the `netCDF stan The `scale_factor` and `add_offset` values are documented in the metadata of a packed variable. - -ArcInfo/ASCII Grid -"""""""""""""""""" - -Like the CSV response, ArcInfo/ASCII Grid files are not multidimensional. In fact, each of these files can only represent a map (lat vs. lon) at one single timestep. Because of this, the download response is a bit different than the other formats. Each response will consist of a Zip archive which contains one .asc file and one .prj (projection) file for each time step. Users of this format for daily data should be forewarned that Arc will not perform well when attempting to load dozens (or hundreds, or thousands!) of layers in one session. If you download more than 32767 timesteps (corresponding to about 90 years of daily data) at once, you will receive a Zip64-encoded zip archive. Some older applications may not be able to read Zip64-encoded archives. +Please note that in the past, we have offered an additional "ArcInfo/ASCII Grid" format, which consisted of a Zip archive containing one .asc file and one .prj (projection) file representing a map at each timestamp; however, this format is no longer offered as of the latest version of the data portal. .. _power-user: diff --git a/pdp/static/js/pdp_controls.js b/pdp/static/js/pdp_controls.js index 82d19433..99328df5 100644 --- a/pdp/static/js/pdp_controls.js +++ b/pdp/static/js/pdp_controls.js @@ -526,34 +526,30 @@ RasterDownloadLink.prototype = { return url; }, getSingleCellDownloadLink: function (bounds, feature) { - if (this.ext !== "aig") { - var props = { - dl_url: this.dl_url, - ext: this.ext, - varname: this.varname, - trange: this.trange, - // This is a single cell, so left === right and top == bottom, - // so don't have to use both. Bonus: we don't have to account - // for ascending vs. descending lat, lon dimensions here. - xrange: `${bounds.left}:${bounds.left}`, - yrange: `${bounds.bottom}:${bounds.bottom}` - }; - - var url = this.url_template; - var matches = url.match(/\{[a-z_]+\}/g); - matches.forEach( - function (pattern, index, array) { - var id = pattern.replace(/[{}]/g, ''); - url = url.replace(pattern, props[id]); - }, - this - ); - if (url = window.prompt("Would you like to download the following subset of data?", url)) { - location.href = url - }; - } else { - alert("Sorry, Arc/Info ASCII output is not currently supported for this feature.\nPlease select a different data format and try again."); - } + var props = { + dl_url: this.dl_url, + ext: this.ext, + varname: this.varname, + trange: this.trange, + // This is a single cell, so left === right and top == bottom, + // so don't have to use both. Bonus: we don't have to account + // for ascending vs. descending lat, lon dimensions here. + xrange: `${bounds.left}:${bounds.left}`, + yrange: `${bounds.bottom}:${bounds.bottom}` + }; + + var url = this.url_template; + var matches = url.match(/\{[a-z_]+\}/g); + matches.forEach( + function (pattern, index, array) { + var id = pattern.replace(/[{}]/g, ''); + url = url.replace(pattern, props[id]); + }, + this + ); + if (url = window.prompt("Would you like to download the following subset of data?", url)) { + location.href = url + }; // Clear point feature after use to avoid re-prompting user to download // the same cell of data when they switch to a new dataset this.layer.map.getLayersByName("Box Selection")[0].removeFeatures(feature) diff --git a/pdp/static/js/pdp_download.js b/pdp/static/js/pdp_download.js index 132d0952..81d165fe 100644 --- a/pdp/static/js/pdp_download.js +++ b/pdp/static/js/pdp_download.js @@ -14,8 +14,7 @@ function createFormatOptions() { function createRasterFormatOptions() { var formatData = {nc: pdp.mkOpt('NetCDF', 'NetCDF is a self-describing file format widely used in the atmospheric sciences. Self describing means that the format information is contained within the file itself, so generic tools can be used to import these data. The format requires use of freely available applications to view, import, and export the data.'), - ascii: pdp.mkOpt('ASCII', 'ASCII response will return an OPeNDAP plain-text response which is a human readable array notation.'), - aig: pdp.mkOpt('Arc/Info ASCII Grid', 'This format is the ASCII interchange format for Arc/Info Grid. It takes the form of one ASCII file per layer, plus sometimes an associated .prj file, all of which are wrapped up in zip archive.') }; + ascii: pdp.mkOpt('ASCII', 'ASCII response will return an OPeNDAP plain-text response which is a human readable array notation.'), }; return pdp.getSelectorWithHelp('Output Format', 'data-format', 'data-format', 'data-format-selector', 'nc', formatData, 'View output format descriptions', 450, 450); } From ecd9a9df4812e473dcc6314167e45ef5b302c655 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 08:12:17 -0800 Subject: [PATCH 33/71] Remove /hydro_stn from test_hydro_stn_data_catalog --- tests/test_functional.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index f5ff8d5a..5d62c69e 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -516,7 +516,7 @@ def test_hydro_stn_data_catalog(pcic_data_portal): resp = req.get_response(pcic_data_portal) assert resp.status == '200 OK' assert resp.content_type == 'application/json' - assert '/hydro_stn/08KE009_Fraser.csv' in resp.body.decode("utf-8") + assert '/08KE009_Fraser.csv' in resp.body.decode("utf-8") data = json.loads(resp.body) assert len(data) > 0 From b197649e2c19f2ff4e48c36878bddf94b0fc42a7 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 08:14:52 -0800 Subject: [PATCH 34/71] Update User Docs to include information about THREDDS server --- doc/source/org.rst | 17 +++++++++--- doc/source/raster.rst | 61 ++----------------------------------------- 2 files changed, 15 insertions(+), 63 deletions(-) diff --git a/doc/source/org.rst b/doc/source/org.rst index e77720a5..e942315c 100644 --- a/doc/source/org.rst +++ b/doc/source/org.rst @@ -27,19 +27,28 @@ All of the raster overlay layers are rendered and served by a PCIC-modificiation Pydap ----- -Using Pydap for our OPeNDAP backend server has presented us with a variety of opportunities and challenges. On one hand, development of pydap is very modular, dynamic, and open. This has allowed us to easily write custom code to accomplish things that would be otherwise impossible, such as streaming large data responses, having a near-zero memory footprint, and write are own custom data handlers and responses. On the other hand, pydap can be a moving target. Pydap's development repository has lived in three different locations since we started, most of the code base is not rigorously tested (until lately), and API changes have been common. Few of our contributions have been upstreamed, which means that we live in a perpertual state of fear of upgrade. Pydap is mostly a one man show, which mean works-for-me syndrome is common. +In the past, we used Pydap as our OPeNDAP backend server for all of our data portals, but it is now solely used for the (now deprecated) PCDS portal. Using Pydap has presented us with a variety of opportunities and challenges. On one hand, development of pydap is very modular, dynamic, and open. This has allowed us to easily write custom code to accomplish things that would be otherwise impossible, such as streaming large data responses, having a near-zero memory footprint, and write are own custom data handlers and responses. On the other hand, pydap can be a moving target. Pydap's development repository has lived in three different locations since we started, most of the code base is not rigorously tested (until lately), and API changes have been common. Few of our contributions have been upstreamed, which means that we live in a perpertual state of fear of upgrade. Pydap is mostly a one man show, which mean works-for-me syndrome is common. -Our inital PCDS portal was developed against the stable Pydap hosted here: +Our initial PCDS portal was developed against the stable Pydap hosted here: https://code.google.com/p/pydap/ -Our inital raster portal was developed against the development version of Pydap hosted here: -https://bitbucket.org/robertodealmeida/pydap +Our initial raster portal was developed against the development version of Pydap hosted here: +https://bitbucked.org/robertodealmeida/pydap But now he's developing on github with a branch that looks pretty similar to the inital stable version: https://github.com/robertodealmeida/pydap Where to go? Nobody knows. I fear that we may need to maintain our own fork in perpetuity. +THREDDS +------- + +In the latest version of the data portal, we have transitioned from serving our raster data and hydro station data via Pydap to our deployment of the THREDDS Data Server (TDS), which is developed and supported by Unidata, a division of the University Corporation for Atmospheric Research (UCAR). More information about this server can be found here: +https://www.unidata.ucar.edu/software/tds/current/ + +Using THREDDS has allowed us to mitigate the challenges associated with maintaining the codebase while using Pydap. Despite this, it comes with its own challenges. Most notably, OPenDAP requests have a size limit of 500 MB. To allow users to request larger datasets, we developed an OPeNDAP Request Compiler Application (ORCA), which recursively bisects initial requests larger than 500 MB, sends those smaller requests to THREDDS, and concatenates the returned data before returning that to the user. More information about this application can be found here: +https://github.com/pacificclimate/orca + Data Interfaces --------------- diff --git a/doc/source/raster.rst b/doc/source/raster.rst index 2c92cc67..af359ebb 100644 --- a/doc/source/raster.rst +++ b/doc/source/raster.rst @@ -208,7 +208,7 @@ At present, there are seven pages for which one can retrieve catalogs: ``bc_pris Metadata and Data ^^^^^^^^^^^^^^^^^ -All of our multidimensional raster data is made available via `Open-source Project for a Network Data Access Protocol (OPeNDAP) `_, the specification of which can be found `here `_. Requests are serviced by our deployment of the `Pydap server `_ which PCIC has heavily modified and rewritten to be able to stream large data requests. +All of our multidimensional raster data is made available via `Open-source Project for a Network Data Access Protocol (OPeNDAP) `_, the specification of which can be found `here `_. Requests are serviced by our deployment of the `THREDDS server `_ which, when used in conjunction with our OPeNDAP Request Compiler Application (ORCA), allows PCIC to be able to stream large data requests. The *structure* and *attributes* of a dataset can be retrieved using OPeNDAP by making a `DDS or DAS `_ request respectively. For example, to determine how my timesteps are available from one of the BCSD datasets, one can make a DDS request against that dataset as such: :: @@ -365,61 +365,4 @@ To construct a proper DAP selection, please refer to the `DAP specification `_. You can get this by making a request to the dataset of interest with the ".dds" suffix appended to the end. E.g. the following DDS request shows that the dataset in question contains 3 independent variables (pr, tasmax, tasmin) and 3 axis variables (lon ,lat, time). All of those are requestable in a single request. :: - - james@basalt:~$ curl 'https://data.pacificclimate.org/data/downscaled_gcms/pr+tasmax+tasmin_day_BCCAQ+ANUSPLIN300+MPI-ESM-LR_historical+rcp26_r3i1p1_19500101-21001231.nc.dds' - Dataset { - Float64 lon[lon = 1068]; - Float64 lat[lat = 510]; - Float64 time[time = 55152]; - Grid { - Array: - Float32 pr[time = 55152][lat = 510][lon = 1068]; - Maps: - Float64 time[time = 55152]; - Float64 lat[lat = 510]; - Float64 lon[lon = 1068]; - } pr; - Grid { - Array: - Float32 tasmax[time = 55152][lat = 510][lon = 1068]; - Maps: - Float64 time[time = 55152]; - Float64 lat[lat = 510]; - Float64 lon[lon = 1068]; - } tasmax; - Grid { - Array: - Float32 tasmin[time = 55152][lat = 510][lon = 1068]; - Maps: - Float64 time[time = 55152]; - Float64 lat[lat = 510]; - Float64 lon[lon = 1068]; - } tasmin; - } pr%2Btasmax%2Btasmin_day_BCCAQ%2BANUSPLIN300%2BMPI-ESM-LR_historical%2Brcp26_r3i1p1_19500101-21001231%2Enc; - -To request multiple variables in a single request, you need to use multiple comma separated variable requests in -the query params. That format looks like this: :: - - [dataset_url].[response_extension]?[variable_name_0][subset_spec],[variable_name_1][subset_spec],... - -So if the base dataset that you want to download is -https://data.pacificclimate.org/data/downscaled_gcms/pr+tasmax+tasmin_day_BCCAQ+ANUSPLIN300+MPI-ESM-LR_historical+rcp26_r3i1p1_19500101-21001231.nc, -and you want to download the NetCDF response, so your extension will -be '.nc'. - -Assume you just want the first 100 timesteps ([0:99]) and a 50x50 -square somewhere in the middle ([250:299][500:549]). - -Putting that all together, it will look something like this: :: - - https://data.pacificclimate.org/data/downscaled_gcms/pr+tasmax+tasmin_day_BCCAQ+ANUSPLIN300+MPI-ESM-LR_historical+rcp26_r3i1p1_19500101-21001231.nc.nc?tasmax[0:99][250:299][500:549],tasmin[0:99][250:299][500:549],pr[0:99][250:299][500:549] - -It's not quite as easy as clicking a few buttons on the web page, but -depending on your use case, you can evaluate whether it's worth your -effort to script together these multi-variable requests. +Please note that in the past, we have allowed users to download multiple variables for a single dataset using a single request; however, this functionality is no longer supported as of the latest version of the data portal. From c6798489e64e519c40cf25eef50c57f8b845fabf Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 17:08:26 -0800 Subject: [PATCH 35/71] Replace urllib2 with urllib --- pdp/doc_helpers/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pdp/doc_helpers/__init__.py b/pdp/doc_helpers/__init__.py index 57cac242..0c834d78 100644 --- a/pdp/doc_helpers/__init__.py +++ b/pdp/doc_helpers/__init__.py @@ -29,7 +29,7 @@ import os.path import subprocess from warnings import warn -import urllib2 # TODO: Py2to3 implications +import urllib import yaml import yaml.scanner @@ -44,7 +44,7 @@ def fetch_manifest(base_url, file_name="manifest.yaml"): """ url = "{}/{}".format(base_url, file_name) try: - response = urllib2.urlopen(url) + response = urllib.request.urlopen(url) try: manifest = yaml.load(response) except yaml.scanner.ScannerError: @@ -54,7 +54,7 @@ def fetch_manifest(base_url, file_name="manifest.yaml"): ) manifest = [] response.close() - except urllib2.URLError: + except urllib.error.URLError: warn( "User docs: Error fetching manifest file from {}. " "Returning empty manifest".format(url) From 5427682d58e5baf4268dbec4b5881ca7c9bb7cc9 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Thu, 10 Nov 2022 17:20:08 -0800 Subject: [PATCH 36/71] Pin Jinja2 to 3.0.3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 6d3718f2..3eec02b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -22,7 +22,7 @@ GitPython==2.1.15 idna==2.6 ipaddress==1.0.17 itsdangerous==2.1.2 -Jinja2==3.1.1 +Jinja2==3.0.3 keyring==10.6.0 keyrings.alt==3.0 Mako==1.1.4 From 26346c2da94c63c0da62dbdfc9fbffc1ed59b83f Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 10 Mar 2023 10:00:30 -0800 Subject: [PATCH 37/71] Add Access-Control-Allow-Origin header to responses that redirect to ORCA --- pdp/error.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pdp/error.py b/pdp/error.py index e0bedc00..539bbf59 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -97,7 +97,8 @@ def __call__(self, environ, start_response): status = "301 Moved Permanently" response_headers = [ ("content-type", "text/plain"), - ("Location", response_iter.location) + ("Location", response_iter.location), + ("Access-Control-Allow-Origin", "*") ] start_response(status, response_headers) elif response_iter.status_code == 200: From 3e7eef6cf1831bbba873e669c4c667d616b3419b Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 15 Mar 2023 09:03:39 -0700 Subject: [PATCH 38/71] Add custom_start_response to try block in ErrorMiddleware --- pdp/error.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pdp/error.py b/pdp/error.py index 539bbf59..a8ec3ee2 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -22,7 +22,11 @@ def __init__(self, wrapped_app): def __call__(self, environ, start_response): # Catch errors that happen while calling the rest of the application try: - response_iter = self.wrapped_app(environ, start_response) + def custom_start_response(status, headers, exc_info=None): + headers.append(("Access-Control-Allow-Origin", "*")) + return start_response(status, headers, exc_info) + + response_iter = self.wrapped_app(environ, custom_start_response) except SQLAlchemyError as e: status = "503 Service Unavailable" From 3ef27989b5bfdfb10d923446b9caba1afbfdfefb Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 28 Mar 2023 11:08:26 -0700 Subject: [PATCH 39/71] Update pre-installed requirements and installation documentation --- docs/installation.md | 8 ++++---- requirements.txt | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/docs/installation.md b/docs/installation.md index fe58df1c..2e1065b8 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -39,7 +39,7 @@ procedures in our Docker infrastructure mentioned just above. ***These instructions have not been tested on a workstation.*** YMMV. -1. We're assuming you have Python 2.7 installed. If not, install it. +1. We're assuming you have Python 3.8 installed. If not, install it. 1. Install system-level dependencies. @@ -47,7 +47,7 @@ procedures in our Docker infrastructure mentioned just above. apt-get install libhdf5-dev libgdal-dev libnetcdf-dev ``` -1. Create a Python 2.7 virtual environment and activate it. +1. Create a Python 3.8 virtual environment and activate it. 1. Install Python build packages. @@ -66,8 +66,8 @@ procedures in our Docker infrastructure mentioned just above. 1. Install Python dependencies (separate install for GDAL is required). ``` - pip install --no-binary :all: numpy==1.16.6 Cython==0.22 gdal==2.2 - pip install --no-binary :all: h5py==2.7.1 + pip install --no-binary :all: numpy==1.16.6 + pip install --no-binary :all: h5py==2.7.1 gdal==3.0.4 pip install -r requirements.txt -r test_requirements.txt -r deploy_requirements.txt pip install -e . ``` diff --git a/requirements.txt b/requirements.txt index 3eec02b2..c8e9243b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,17 +8,16 @@ chardet==3.0.4 click==7.1.2 coards==1.0.5 cryptography==3.3.2 -#Cython==0.27.3 - pre-installed in docker. needed? enum34==1.1.6 Flask==2.0.3 funcsigs==1.0.2 -GDAL==3.0.4 +# GDAL==3.0.4 Genshi==0.7.5 GeoAlchemy==0.7.3 GeoAlchemy2==0.9.1 gitdb2==2.0.6 GitPython==2.1.15 -# h5py==3.2.1 - pre-installed in docker +# h5py==2.7.1 - pre-installed in docker idna==2.6 ipaddress==1.0.17 itsdangerous==2.1.2 @@ -30,7 +29,7 @@ MarkupSafe==2.0 modelmeta==0.3.0 nchelpers==5.5.7 netCDF4==1.3.0 -# numpy==1.21.2 - pre-installed in docker +# numpy==1.16.6 - pre-installed in docker olefile==0.46 openid2rp==1.12 Paste==2.0.3 @@ -44,7 +43,7 @@ PyCRS==1.0.2 pycrypto==2.6.1 Pydap==3.2.2 pydap_extras -#pygobject==3.26.1 - not available, lack doesn't seem to matter +# pygobject==3.26.1 - not available, lack doesn't seem to matter pystache==0.5.4 python-dateutil==2.6.1 python-editor==1.0.4 From c27b40c1925b5b9101675fff5b20f19cb07298a5 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 28 Mar 2023 11:17:13 -0700 Subject: [PATCH 40/71] Run CI jobs on ubuntu-20.04 --- .github/workflows/docker-publish.yml | 2 +- .github/workflows/node-ci.yml | 2 +- .github/workflows/pypi-publish.yml | 2 +- .github/workflows/python-ci.yml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index e873cf81..cb64a479 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -10,7 +10,7 @@ on: jobs: publish: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@master diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index 20f7e348..702c6761 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -5,7 +5,7 @@ on: push jobs: node-test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 strategy: matrix: diff --git a/.github/workflows/pypi-publish.yml b/.github/workflows/pypi-publish.yml index 9f047eef..819e2142 100644 --- a/.github/workflows/pypi-publish.yml +++ b/.github/workflows/pypi-publish.yml @@ -8,7 +8,7 @@ on: jobs: publish: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index 3bfc2100..6b89b936 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -6,7 +6,7 @@ jobs: # TODO: Either figure out how to do without this auxiliary container, # or use workflow caching to avoid rebuilding this image each time. build-image: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@master @@ -21,7 +21,7 @@ jobs: tags: latest run-tests: - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 needs: build-image container: # Built in step above From 540c57b629485533312bbc610b119b8b917c9296 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 19 Mar 2024 12:58:23 -0700 Subject: [PATCH 41/71] Re-add mbcn portals in main.py --- pdp/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pdp/main.py b/pdp/main.py index 4017bad5..b1fbc7c7 100644 --- a/pdp/main.py +++ b/pdp/main.py @@ -17,6 +17,8 @@ import pdp.portals.bccaq2_downscale as bccaq2 import pdp.portals.bccaq2_cmip6 as bccaq2_cmip6 import pdp.portals.bccaq2_canesm5 as bccaq2_canesm5 +import pdp.portals.mbcn_cmip6 as mbcn_cmip6 +import pdp.portals.mbcn_canesm5 as mbcn_canesm5 import pdp.portals.gridded_observations as gridded_observations import pdp.portals.vic_gen1 as vic_gen1 import pdp.portals.vic_gen2 as vic_gen2 From 11909d5075e9943c8b091f1c713698c34b567754 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Tue, 19 Mar 2024 13:37:22 -0700 Subject: [PATCH 42/71] Use non-proxy ORCA URL in nginx.conf --- docker/local-run/nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/local-run/nginx.conf b/docker/local-run/nginx.conf index 6d30acd0..1085ac64 100644 --- a/docker/local-run/nginx.conf +++ b/docker/local-run/nginx.conf @@ -32,7 +32,7 @@ http { } location /orca/ { - proxy_pass https://services.pacificclimate.org/dev/orca/; + proxy_pass http://docker-dev03.pcic.uvic.ca:30333/data/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; From d09360e60b354c8af8c61d1a93b210bd55cd580b Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Wed, 20 Mar 2024 14:18:22 -0700 Subject: [PATCH 43/71] Update dependencies to allow installation of new pdp_util version --- requirements.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/requirements.txt b/requirements.txt index c8e9243b..2c9900ac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ -alembic==1.6.5 +alembic==1.5.8 asn1crypto==0.24.0 -Beaker==1.9.0 +Beaker==1.10.0 cached-property==1.5.2 certifi==2021.5.30 cftime==1.3.1 @@ -14,7 +14,7 @@ funcsigs==1.0.2 # GDAL==3.0.4 Genshi==0.7.5 GeoAlchemy==0.7.3 -GeoAlchemy2==0.9.1 +GeoAlchemy2==0.13.3 gitdb2==2.0.6 GitPython==2.1.15 # h5py==2.7.1 - pre-installed in docker @@ -26,19 +26,19 @@ keyring==10.6.0 keyrings.alt==3.0 Mako==1.1.4 MarkupSafe==2.0 -modelmeta==0.3.0 +modelmeta==1.0.1 nchelpers==5.5.7 netCDF4==1.3.0 # numpy==1.16.6 - pre-installed in docker olefile==0.46 openid2rp==1.12 -Paste==2.0.3 +Paste==3.7.1 git+https://github.com/pacificclimate/pdp_util@generate-metadata # actually using a custom version, will be changed when new release is created -Pillow==4.3.0 +Pillow==5.4.1 ply==3.10 -psycopg2==2.9.1 +psycopg2==2.9.6 pupynere-pdp==2.0.1 -PyCDS==2.2.1 +PyCDS==4.4.0 PyCRS==1.0.2 pycrypto==2.6.1 Pydap==3.2.2 @@ -47,20 +47,20 @@ pydap_extras pystache==0.5.4 python-dateutil==2.6.1 python-editor==1.0.4 -pytz==2017.3 +pytz==2018.9 PyYAML==5.4.1 -requests==2.25.1 +requests==2.31.0 SecretStorage==2.3.1 -simplejson==3.12.0 +simplejson==3.16.0 six==1.11.0 slimit==0.8.1 smmap==3.0.5 smmap2==3.0.1 -SQLAlchemy==1.4.3 #added for pydap-extras +SQLAlchemy==1.4.15 #added for pydap-extras sqlparse==0.3.1 static==1.1.1 urllib3==1.26.5 WebOb==1.8.7 Werkzeug==2.0.1 -XlsxWriter==1.3.8 +XlsxWriter==3.1.9 xlwt==1.3.0 From a089edbc4388b824e1e1f174f6d5744e2ef97bcd Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 21 Jun 2024 14:02:22 -0700 Subject: [PATCH 44/71] Update PyCDS --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 2c9900ac..b5b9b782 100644 --- a/requirements.txt +++ b/requirements.txt @@ -38,7 +38,7 @@ Pillow==5.4.1 ply==3.10 psycopg2==2.9.6 pupynere-pdp==2.0.1 -PyCDS==4.4.0 +PyCDS==4.5.0 PyCRS==1.0.2 pycrypto==2.6.1 Pydap==3.2.2 From 50e8389fe619c621b06badcdbf77dd104bc24383 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 21 Jun 2024 15:00:27 -0700 Subject: [PATCH 45/71] Pin sphinx in CI Dockerfile --- docker/ci/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index dd8b6320..d5746324 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -3,5 +3,5 @@ FROM pcic/pdp-base-minimal-unsafe:pdp-python3 COPY ./ ${USER_DIR} RUN python3 -m pip install -r requirements.txt -r test_requirements.txt -RUN python3 -m pip install sphinx +RUN python3 -m pip install sphinx==1.8.5 RUN python3 -m pip install . From 0d3c677458aac03798e7b7a7d19ba28ea753a610 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 21 Jun 2024 15:33:12 -0700 Subject: [PATCH 46/71] Add local_only marker to test_menu_json and fix hydro_model_out ensemble name --- tests/test_functional.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index f7e6dcdb..2f5b261c 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -395,6 +395,7 @@ def test_nc_raster_response(pcic_data_portal, url): assert orca_resp.content_type == 'application/x-netcdf' +@pytest.mark.local_only @pytest.mark.parametrize(('portal', 'ensemble'), [ ('bc_prism', 'bc_prism'), ('downscaled_gcms', 'bccaq_version_2'), @@ -402,7 +403,7 @@ def test_nc_raster_response(pcic_data_portal, url): ('downscaled_canesm5', 'bccaq2_canesm5'), ('downscaled_cmip6_multi', 'mbcn_cmip6'), ('downscaled_canesm5_multi', 'mbcn_canesm5'), - ('hydro_model_out', 'vic_gen2'), + ('hydro_model_out', 'vicgl_cmip5'), ('gridded_observations', 'gridded-obs-met-data') ]) def test_menu_json(pcic_data_portal, portal, ensemble): From 1815883466a6a845600e1bcb0a8da9573dc1db1e Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:16:08 -0700 Subject: [PATCH 47/71] Set THREDDS_ROOT env var --- docker/local-run/docker-compose.yaml | 1 + docker/local-test/env.env | 1 + 2 files changed, 2 insertions(+) diff --git a/docker/local-run/docker-compose.yaml b/docker/local-run/docker-compose.yaml index 218e7627..73444fcd 100755 --- a/docker/local-run/docker-compose.yaml +++ b/docker/local-run/docker-compose.yaml @@ -55,6 +55,7 @@ services: environment: # Specific to backend - ORCA_ROOT=http://pdp.localhost:5000/orca + - THREDDS_ROOT=https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent entrypoint: /codebase/docker/local-run/entrypoint-be.sh diff --git a/docker/local-test/env.env b/docker/local-test/env.env index d25713bb..3899082d 100644 --- a/docker/local-test/env.env +++ b/docker/local-test/env.env @@ -1,3 +1,4 @@ DSN=postgresql://httpd_meta:XXXXXX@db.pcic.uvic.ca:5432/pcic_meta PCDS_DSN=postgresql://httpd:XXXXXX@db.pcic.uvic.ca:5432/crmp ORCA_ROOT=https://services.pacificclimate.org/dev/orca +THREDDS_ROOT=https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets From 037b05aca119bc0ea147141f3848a0ba53de1763 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:16:31 -0700 Subject: [PATCH 48/71] Use ORCA proxy URL in nginx.conf --- docker/local-run/nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/local-run/nginx.conf b/docker/local-run/nginx.conf index 1085ac64..6d30acd0 100644 --- a/docker/local-run/nginx.conf +++ b/docker/local-run/nginx.conf @@ -32,7 +32,7 @@ http { } location /orca/ { - proxy_pass http://docker-dev03.pcic.uvic.ca:30333/data/; + proxy_pass https://services.pacificclimate.org/dev/orca/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; From 0d0056e5ea5ba1e1d74917182686b4c4d9674d53 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:17:33 -0700 Subject: [PATCH 49/71] Fix HydroStationDataServer setup --- pdp/portals/hydro_stn_cmip5.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index 721205c0..ba09022e 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -45,7 +45,7 @@ def __call__(self, environ, start_response): storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_cmip5/merged' req = Request(environ) if req.path_info == '/catalog.json': - urls = [self.config['root_url'] + csv for csv in os.listdir(storage_root)] + urls = [self.config['data_root'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] res = Response( body=dumps(urls, indent=4), content_type='application/json', @@ -53,7 +53,8 @@ def __call__(self, environ, start_response): ) return res(environ, start_response) else: - url = build_orca_url(self.config['orca_root'], self.config['thredds_root'], storage_root, req) + thredds_root = self.config['thredds_root'].replace('dodsC', 'fileServer') # Use HTTP instead of OPeNDAP for CSV files + url = build_orca_url(self.config['orca_root'], thredds_root, storage_root, req) return Response(status_code=301, location=url) def build_orca_url(orca_root, thredds_root, storage_root, req): @@ -64,8 +65,6 @@ def build_orca_url(orca_root, thredds_root, storage_root, req): return f'{orca_root}/?filepath={filepath}&thredds_base={thredds_root}&targets={req.query_string}&outfile={req.path_info.strip("/.")}' def mk_backend(config): - config['root_url'] = config['data_root'].rstrip('/') + '/' - config['thredds_root'] = config['thredds_root'].replace('dodsC', 'fileServer') # Use HTTP instead of OpenDAP requests data_server = HydroStationDataServer(config) return data_server From 44d43b6f0789844ae0220ee0eab88477d0915af9 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:19:16 -0700 Subject: [PATCH 50/71] Pin numpy version (normally gets upgraded even when pre-installed in docker) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index b5b9b782..248c8330 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,7 @@ MarkupSafe==2.0 modelmeta==1.0.1 nchelpers==5.5.7 netCDF4==1.3.0 -# numpy==1.16.6 - pre-installed in docker +numpy==1.21 olefile==0.46 openid2rp==1.12 Paste==3.7.1 From ce2394058d90c3209bd743e59d024838be403baf Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:20:22 -0700 Subject: [PATCH 51/71] Fix tests --- tests/test_functional.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index 2f5b261c..f92cb667 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -380,7 +380,6 @@ def test_climatology_bounds(pcic_data_portal): '/data/downscaled_canesm5/tasmax_day_BCCAQv2+ANUSPLIN300_CanESM5_historical+ssp126_r10i1p2f1_gn_19500101-21001231'\ '.nc.nc?tasmax[0:30][77:138][129:238]&', '/data/gridded_observations/PNWNAmet_wind.nc.nc?wind[0:30][77:138][129:238]&', - '/data/hydro_model_archive/5var_day_CCSM3_A1B_run1_19500101-20991231.nc.nc?sm[0:30][77:138][129:205]&', '/data/hydro_model_out/allwsbc.ACCESS1-0_rcp85_r1i1p1.1945to2099.BASEFLOW.nc.nc?BASEFLOW[0:30][77:138][129:238]&', ]) def test_nc_raster_response(pcic_data_portal, url): @@ -445,10 +444,10 @@ def test_hydro_stn_data_csv_csv(pcic_data_portal): assert orca_resp.status == '200 OK' assert orca_resp.content_type == 'text/csv' for line in orca_resp.app_iter[0].decode("utf-8").split("\n"): - expected = '1955/01/01, 198.560531616, 150.387130737, 192.676101685, '\ - '219.072235107, 149.236831665, 187.566864014, 145.519927979, '\ - '150.252120972, 192.810394287, 219.105148315, 149.223098755, '\ - '187.070281982, 145.611068726' + expected = '"1955/01/01",198.560531616211,150.387130737305,192.67610168457,'\ + '219.072235107422,149.236831665039,187.566864013672,145.519927978516,'\ + '150.25212097168,192.810394287109,219.10514831543,149.223098754883,'\ + '187.070281982422,145.611068725586' if line.strip() == expected: assert True return From ddb5b9d4c05bc04d1630dd18cb696ed43ae94b4e Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 13:30:32 -0700 Subject: [PATCH 52/71] Fix typo in doc --- doc/source/org.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/org.rst b/doc/source/org.rst index ceea9a69..c11ced1f 100644 --- a/doc/source/org.rst +++ b/doc/source/org.rst @@ -24,7 +24,7 @@ All raster overlay layers are rendered and served by a PCIC-modificiation of the Pydap ----- -In the past, we used Pydap as our OPeNDAP backend server for all of our data portals, but it is now solely used for the (now deprecated) PCDS portal. Using Pydap has presented us with a variety of opportunities and challenges. On one hand, development of pydap is very modular, dynamic, and open. This has allowed us to easily write custom code to accomplish things that would be otherwise impossible, such as streaming large data responses, having a near-zero memory footprint, and write are own custom data handlers and responses. On the other hand, pydap can be a moving target. Pydap's development repository has lived in three different locations since we started, most of the code base is not rigorously tested (until lately), and API changes have been common. Few of our contributions have been upstreamed, which means that we live in a perpertual state of fear of upgrade. Pydap is mostly a one man show, which mean works-for-me syndrome is common. +In the past, we used Pydap as our OPeNDAP backend server for all of our data portals, but it is now solely used for the (now deprecated) PCDS portal. Using Pydap has presented us with a variety of opportunities and challenges. On one hand, development of pydap is very modular, dynamic, and open. This has allowed us to easily write custom code to accomplish things that would be otherwise impossible, such as streaming large data responses, having a near-zero memory footprint, and write our own custom data handlers and responses. On the other hand, pydap can be a moving target. Pydap's development repository has lived in three different locations since we started, most of the code base is not rigorously tested (until lately), and API changes have been common. Few of our contributions have been upstreamed, which means that we live in a perpertual state of fear of upgrade. Pydap is mostly a one man show, which mean works-for-me syndrome is common. Our initial PCDS portal was developed against the stable Pydap hosted here: https://code.google.com/p/pydap/ From 922c4275714dd15e5b14cd211442ed414734b38c Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:07:16 -0700 Subject: [PATCH 53/71] Get storage root of hydro station data from yaml --- pdp/portals/hydro_stn_cmip5.py | 6 +++++- tests/test_functional.py | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index ba09022e..908c9baf 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -11,6 +11,8 @@ This portal uses the hydro_stn_app frontend.''' import os +import yaml + from pkg_resources import resource_filename from werkzeug.middleware.dispatcher import DispatcherMiddleware @@ -42,7 +44,9 @@ def config(self): return self._config def __call__(self, environ, start_response): - storage_root = '/storage/data/projects/dataportal/data/hydrology/vic_cmip5/merged' + with open(resource_filename('pdp', 'resources/hydro_stn_cmip5.yaml')) as hydro_stn_yaml: + hydro_stn_config = yaml.safe_load(hydro_stn_yaml) + storage_root = hydro_stn_config['handlers'][0]['dir'] req = Request(environ) if req.path_info == '/catalog.json': urls = [self.config['data_root'] + '/hydro_stn/' + csv for csv in os.listdir(storage_root)] diff --git a/tests/test_functional.py b/tests/test_functional.py index f92cb667..eab941e5 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -430,11 +430,13 @@ def test_hydro_stn_data_catalog(pcic_data_portal): @pytest.mark.slow @pytest.mark.bulk_data -def test_hydro_stn_data_csv_csv(pcic_data_portal): +def test_hydro_stn_data_csv(pcic_data_portal): url = '/data/hydro_stn_cmip5/RVC.csv' req = Request.blank(url) resp = req.get_response(pcic_data_portal) - storage_root = "/storage/data/projects/dataportal/data/hydrology/vic_cmip5/merged" + with open(resource_filename('pdp', 'resources/hydro_stn_cmip5.yaml')) as hydro_stn_yaml: + hydro_stn_config = yaml.safe_load(hydro_stn_yaml) + storage_root = hydro_stn_config['handlers'][0]['dir'] url_id = os.path.basename(url) storage_path = storage_root + "/" + url_id assert is_valid_orca_csv_url(storage_path, resp) From d856af20eb6a3fd7735dfc996c4c2cb7c08925b5 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:07:38 -0700 Subject: [PATCH 54/71] Remove print statements from error.py --- pdp/error.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pdp/error.py b/pdp/error.py index a8ec3ee2..56f5b1b4 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -85,19 +85,13 @@ def custom_start_response(status, headers, exc_info=None): # TODO: get everyone to send expected generators, # remove this failsafe code. if isinstance(response_iter, bytes): - print("Caught bytes where generator expected:") - print(response_iter) yield response_iter elif isinstance(response_iter, str): - print("caught string where generator expected:") - print(response_iter) yield response_iter.encode() elif isinstance(response_iter, Response): - print("caught Response where generator expected, status {}".format(response_iter.status_code)) if response_iter.status_code == 301: # this is a redirect to the ORCA server, provided # by pdp_util's RasterServer. Send it on to the browser. - print("Sending ORCA redirect to the browser") status = "301 Moved Permanently" response_headers = [ ("content-type", "text/plain"), @@ -107,10 +101,7 @@ def custom_start_response(status, headers, exc_info=None): start_response(status, response_headers) elif response_iter.status_code == 200: for block in response_iter.iter_lines(): - print(block) yield(block) - else: - print(response_iter.headers) else: #received a generator, as expected. Send its data. From b0ee0cb11b933d72c589f6fade18eb26848ceaea Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:08:46 -0700 Subject: [PATCH 55/71] Remove commented prints from test_functional.py --- tests/test_functional.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index eab941e5..f9264688 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -89,9 +89,6 @@ def test_climo_index( assert resp.content_type == 'text/html' #assert resp.content_length < 0 -# print("resp is") -# print("{}".format(resp)) -# sleep(3) soup = BeautifulSoup(resp.body, "html.parser") assert title in soup.title.string From c2439548c75bf3b101ca78a0325c31a7b8a34220 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:09:42 -0700 Subject: [PATCH 56/71] Fix typo and remove sentence in doc --- doc/source/org.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/org.rst b/doc/source/org.rst index c11ced1f..6865e1f2 100644 --- a/doc/source/org.rst +++ b/doc/source/org.rst @@ -30,12 +30,11 @@ Our initial PCDS portal was developed against the stable Pydap hosted here: https://code.google.com/p/pydap/ Our initial raster portal was developed against the development version of Pydap hosted here: -https://bitbucked.org/robertodealmeida/pydap +https://bitbucket.org/robertodealmeida/pydap But now he's developing on github with a branch that looks pretty similar to the inital stable version: https://github.com/robertodealmeida/pydap -Where to go? Nobody knows. I fear that we may need to maintain our own fork in perpetuity. THREDDS ------- From 98dabe60af619d284d5168e15d67c389ecd85d24 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:10:09 -0700 Subject: [PATCH 57/71] Clean up js code --- pdp/static/js/data-services.js | 9 +++++---- pdp/static/js/hydro_stn_controls.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pdp/static/js/data-services.js b/pdp/static/js/data-services.js index ae4346cd..ccff64f5 100644 --- a/pdp/static/js/data-services.js +++ b/pdp/static/js/data-services.js @@ -120,15 +120,16 @@ const lines = data.split("\n"); const result = {}; if (lines[0] === "Dataset {") { // Response comes from THREDDS - // Ignore header information - for (let i = 5; i < lines.length - 1; i += 3) { + // Ignore header information from lines 0-4 + for (const i = 5; i < lines.length - 1; i += 3) { // Only use coordinate name as key result[lines[i].substring(0,3)] = JSON.parse("[" + lines[i + 1] + "]"); } } else { // Response comes from PyDAP - for (let i = 0; i < lines.length - 1; i += 2) { - result[lines[i]] = JSON.parse(lines[i + 1]); } + for (const i = 0; i < lines.length - 1; i += 2) { + result[lines[i]] = JSON.parse(lines[i + 1]); + } } return result; } diff --git a/pdp/static/js/hydro_stn_controls.js b/pdp/static/js/hydro_stn_controls.js index cadb8b3c..638d0b74 100644 --- a/pdp/static/js/hydro_stn_controls.js +++ b/pdp/static/js/hydro_stn_controls.js @@ -87,7 +87,7 @@ function addToSidebar(idx, dataArray) { }); link = document.createElement('a'); - link.href = pdp.data_root + "/hydro_stn_cmip5/" + dataArray[idx].FileName; + link.href = `${pdp.data_root}/hydro_stn_cmip5/${dataArray[idx].FileName}`; link.appendChild(document.createTextNode(dataArray[idx].StationName)); item.appendChild(link); From 9c2544165edb7772272d9d89dd765719e41d0f60 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:20:16 -0700 Subject: [PATCH 58/71] Rename is_valid_orca functions to assert_is_valid_orca --- tests/test_functional.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index f9264688..460ae7d1 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -20,7 +20,7 @@ from bs4 import BeautifulSoup -def is_valid_orca_nc_url(url_id, resp): +def assert_is_valid_orca_nc_url(url_id, resp): orca_base = os.getenv("ORCA_ROOT") with session_scope(os.getenv("DSN")) as sesh: q = sesh.query(DataFile.filename).filter(DataFile.filename.contains(url_id)) @@ -31,16 +31,14 @@ def is_valid_orca_nc_url(url_id, resp): assert all(dim in resp.location for dim in ["time", "lat", "lon"]) assert orca_base in resp.location assert storage_path in resp.location - return True -def is_valid_orca_csv_url(storage_path, resp): +def assert_is_valid_orca_csv_url(storage_path, resp): orca_base = os.getenv("ORCA_ROOT") assert resp.status == "301 Moved Permanently" assert resp.content_type == "text/plain" assert orca_base in resp.location assert storage_path in resp.location - return True @pytest.mark.parametrize('url', [ @@ -330,7 +328,7 @@ def test_climatology_bounds(pcic_data_portal): req = Request.blank(url) resp = req.get_response(pcic_data_portal) url_id = os.path.basename(url).split(".nc")[0] - assert is_valid_orca_nc_url(url_id, resp) + assert_is_valid_orca_nc_url(url_id, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() @@ -383,7 +381,7 @@ def test_nc_raster_response(pcic_data_portal, url): req = Request.blank(url) resp = req.get_response(pcic_data_portal) url_id = os.path.basename(url).split(".nc")[0] - assert is_valid_orca_nc_url(url_id, resp) + assert_is_valid_orca_nc_url(url_id, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() @@ -436,7 +434,7 @@ def test_hydro_stn_data_csv(pcic_data_portal): storage_root = hydro_stn_config['handlers'][0]['dir'] url_id = os.path.basename(url) storage_path = storage_root + "/" + url_id - assert is_valid_orca_csv_url(storage_path, resp) + assert_is_valid_orca_csv_url(storage_path, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() @@ -479,7 +477,7 @@ def test_hydro_model_out_allwsbc(pcic_data_portal, url): req = Request.blank(url.format(base)) resp = req.get_response(pcic_data_portal) url_id = os.path.basename(url.format(base)).split(".nc")[0] - assert is_valid_orca_nc_url(url_id, resp) + assert_is_valid_orca_nc_url(url_id, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() @@ -504,7 +502,7 @@ def test_empty_hyperslabs(pcic_data_portal, projection, length): req = Request.blank(url) resp = req.get_response(pcic_data_portal) url_id = os.path.basename(url).split(".nc")[0] - assert is_valid_orca_nc_url(url_id, resp) + assert_is_valid_orca_nc_url(url_id, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() @@ -541,7 +539,7 @@ def test_nonrecord_variables(pcic_data_portal, file, expected_mean): req = Request.blank(url) resp = req.get_response(pcic_data_portal) url_id = os.path.basename(url).split(".nc")[0] - assert is_valid_orca_nc_url(url_id, resp) + assert_is_valid_orca_nc_url(url_id, resp) orca_req = Request.blank(resp.location) orca_resp = orca_req.get_response() From 6557fad520ba0385a3e4efcb1569c925a3fd0609 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:20:31 -0700 Subject: [PATCH 59/71] Remove print in test --- tests/test_functional.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_functional.py b/tests/test_functional.py index 460ae7d1..f673063b 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -200,7 +200,6 @@ def test_clip_to_date_one(pcic_data_portal): req = Request.blank(base_url + urlencode(params)) resp = req.get_response(pcic_data_portal) - print(resp.status) assert resp.status == '200 OK' t = TemporaryFile() t.write(resp.body) From 067078739577dbc1fa6f9c02fc16bda650bd2169 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:33:24 -0700 Subject: [PATCH 60/71] Yield strings throughout error.py --- pdp/error.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pdp/error.py b/pdp/error.py index 56f5b1b4..7ab11ca7 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -35,8 +35,8 @@ def custom_start_response(status, headers, exc_info=None): ] start_response(status, response_headers, sys.exc_info()) logger.error("SQLAlchemyError: {}".format(e.args[0])) - yield b'There was an unexpected problem accessing the database\n' - yield e.args[0].encode() + yield 'There was an unexpected problem accessing the database\n' + yield e.args[0] except EnvironmentError as e: # except IOError as e: @@ -63,7 +63,7 @@ def custom_start_response(status, headers, exc_info=None): start_response(status, response_headers, sys.exc_info()) logger.error("500 Internal Server Error: {}\n{}".format( e.args, traceback.format_exc())) - yield b'There was an unhandleable problem with the application\n' + yield 'There was an unhandleable problem with the application\n' yield e.args[0] else: From 175e5ab1a3a0cb5074fd7dbbb1193d65f8273b13 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:33:47 -0700 Subject: [PATCH 61/71] Replace default THREDDS host --- pdp/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdp/__init__.py b/pdp/__init__.py index fc0555ae..5c0fea91 100644 --- a/pdp/__init__.py +++ b/pdp/__init__.py @@ -32,7 +32,7 @@ def get_config_from_environment(): 'data_root': 'http://tools.pacificclimate.org/dataportal/data', 'title': '', 'ensemble_name': '', - 'thredds_root': 'https://docker-dev03.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets', + 'thredds_root': 'https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets', 'orca_root': 'https://services.pacificclimate.org/orca', 'dsn': 'postgresql://user:pass@host/database', 'pcds_dsn': 'postgresql://user:pass@host/database', From e74f36a0ffede5252629b50a0dc4ad0bdb0986ff Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:34:11 -0700 Subject: [PATCH 62/71] Add THREDDS_ROOT to production docker-compose files --- docker/production/docker-compose-local.yaml | 1 + docker/production/docker-compose.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/docker/production/docker-compose-local.yaml b/docker/production/docker-compose-local.yaml index 8401e1ee..3a7f5db1 100755 --- a/docker/production/docker-compose-local.yaml +++ b/docker/production/docker-compose-local.yaml @@ -52,6 +52,7 @@ services: environment: # Specific to backend - ORCA_ROOT=http://pdp.localhost:5000/orca + - THREDDS_ROOT=https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent volumes: diff --git a/docker/production/docker-compose.yaml b/docker/production/docker-compose.yaml index 12744e72..3ede51ea 100644 --- a/docker/production/docker-compose.yaml +++ b/docker/production/docker-compose.yaml @@ -33,6 +33,7 @@ services: environment: # Specific to backend - ORCA_ROOT=https://services.pacificclimate.org/orca + - THREDDS_ROOT=https://marble-dev01.pcic.uvic.ca/twitcher/ows/proxy/thredds/dodsC/datasets - APP_MODULE=pdp.wsgi:backend - GUNICORN_WORKER_CLASS=gevent ports: From 68a0045427abe9dcc02ea330c666300ac7c233ad Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 14:38:29 -0700 Subject: [PATCH 63/71] Remove config property from hydro_stn_cmip5 --- pdp/portals/hydro_stn_cmip5.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pdp/portals/hydro_stn_cmip5.py b/pdp/portals/hydro_stn_cmip5.py index 908c9baf..ad7caaf8 100644 --- a/pdp/portals/hydro_stn_cmip5.py +++ b/pdp/portals/hydro_stn_cmip5.py @@ -37,11 +37,7 @@ class HydroStationDataServer(object): ''' def __init__(self, config): - self._config = config - - @property - def config(self): - return self._config + self.config = config def __call__(self, environ, start_response): with open(resource_filename('pdp', 'resources/hydro_stn_cmip5.yaml')) as hydro_stn_yaml: From 5acf408cd877a93fe2c5b97b4311dd5b79bf5a33 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 15:28:07 -0700 Subject: [PATCH 64/71] Import yaml in test_functional.py --- tests/test_functional.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_functional.py b/tests/test_functional.py index f673063b..bdf8656a 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -4,6 +4,7 @@ from zipfile import ZipFile import csv import json +import yaml import os from pkg_resources import resource_filename import static From c2f0c37f2a3ee4ead6611bd6ac3cb68d3f3a1b88 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 15:28:22 -0700 Subject: [PATCH 65/71] Yield bytes instead of strings --- pdp/error.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pdp/error.py b/pdp/error.py index 7ab11ca7..2e944cfe 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -35,8 +35,8 @@ def custom_start_response(status, headers, exc_info=None): ] start_response(status, response_headers, sys.exc_info()) logger.error("SQLAlchemyError: {}".format(e.args[0])) - yield 'There was an unexpected problem accessing the database\n' - yield e.args[0] + yield b'There was an unexpected problem accessing the database\n' + yield e.args[0].encode() except EnvironmentError as e: # except IOError as e: @@ -54,8 +54,8 @@ def custom_start_response(status, headers, exc_info=None): " filename {}\n" "{}".format( e.errno, e.strerror, e.filename, e.args[0])) - yield 'We had an unexpected problem accessing on-disk resources\n' - yield e.args[0] + yield b'We had an unexpected problem accessing on-disk resources\n' + yield e.args[0] # e.args[0] already in bytes - no need to encode except Exception as e: status = "500 Internal Server Error" @@ -63,7 +63,7 @@ def custom_start_response(status, headers, exc_info=None): start_response(status, response_headers, sys.exc_info()) logger.error("500 Internal Server Error: {}\n{}".format( e.args, traceback.format_exc())) - yield 'There was an unhandleable problem with the application\n' + yield b'There was an unhandleable problem with the application\n' yield e.args[0] else: From e84dfe92c3544f5dd3770649d4d0cca2aedd62b8 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Mon, 24 Jun 2024 16:05:48 -0700 Subject: [PATCH 66/71] Use let instead of const for looping variable --- pdp/static/js/data-services.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdp/static/js/data-services.js b/pdp/static/js/data-services.js index ccff64f5..0c381a72 100644 --- a/pdp/static/js/data-services.js +++ b/pdp/static/js/data-services.js @@ -121,13 +121,13 @@ const result = {}; if (lines[0] === "Dataset {") { // Response comes from THREDDS // Ignore header information from lines 0-4 - for (const i = 5; i < lines.length - 1; i += 3) { + for (let i = 5; i < lines.length - 1; i += 3) { // Only use coordinate name as key result[lines[i].substring(0,3)] = JSON.parse("[" + lines[i + 1] + "]"); } } else { // Response comes from PyDAP - for (const i = 0; i < lines.length - 1; i += 2) { + for (let i = 0; i < lines.length - 1; i += 2) { result[lines[i]] = JSON.parse(lines[i + 1]); } } From df55cce48493140301ecf22bdd650c88f5b7ad84 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 28 Jun 2024 12:48:41 -0700 Subject: [PATCH 67/71] Remove comment about non-iterable errors --- pdp/error.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/pdp/error.py b/pdp/error.py index 2e944cfe..e44a3a3b 100644 --- a/pdp/error.py +++ b/pdp/error.py @@ -69,21 +69,6 @@ def custom_start_response(status, headers, exc_info=None): else: # Catch error that happen while generating a streamed response try: - # in theory, this block should be receiving an iterable - # that can be stepped over and streamed to the browser. - # in practice, the upgrade to python 3 has resulted in - # the reception of non-iterable types. - # These ifs catch and convert the non-iterable - # objects for a graceful recovery, while logging an error - # message so that the coder can track down the source of - # the unexpected type. - # The else is the previous behaviour) - # So far the following types have been observed: - # * bytes - sometimes sent by the front end - # * strings - sometimes sent by backend API calls - # * Response objects - not yet clear who is sending these - # TODO: get everyone to send expected generators, - # remove this failsafe code. if isinstance(response_iter, bytes): yield response_iter elif isinstance(response_iter, str): From 9d72ffe0b5714baef68f53092b078bca572d4f97 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 28 Jun 2024 12:49:09 -0700 Subject: [PATCH 68/71] Remove most of Pydap paragraph --- doc/source/org.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/org.rst b/doc/source/org.rst index 6865e1f2..95c235b5 100644 --- a/doc/source/org.rst +++ b/doc/source/org.rst @@ -24,7 +24,7 @@ All raster overlay layers are rendered and served by a PCIC-modificiation of the Pydap ----- -In the past, we used Pydap as our OPeNDAP backend server for all of our data portals, but it is now solely used for the (now deprecated) PCDS portal. Using Pydap has presented us with a variety of opportunities and challenges. On one hand, development of pydap is very modular, dynamic, and open. This has allowed us to easily write custom code to accomplish things that would be otherwise impossible, such as streaming large data responses, having a near-zero memory footprint, and write our own custom data handlers and responses. On the other hand, pydap can be a moving target. Pydap's development repository has lived in three different locations since we started, most of the code base is not rigorously tested (until lately), and API changes have been common. Few of our contributions have been upstreamed, which means that we live in a perpertual state of fear of upgrade. Pydap is mostly a one man show, which mean works-for-me syndrome is common. +In the past, we used Pydap as our OPeNDAP backend server for all of our data portals, but it is now solely used for the (now deprecated) PCDS portal. Our initial PCDS portal was developed against the stable Pydap hosted here: https://code.google.com/p/pydap/ From 56ea34635f0d3a83121db954f9ae184522d44c7b Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 28 Jun 2024 12:50:28 -0700 Subject: [PATCH 69/71] Add comment about replacing pdp-base-minimal tag with new release once it's created --- docker/ci/Dockerfile | 2 +- docker/local-run/Dockerfile | 4 ++-- docker/local-test/Dockerfile | 2 +- docker/production/Dockerfile | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index d5746324..b6dcdba5 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -1,4 +1,4 @@ -FROM pcic/pdp-base-minimal-unsafe:pdp-python3 +FROM pcic/pdp-base-minimal-unsafe:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged COPY ./ ${USER_DIR} diff --git a/docker/local-run/Dockerfile b/docker/local-run/Dockerfile index 8bd84aea..14a1d100 100644 --- a/docker/local-run/Dockerfile +++ b/docker/local-run/Dockerfile @@ -1,4 +1,4 @@ -FROM pcic/pdp-base-minimal:pdp-python3 +FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged LABEL Maintainer="Rod Glover " USER root @@ -18,4 +18,4 @@ ADD *requirements.txt /codebase/ RUN pip3 install -r requirements.txt -r test_requirements.txt -r deploy_requirements.txt -ENTRYPOINT ./docker/local-run/entrypoint.sh \ No newline at end of file +ENTRYPOINT ./docker/local-run/entrypoint.sh diff --git a/docker/local-test/Dockerfile b/docker/local-test/Dockerfile index 703b9a19..a6dee35d 100644 --- a/docker/local-test/Dockerfile +++ b/docker/local-test/Dockerfile @@ -1,4 +1,4 @@ -FROM pcic/pdp-base-minimal:pdp-python3 +FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged USER root # TODO: Move into pdp-base-minimal? diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index ed05a288..a56dd22b 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -2,7 +2,7 @@ # Dockerfile to run the PCIC data portal # ############################################ -FROM pcic/pdp-base-minimal:pdp-python3 +FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged LABEL Maintainer="James Hiebert " USER root From b818f9e22b071491df814635e6c6796cf1ba7c97 Mon Sep 17 00:00:00 2001 From: Eric Yvorchuk Date: Fri, 28 Jun 2024 12:54:00 -0700 Subject: [PATCH 70/71] Move Dockerfile comments to own line --- docker/ci/Dockerfile | 3 ++- docker/local-run/Dockerfile | 3 ++- docker/local-test/Dockerfile | 3 ++- docker/production/Dockerfile | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docker/ci/Dockerfile b/docker/ci/Dockerfile index b6dcdba5..24716b31 100644 --- a/docker/ci/Dockerfile +++ b/docker/ci/Dockerfile @@ -1,4 +1,5 @@ -FROM pcic/pdp-base-minimal-unsafe:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged +# TODO: Replace pdp-base-minimal tag with new release tag when this branch of pdp-docker has been merged +FROM pcic/pdp-base-minimal-unsafe:pdp-python3 COPY ./ ${USER_DIR} diff --git a/docker/local-run/Dockerfile b/docker/local-run/Dockerfile index 14a1d100..90bd4e51 100644 --- a/docker/local-run/Dockerfile +++ b/docker/local-run/Dockerfile @@ -1,4 +1,5 @@ -FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged +# TODO: Replace pdp-base-minimal tag with new release tag when this branch of pdp-docker has been merged +FROM pcic/pdp-base-minimal:pdp-python3 LABEL Maintainer="Rod Glover " USER root diff --git a/docker/local-test/Dockerfile b/docker/local-test/Dockerfile index a6dee35d..a8b8ff63 100644 --- a/docker/local-test/Dockerfile +++ b/docker/local-test/Dockerfile @@ -1,4 +1,5 @@ -FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged +# TODO: Replace pdp-base-minimal tag with new release tag when this branch of pdp-docker has been merged +FROM pcic/pdp-base-minimal:pdp-python3 USER root # TODO: Move into pdp-base-minimal? diff --git a/docker/production/Dockerfile b/docker/production/Dockerfile index a56dd22b..4433d13a 100644 --- a/docker/production/Dockerfile +++ b/docker/production/Dockerfile @@ -2,7 +2,8 @@ # Dockerfile to run the PCIC data portal # ############################################ -FROM pcic/pdp-base-minimal:pdp-python3 # Replace with new release tag when this branch of pdp-docker has been merged +# TODO: Replace pdp-base-minimal tag with new release tag when this branch of pdp-docker has been merged +FROM pcic/pdp-base-minimal:pdp-python3 LABEL Maintainer="James Hiebert " USER root From 4821f0968253d9ac86ec46a1aa992f907d1f9a1a Mon Sep 17 00:00:00 2001 From: Lee Zeman Date: Fri, 23 Aug 2024 20:08:51 -0700 Subject: [PATCH 71/71] update to new pdp_util release --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 248c8330..335cec7f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -33,7 +33,7 @@ numpy==1.21 olefile==0.46 openid2rp==1.12 Paste==3.7.1 -git+https://github.com/pacificclimate/pdp_util@generate-metadata # actually using a custom version, will be changed when new release is created +pdp_util==3.0.0 Pillow==5.4.1 ply==3.10 psycopg2==2.9.6