Beispiel #1
0
def authenticate(env_user="******", env_pass="******"):
    """Authenticate the user ID and password for connection to Zoltar.

    :param env_user: username of account in Zoltar
    :param env_pass: password ""
    """
    # Ensure environment variables exist
    env_vars = [env_user, env_pass]
    for var in env_vars:
        if os.environ.get(var) == None:
            print("\nERROR: Cannot locate environment variable:  %s" % var)
            print(
                "\nPC users, try the command: set %s='<your zoltar username>'"
                % var)
            print(
                "Mac users, try the command: export %s=<your zoltar username>"
                % var)
            print("Then, Refresh the command window\n")
            return
    # Authenticate Zoltar connection
    try:
        conn = ZoltarConnection()
        conn.authenticate(os.environ.get(env_user), os.environ.get(env_pass))
        return conn
    except Exception as exc:
        print(f"Error authenticating Zoltar credentials: {exc!r}.")
        print(
            f"Ensure the environment variables for your username and password are correct."
        )
    return print("ERROR")
Beispiel #2
0
def create_project_app():
    """Application that demonstrates project creation and deletion.

    App args:
    - zoltar_host: host to pass to ZoltarConnection(). This is typically "https://www.zoltardata.com" (no quotes and no
        trailing '/') unless used for developer testing.
    - project_config_file: configuration json file for the project of interest. see zoltar documentation for details,
        esp. utils.project.create_project_from_json()

    Required environment variables:
    - 'Z_USERNAME': username of the account that has permission to access the resources in above app args
    - 'Z_PASSWORD': password ""
    """
    #host = sys.argv[1]
    project_config_file = sys.argv[1]

    conn = ZoltarConnection()
    conn.authenticate(os.environ.get('Z_USERNAME'),
                      os.environ.get('Z_PASSWORD'))

    with open(project_config_file) as fp:
        project_dict = json.load(fp)

    # delete existing project if found
    project_dict = project_dict[0]
    existing_project = [
        project for project in conn.projects
        if project.name == project_dict['name']
    ]
    if existing_project:
        existing_project = existing_project[0]
        print(f"deleting existing project: {existing_project}")
        existing_project.delete()
        print("delete done")

    # create new project
    print(f"creating new project. project name={project_dict['name']}")
    response = requests.post(
        f'{conn.host}/api/projects/',
        headers={'Authorization': f'JWT {conn.session.token}'},
        json={'project_config': project_dict})
    if response.status_code != 200:  # HTTP_200_OK
        raise RuntimeError(
            f"status_code was not 200. status_code={response.status_code}, text={response.text}"
        )

    new_project_json = response.json()
    new_project = Project(conn, new_project_json['url'])
    print(f"created new project: {new_project}")
def upload_to_zoltar(site_key, is_local_host=False):
    proj_config = read_config(CONFIG_LOCAL_PATH)

    helpers = {
        FTE: upload_to_zoltar_fte,
        ECONOMIST: upload_to_zoltar_economist
    }

    if is_local_host:
        conn = ZoltarConnection(LOCAL_HOST)
        conn.authenticate(LOCAL_USERNAME, LOCAL_PASSWORD)
        helpers[site_key](conn, proj_config)
    else:
        conn = util.authenticate()
        helpers[site_key](conn, proj_config)
Beispiel #4
0
    def test_is_token_expired(self):
        # test an expired token
        conn = mock_authenticate(ZoltarConnection(
            'http://example.com'))  # default token (mock_token) is expired
        self.assertTrue(conn.session.is_token_expired())

        # construct and test an unexpired token
        token_split = MOCK_TOKEN.split(
            '.')  # 3 parts: header, payload, signature
        old_header = token_split[0]
        old_signature = token_split[1]

        # round to exclude decimal portion - throws off some JWT tools:
        ten_min_from_now = round((datetime.datetime.utcnow() +
                                  datetime.timedelta(minutes=10)).timestamp())
        new_payload = {
            'user_id': 3,
            'username': '******',
            'exp': ten_min_from_now,
            'email': ''
        }
        new_payload_json = json.dumps(new_payload)
        payload_b64 = base64.b64encode(new_payload_json.encode('utf_8'))
        unexpired_token = f"{old_header}.{payload_b64.decode('utf-8')}.{old_signature}"
        conn.session.token = unexpired_token
        self.assertFalse(conn.session.is_token_expired())
Beispiel #5
0
 def test_json_for_uri_calls_re_authenticate_if_necessary(self):
     with patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock, \
             patch('requests.get') as get_mock:
         get_mock.return_value.status_code = 200
         conn = mock_authenticate(ZoltarConnection('http://example.com'))
         conn.json_for_uri('/')
         re_auth_mock.assert_called_once()
    def test_verify_instance_api_hits(self, json_for_uri_mock):
        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        conn = ZoltarConnection('https://example.com')
        projects = conn.projects
        json_for_uri_mock.assert_called_once_with(
            'https://example.com/api/projects/')

        json_for_uri_mock.reset_mock()
        models = projects[0].models
        json_for_uri_mock.assert_called_once_with(
            'http://example.com/api/project/3/models/')

        json_for_uri_mock.reset_mock()
        projects[0].units
        json_for_uri_mock.assert_called_once_with(
            'http://example.com/api/project/3/units/')

        json_for_uri_mock.reset_mock()
        projects[0].targets
        json_for_uri_mock.assert_called_once_with(
            'http://example.com/api/project/3/targets/')

        json_for_uri_mock.reset_mock()
        projects[0].timezeros
        json_for_uri_mock.assert_called_once_with(
            'http://example.com/api/project/3/timezeros/')

        json_for_uri_mock.return_value = MODELS_LIST_DICTS[0]
        json_for_uri_mock.reset_mock()
        models[0].name
        json_for_uri_mock.assert_not_called()
Beispiel #7
0
 def test_create_timezero(self):
     conn = mock_authenticate(ZoltarConnection('http://example.com'))
     with patch('zoltpy.connection.ZoltarConnection.json_for_uri', return_value=PROJECTS_LIST_DICTS), \
          patch('requests.post') as post_mock, \
             patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock:
         project = conn.projects[0]
         post_mock.return_value.status_code = 200
         post_return_value = {
             "id": 705,
             "url": "http://example.com/api/timezero/705/",
             "timezero_date": "2011-10-02",
             "data_version_date": "2011-10-03",
             "is_season_start": True,
             "season_name": "2011-2012"
         }
         post_mock.return_value.json = MagicMock(
             return_value=post_return_value)
         project.create_timezero("2011-10-02", "2011-10-03", True,
                                 "2011-2012")
         post_mock.assert_called_once()
         exp_timezero_config = dict(post_return_value)  # copy
         del exp_timezero_config['id']
         del exp_timezero_config['url']
         act_timezero_config = post_mock.call_args[1]['json'][
             'timezero_config']
         self.assertEqual(exp_timezero_config, act_timezero_config)
         re_auth_mock.assert_called_once()
    def test_query_with_ids(self, json_for_uri_mock):
        def json_for_uri_mock_side_effect(*args, **kwargs):
            return {
                'http://example.com/api/projects/': PROJECTS_LIST_DICTS,
                'http://example.com/api/project/3/models/': MODELS_LIST_DICTS,
                'http://example.com/api/project/3/units/': UNITS_LIST_DICTS,
                'http://example.com/api/project/3/targets/':
                TARGETS_LIST_DICTS,
                'http://example.com/api/project/3/timezeros/':
                TIMEZEROS_LIST_DICTS
            }[args[0]]

        json_for_uri_mock.side_effect = json_for_uri_mock_side_effect
        conn = mock_authenticate(ZoltarConnection('http://example.com'))

        project = conn.projects[0]

        # case: blue sky
        input_exp_output_queries = [
            ({}, {}),
            ({
                'models': ['docs forecast model'],
                'units': ['location1', 'location2'],
                'targets': ['pct next week', 'cases next week'],
                'timezeros': ['2011-10-02', '2011-10-16'],
                'types': ['point', 'quantile']
            }, {
                'models': [5],
                'units': [23, 24],
                'targets': [15, 16],
                'timezeros': [5, 7],
                'types': ['point', 'quantile']
            }),
            (
                {
                    'models': ['doc_model_abbrev']
                },  # 'models' can be either model name or abbreviation
                {
                    'models': [5]
                })
        ]
        for input_query, exp_output_query in input_exp_output_queries:
            act_output_query = project.query_with_ids(input_query)
            self.assertEqual(exp_output_query, act_output_query)

        # case: name not found
        for query in [{
                'models': ['bad model name']
        }, {
                'units': ['bad unit name']
        }, {
                'targets': ['bad target name']
        }, {
                'timezeros': ['1999-10-02']
        }]:
            with self.assertRaises(RuntimeError) as context:
                project.query_with_ids(query)
            self.assertIn('one or more', str(context.exception))
 def test_authenticate(self):
     conn = ZoltarConnection('')
     username = '******'
     password = '******'
     mock_authenticate(conn, username, password)
     with patch('requests.post') as post_mock:
         post_mock.return_value.status_code = 200
         post_mock.return_value.json = MagicMock(
             return_value={'token': MOCK_TOKEN})
         conn.authenticate(username, password)
         self.assertEqual(username, conn.username)
         self.assertEqual(password, conn.password)
         self.assertIsInstance(conn.session, ZoltarSession)
         self.assertEqual(MOCK_TOKEN, conn.session.token)
         post_mock.assert_called_once_with('/api-token-auth/', {
             'username': '******',
             'password': '******'
         })
Beispiel #10
0
    def test_instances(self, json_for_uri_mock):
        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        conn = ZoltarConnection()

        # test ZoltarConnection.projects
        projects = conn.projects  # hits /api/projects/
        self.assertEqual(2, len(projects))

        project_0 = projects[0]
        self.assertIsInstance(project_0, Project)
        self.assertEqual("Docs Example Project", project_0.name)

        # test Project.models
        json_for_uri_mock.return_value = MODELS_LIST_DICTS
        models = project_0.models  # hits api/project/3/models/
        self.assertEqual(1, len(models))

        model_0 = models[0]
        self.assertIsInstance(model_0, Model)
        self.assertEqual("docs forecast model", model_0.name)

        # test Project.units
        json_for_uri_mock.return_value = UNITS_LIST_DICTS
        units = project_0.units  # hits api/project/3/units/
        self.assertEqual(3, len(units))

        unit_0 = units[0]
        self.assertIsInstance(unit_0, Unit)
        self.assertEqual("location1", unit_0.name)

        # test Project.targets
        json_for_uri_mock.return_value = TARGETS_LIST_DICTS
        targets = project_0.targets  # hits api/project/3/targets/
        self.assertEqual(2, len(targets))

        target_0 = targets[0]
        self.assertIsInstance(target_0, Target)
        self.assertEqual("pct next week", target_0.name)

        # test Project.timezeros
        json_for_uri_mock.return_value = TIMEZEROS_LIST_DICTS
        timezeros = project_0.timezeros  # hits api/project/3/timezeros/
        self.assertEqual(3, len(timezeros))

        timezero_0 = timezeros[0]
        self.assertIsInstance(timezero_0, TimeZero)
        self.assertEqual("2011-10-02", timezero_0.timezero_date)

        # test Model.forecasts
        json_for_uri_mock.return_value = FORECASTS_LIST_DICTS
        forecasts = model_0.forecasts  # hits api/model/5/forecasts/
        self.assertEqual(1, len(forecasts))

        forecast_0 = forecasts[0]
        self.assertIsInstance(forecast_0, Forecast)
        self.assertEqual("docs-predictions.json", forecast_0.source)
Beispiel #11
0
 def test_delete_calls_re_authenticate_if_necessary(self):
     with patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock, \
             patch('zoltpy.connection.ZoltarConnection.json_for_uri') as json_for_uri_mock, \
             patch('requests.delete') as delete_mock:
         json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
         delete_mock.return_value.status_code = 200
         conn = mock_authenticate(ZoltarConnection('http://example.com'))
         projects = conn.projects
         projects[0].delete()
         re_auth_mock.assert_called_once()
Beispiel #12
0
 def test_create_model(self, json_for_uri_mock):
     with open('examples/example-model-config.json') as fp:
         model_config = json.load(fp)
         model_config['url'] = 'http://example.com/api/model/5/'
     conn = mock_authenticate(ZoltarConnection('http://example.com'))
     project = Project(conn, 'http://example.com/api/project/3/')
     with patch('requests.post') as post_mock, \
             patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock:
         post_mock.return_value.status_code = 200
         post_mock.return_value.json = MagicMock(return_value=model_config)
         new_model = project.create_model(model_config)
         self.assertEqual(1, post_mock.call_count)
         self.assertEqual('http://example.com/api/project/3/models/',
                          post_mock.call_args[0][0])
         self.assertIsInstance(new_model, Model)
         re_auth_mock.assert_called_once()
Beispiel #13
0
 def test_upload_truth_data(self, json_for_uri_mock):
     conn = mock_authenticate(ZoltarConnection('http://example.com'))
     project = Project(conn, 'http://example.com/api/project/3/')
     with open('tests/job-2.json') as ufj_fp, \
             open('tests/docs-ground-truth.csv') as csv_fp, \
             patch('requests.post') as post_mock, \
             patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock:
         job_json = json.load(ufj_fp)
         post_mock.return_value.status_code = 200
         post_mock.return_value.json = MagicMock(return_value=job_json)
         act_job_json = project.upload_truth_data(csv_fp)
         re_auth_mock.assert_called_once()
         self.assertEqual(1, post_mock.call_count)
         self.assertEqual('http://example.com/api/project/3/truth/',
                          post_mock.call_args[0][0])
         self.assertIsInstance(act_job_json, Job)
         self.assertEqual(job_json['url'], act_job_json.uri)
Beispiel #14
0
 def test_upload_forecast(self, json_for_uri_mock):
     conn = mock_authenticate(ZoltarConnection('http://example.com'))
     with open('tests/job-2.json') as ufj_fp, \
             open("examples/example-model-config.json") as fp, \
             patch('requests.post') as post_mock, \
             patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock:
         job_json = json.load(ufj_fp)
         model_config = json.load(fp)
         model_config['url'] = 'http://example.com/api/model/5/'
         post_mock.return_value.status_code = 200
         post_mock.return_value.json = MagicMock(return_value=job_json)
         forecast_model = Model(conn, model_config['url'], model_config)
         act_job_json = forecast_model.upload_forecast({}, None, None)
         re_auth_mock.assert_called_once()
         self.assertEqual(1, post_mock.call_count)
         self.assertEqual('http://example.com/api/model/5/forecasts/',
                          post_mock.call_args[0][0])
         self.assertIsInstance(act_job_json, Job)
         self.assertEqual(job_json['url'], act_job_json.uri)
Beispiel #15
0
    def test_submit_truth_query(self, json_for_uri_mock):
        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        conn = mock_authenticate(ZoltarConnection('http://example.com'))
        project = conn.projects[0]

        with open('tests/job-submit-query.json') as job_submit_json_fp, \
                patch('requests.post') as post_mock, \
                patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary'):
            # test submit
            query = {}  # all forecasts
            job_submit_json = json.load(job_submit_json_fp)
            post_mock.return_value.status_code = 200
            post_mock.return_value.json = MagicMock(
                return_value=job_submit_json)
            job = project.submit_query(QueryType.TRUTH, query)
            self.assertEqual('http://example.com/api/project/3/truth_queries/',
                             post_mock.call_args[0][0])
            self.assertEqual(post_mock.call_args[1]['json'], {'query': query})
            self.assertIsInstance(job, Job)
Beispiel #16
0
    def test_forecasts_set_issued_at(self):
        from tests.test_util import FORECAST_DICT  # avoid circular imports

        conn = mock_authenticate(ZoltarConnection(
            'http://example.com'))  # default token (mock_token) is expired
        with patch('requests.patch') as patch_mock, \
                patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary') as re_auth_mock, \
                patch('zoltpy.connection.ZoltarConnection.json_for_uri') as json_for_uri_mock:
            patch_mock.return_value.status_code = 200
            forecast = Forecast(conn, "http://example.com/api/forecast/3/",
                                FORECAST_DICT)
            self.assertEqual(FORECAST_DICT['issued_at'], forecast.issued_at)

            new_issued_at = 'new issued_at'  # type isn't checked locally, just remotely
            new_forecast_dict = dict(FORECAST_DICT)  # non-deep copy OK
            new_forecast_dict['issued_at'] = new_issued_at
            forecast.issued_at = new_issued_at  # call setter. does not refresh
            json_for_uri_mock.return_value = new_forecast_dict
            forecast.refresh()
            self.assertEqual(new_issued_at, forecast.issued_at)
Beispiel #17
0
    def test_delete_forecast(self):
        def json_for_uri_mock_side_effect(*args, **kwargs):  # returns a sequence of return args
            return {'http://example.com/api/projects/': PROJECTS_LIST_DICTS,
                    'http://example.com/api/project/3/models/': [MODEL_DICT],
                    'https://example.com/api/model/150/forecasts/': [FORECAST_DICT]}[args[0]]


        conn = mock_authenticate(ZoltarConnection('http://example.com'))
        with patch('zoltpy.connection.ZoltarConnection.json_for_uri') as json_for_uri_mock, \
                patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary'), \
                patch('zoltpy.connection.Forecast.delete') as delete_forecast_mock:
            json_for_uri_mock.side_effect = json_for_uri_mock_side_effect

            # case: finds existing_forecast
            delete_forecast(conn, PROJECTS_LIST_DICTS[0]['name'], MODEL_DICT['name'], '2020-04-12')
            self.assertEqual(1, delete_forecast_mock.call_count)

            # case: does not find existing_forecast
            delete_forecast_mock.reset_mock()
            delete_forecast(conn, PROJECTS_LIST_DICTS[0]['name'], MODEL_DICT['name'], '2020-04-22')
            self.assertEqual(0, delete_forecast_mock.call_count)
Beispiel #18
0
    def test_download_forecast(self):
        def json_for_uri_mock_side_effect(*args, **kwargs):  # returns a sequence of return args
            return {'http://example.com/api/projects/': PROJECTS_LIST_DICTS,
                    'http://example.com/api/project/3/models/': [MODEL_DICT],
                    'https://example.com/api/model/150/forecasts/': [FORECAST_DICT]}[args[0]]


        conn = mock_authenticate(ZoltarConnection('http://example.com'))
        with patch('zoltpy.connection.ZoltarConnection.json_for_uri') as json_for_uri_mock, \
                patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary'), \
                patch('zoltpy.connection.Forecast.data') as forecast_data_mock:
            json_for_uri_mock.side_effect = json_for_uri_mock_side_effect

            project_name = "Docs Example Project"
            model_abbr = "60-contact"
            timezero_date = "2020-04-12"

            # case: blue sky
            download_forecast(conn, project_name, model_abbr, timezero_date)
            forecast_data_mock.assert_called_once()

            # case: bad project name
            forecast_data_mock.reset_mock()
            with self.assertRaises(RuntimeError) as context:
                download_forecast(conn, project_name + 'bad', model_abbr, timezero_date)
            self.assertIn('found no project named', str(context.exception))

            # case: bad model name
            forecast_data_mock.reset_mock()
            with self.assertRaises(RuntimeError) as context:
                download_forecast(conn, project_name, model_abbr + 'bad', timezero_date)
            self.assertIn('found no model named', str(context.exception))

            # case: bad timezero_date
            forecast_data_mock.reset_mock()
            with self.assertRaises(RuntimeError) as context:
                download_forecast(conn, project_name, model_abbr, "2020-02-22")
            self.assertIn('found no forecast with timezero date', str(context.exception))
Beispiel #19
0
    def test_edit_model(self, json_for_uri_mock):
        conn = ZoltarConnection()
        mock_authenticate(conn, '', '')

        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        projects = conn.projects  # hits /api/projects/
        project_0 = projects[0]

        json_for_uri_mock.return_value = MODELS_LIST_DICTS
        models = project_0.models  # hits api/project/3/models/
        model_0 = models[0]

        with open('examples/example-model-config.json') as fp:
            model_config = json.load(fp)

        # case: blue sky
        with patch('requests.put') as put_mock:
            put_mock.return_value.status_code = 200
            model_0.edit(model_config)
            put_mock.assert_called_once_with(
                'http://example.com/api/model/5/',
                data={'model_config': model_config},
                headers={'Authorization': f'JWT {MOCK_TOKEN}'})
Beispiel #20
0
    def test_submit_and_download_forecast_query(self, json_for_uri_mock):
        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        conn = mock_authenticate(ZoltarConnection('http://example.com'))
        project = conn.projects[0]

        with open('tests/job-submit-query.json') as job_submit_json_fp, \
                patch('requests.post') as post_mock, \
                patch('zoltpy.connection.ZoltarConnection.re_authenticate_if_necessary'):
            # test submit
            query = {}  # all forecasts
            job_submit_json = json.load(job_submit_json_fp)
            post_mock.return_value.status_code = 200
            post_mock.return_value.json = MagicMock(
                return_value=job_submit_json)
            job = project.submit_query(QueryType.FORECASTS, query)
            self.assertEqual(
                'http://example.com/api/project/3/forecast_queries/',
                post_mock.call_args[0][0])
            self.assertEqual(post_mock.call_args[1]['json'], {'query': query})
            self.assertIsInstance(job, Job)

            # test download
            json_for_uri_mock.reset_mock(return_value=True)
            json_for_uri_mock.return_value.content = b'unit,target,class,value,cat,prob,sample,quantile,family,param1,param2,param3\r\nlocation1,season severity,bin,,moderate,0.1,,,,,,\r\n'
            rows = job.download_data()
            json_for_uri_mock.assert_called_once_with(
                'http://127.0.0.1:8000/api/job/44/data/', False, 'text/csv')
            self.assertEqual(2, len(rows))
            exp_rows = [[
                'unit', 'target', 'class', 'value', 'cat', 'prob', 'sample',
                'quantile', 'family', 'param1', 'param2', 'param3'
            ],
                        [
                            'location1', 'season severity', 'bin', '',
                            'moderate', '0.1', '', '', '', '', '', ''
                        ]]
            self.assertEqual(exp_rows, rows)
Beispiel #21
0
    def test_instances(self, json_for_uri_mock):
        json_for_uri_mock.return_value = PROJECTS_LIST_DICTS
        conn = ZoltarConnection()

        # test ZoltarConnection.projects
        projects = conn.projects  # hits /api/projects/
        self.assertEqual(2, len(projects))

        project_0 = projects[0]
        self.assertIsInstance(project_0, Project)
        self.assertEqual("Docs Example Project", project_0.name)

        # test Project.models
        json_for_uri_mock.return_value = MODELS_LIST_DICTS
        models = project_0.models  # hits api/project/3/models/
        self.assertEqual(1, len(models))

        model_0 = models[0]
        self.assertIsInstance(model_0, Model)
        self.assertEqual("docs forecast model", model_0.name)

        # test Project.units
        json_for_uri_mock.return_value = UNITS_LIST_DICTS
        units = project_0.units  # hits api/project/3/units/
        self.assertEqual(3, len(units))

        unit_0 = units[0]
        self.assertIsInstance(unit_0, Unit)
        self.assertEqual("loc1", unit_0.abbreviation)
        self.assertEqual("location1", unit_0.name)

        # test Project.targets
        json_for_uri_mock.return_value = TARGETS_LIST_DICTS
        targets = project_0.targets  # hits api/project/3/targets/
        self.assertEqual(2, len(targets))

        target_0 = targets[0]
        self.assertIsInstance(target_0, Target)
        self.assertEqual("pct next week", target_0.name)

        # test Project.timezeros
        json_for_uri_mock.return_value = TIMEZEROS_LIST_DICTS
        timezeros = project_0.timezeros  # hits api/project/3/timezeros/
        self.assertEqual(3, len(timezeros))

        timezero_0 = timezeros[0]
        self.assertIsInstance(timezero_0, TimeZero)  # "2011-10-02"
        self.assertIsInstance(timezero_0.timezero_date, datetime.date)
        self.assertIsInstance(timezero_0.data_version_date, datetime.date)
        self.assertEqual(datetime.date(2011, 10, 2), timezero_0.timezero_date)
        self.assertEqual(datetime.date(2011, 10, 22),
                         timezero_0.data_version_date)

        timezero_1 = timezeros[1]  # None
        self.assertIsInstance(timezero_1.timezero_date, datetime.date)
        self.assertEqual(datetime.date(2011, 10, 9), timezero_1.timezero_date)
        self.assertEqual(None, timezero_1.data_version_date)

        # test Project.created_at
        json_for_uri_mock.return_value = {
            "id": 44,
            "url": "https://www.zoltardata.com/api/project/44/truth/",
            "project": "https://www.zoltardata.com/api/project/44/",
            "source": "zoltar-truth.csv",
            "created_at": "2021-06-16T21:06:37.893283+00:00",
            "issued_at": "2021-06-16T21:06:37.851554+00:00"
        }
        created_at = project_0.truth_created_at
        self.assertIsInstance(created_at, datetime.datetime)
        self.assertEqual(
            dateutil.parser.parse("2021-06-16T21:06:37.893283+00:00"),
            created_at)

        issued_at = project_0.truth_issued_at
        self.assertIsInstance(issued_at, datetime.datetime)
        self.assertEqual(
            dateutil.parser.parse("2021-06-16T21:06:37.851554+00:00"),
            issued_at)

        # test Model.forecasts
        json_for_uri_mock.return_value = FORECASTS_LIST_DICTS
        forecasts = model_0.forecasts  # hits api/model/5/forecasts/
        self.assertEqual(2, len(forecasts))

        # test Model.latest_forecast
        json_for_uri_mock.return_value = FORECASTS_LIST_DICTS
        latest_forecast = model_0.latest_forecast  # hits api/model/5/forecasts/
        self.assertIsInstance(latest_forecast, Forecast)
        self.assertEqual(
            '2020-08-17',
            latest_forecast.timezero.timezero_date.strftime(
                YYYY_MM_DD_DATE_FORMAT))

        forecast_0 = forecasts[0]
        self.assertIsInstance(forecast_0, Forecast)
        self.assertEqual('2020-08-17-COVIDhub-ensemble.csv', forecast_0.source)
import pprint

logger = logging.getLogger(__name__)

#TODO: Make these as environment variables
STAGING = False

# meta info
project_name = 'COVID-19 Forecasts'
project_obj = None
project_timezeros = []

# Is staging is set to True, use the staging server
if STAGING:
    conn = ZoltarConnection(host='https://rl-zoltar-staging.herokuapp.com')
else:
    conn = ZoltarConnection()
conn.authenticate(os.environ.get("Z_USERNAME"), os.environ.get("Z_PASSWORD"))

url = 'https://github.com/reichlab/covid19-forecast-hub/tree/master/data-processed/'

# mapping of variables in the metadata to the parameters in Zoltar
metadata_field_to_zoltar = {
    'team_name': 'team_name',
    'model_name': 'name',
    'model_abbr': 'abbreviation',
    'model_contributors': 'contributors',
    'website_url': 'home_url',
    'license': 'license',
    'team_model_designation': 'notes',
Beispiel #23
0
import pandas as pd
from zoltpy.quantile_io import json_io_dict_from_quantile_csv_file
from zoltpy import util
from zoltpy.cdc_io import YYYY_MM_DD_DATE_FORMAT
from zoltpy.connection import ZoltarConnection
import os

project_name = 'COVID-19 Forecasts'
conn = ZoltarConnection()
conn.authenticate(os.environ.get("Z_USERNAME"), os.environ.get("Z_PASSWORD"))
project_obj = [
    project for project in conn.projects if project.name == project_name
][0]
models = [model for model in project_obj.models]
forecasts = []
for model in models:
    forecasts.extend(list(model.forecasts))

forecast_sources = [forecast.source for forecast in forecasts]

deleted_forecasts = pd.read_csv("deleted_forecasts.csv")

for forecast in deleted_forecasts['file_name']:
    if forecast in forecast_sources:
        print(forecast)
Beispiel #24
0
def create_model_app():
    """Application that demonstrates model creation and deletion.

    App args:
    - zoltar_host: host to pass to ZoltarConnection()
    - project_name: name of Project to work with
    - model_name: name of a ForecastModel to create and delete. it will be given demonstration data

    Required environment variables:
    - 'Z_USERNAME': username of the account that has permission to access the resources in above app args
    - 'Z_PASSWORD': password ""
    """
    host = sys.argv[1]
    project_name = sys.argv[2]
    model_name = sys.argv[3]

    conn = ZoltarConnection(host)
    conn.authenticate(os.environ.get('Z_USERNAME'),
                      os.environ.get('Z_PASSWORD'))

    # delete existing model if found
    project = [
        project for project in conn.projects if project.name == project_name
    ]
    if not project:
        print(f"could not find project with model_name={project_name!r}")
        return

    # show all models prior to delete/create
    project = project[0]
    print(f'\n* "before" models in {project}')
    for model in project.models:
        print(f'- {model}')

    existing_model = [
        model for model in project.models if model.name == model_name
    ]
    if existing_model:
        existing_model = existing_model[0]
        print(f"deleting existing model: {existing_model}")
        existing_model.delete()
        print("delete done")

    # create new model
    model_config = {
        'name': 'a model_name',
        'abbreviation': 'an abbreviation',
        'team_name': 'a team_name',
        'description': 'a description',
        'home_url': 'http://example.com/',
        'aux_data_url': 'http://example.com/'
    }
    print(
        f"creating new model. project={project}, model_config={model_config}")
    new_model = project.create_model(model_config)
    print(f"created new model: {new_model}")

    # show all models after delete/create
    project.refresh()
    print(f'\n* "after" models in {project}')
    for model in project.models:
        print(f'- {model}')
Beispiel #25
0
    def test_create_timezero(self):
        conn = mock_authenticate(ZoltarConnection('http://example.com'))
        with patch('zoltpy.connection.ZoltarConnection.json_for_uri',
                   return_value=PROJECTS_LIST_DICTS):
            project = conn.projects[0]

        # test valid arg combinations
        valid_args_tuples = [("2011-10-02", None, False, ''),
                             ("2011-10-02", "2011-10-03", False, ''),
                             ("2011-10-02", "2011-10-03", True,
                              "'tis the season")]
        for timezero_date, data_version_date, is_season_start, season_name in valid_args_tuples:
            with patch('requests.post') as post_mock:
                post_mock.return_value.status_code = 200
                post_mock.return_value.json = MagicMock(
                    return_value={
                        "url": "http://example.com/api/timezero/497/"
                    })
                try:
                    project.create_timezero(timezero_date, data_version_date,
                                            is_season_start, season_name)
                    post_mock.assert_called_once()
                except Exception as ex:
                    self.fail(f"unexpected exception: {ex}")

        # test valid POST args
        with patch('requests.post') as post_mock:
            post_mock.return_value.status_code = 200
            post_return_value = {
                "id": 705,
                "url": "http://example.com/api/timezero/705/",
                "timezero_date": "2011-10-02",
                "data_version_date": "2011-10-03",
                "is_season_start": True,
                "season_name": "2011-2012"
            }
            post_mock.return_value.json = MagicMock(
                return_value=post_return_value)
            try:
                project.create_timezero("2011-10-02", "2011-10-03", True,
                                        "2011-2012")
                post_mock.assert_called_once()
                exp_timezero_config = dict(post_return_value)  # copy
                del exp_timezero_config['id']
                del exp_timezero_config['url']
                act_timezero_config = post_mock.call_args[1]['json'][
                    'timezero_config']
                self.assertEqual(exp_timezero_config, act_timezero_config)
            except Exception as ex:
                self.fail(f"unexpected exception: {ex}")

        # test yes is_season_start but no season_name
        with self.assertRaises(RuntimeError) as context:
            project.create_timezero("2011-10-02", "2011-10-03", True)
        self.assertIn(
            'season_name not found but is required when is_season_start is passed',
            str(context.exception))

        # test no is_season_start but yes season_name
        with self.assertRaises(RuntimeError) as context:
            project.create_timezero("2011-10-02", False, "'tis the season")
        self.assertIn(
            'season_name not found but is required when is_season_start is passed',
            str(context.exception))
Beispiel #26
0
def zoltar_connection_app():
    """
    Application demonstrating use of the library at the ZoltarConnection level (rather than using the package's
    higher-level functions such as delete_forecast(), etc.)

    - App args: None
    - Required environment variables:
      - 'Z_HOST': Zoltar host to connect to. typically "https://www.zoltardata.com"
      - 'Z_USERNAME': username of the account that has permission to access the resources in above app args
      - 'Z_PASSWORD': password ""
    """
    host = os.environ.get('Z_HOST')
    username = os.environ.get('Z_USERNAME')
    password = os.environ.get('Z_PASSWORD')

    #
    # try out non-destructive functions
    #

    # work with a connection
    conn = ZoltarConnection(host)
    conn.authenticate(username, password)
    print('\n* projects')
    for project in conn.projects:
        print(f'- {project}, {project.id}, {project.name}')

    # work with a project
    project = [
        project for project in conn.projects
        if project.name == 'Docs Example Project'
    ][0]
    print(f'\n* working with {project}')
    print(f"- objects in {project}:\n"
          f"  = units: {project.units}\n"
          f"  = targets: {project.targets}\n"
          f"  = timezeros: {project.timezeros}\n"
          f"  = models: {project.models}")

    # get the project's truth detail
    print(f'\n* truth for {project}')
    print(
        f'- source, created_at: {project.truth_source}, {project.truth_created_at}'
    )

    # get the project's latest forecasts
    print(f'\n* latests forecasts for {project}')
    print(f'- source, created_at: {project.latest_forecasts}')

    # work with a model
    model = [
        model for model in project.models
        if model.name == 'docs forecast model'
    ][0]
    print(f'\n* working with {model}')
    print(f'- forecasts: {model.forecasts}')

    # work with a forecast
    forecast = model.forecasts[0]
    print(f'\n* working with {forecast}')

    forecast_data = forecast.data()
    print(f"- data: {len(forecast_data['predictions'])} predictions"
          )  # 26 predictions

    # work with a cdc csv file
    cdc_csv_file = "tests/EW01-2011-ReichLab_kde_US_National.csv"
    print(f'\n* working with a cdc csv file: {cdc_csv_file}')
    with open(cdc_csv_file) as fp:
        json_io_dict = json_io_dict_from_cdc_csv_file(2011, fp)
    print(
        f"- converted cdc data to json: {len(json_io_dict['predictions'])} predictions"
    )  # 154 predictions

    # work with a quantile csv file
    quantile_csv_file = "tests/quantile-predictions.csv"
    print(f'\n* working with a quantile csv file: {quantile_csv_file}')
    with open(quantile_csv_file) as fp:
        json_io_dict, error_messages = \
            json_io_dict_from_quantile_csv_file(fp, ['1 wk ahead cum death', '1 day ahead inc hosp'])
    print(
        f"- converted quantile data to json: {len(json_io_dict['predictions'])} predictions"
    )  # 5 predictions

    # convert to a Pandas DataFrame
    print(f'\n* working with a pandas data frame')
    dataframe = dataframe_from_json_io_dict(forecast_data)
    print(f'- dataframe: {dataframe}')

    # query forecast data
    print(f"\n* querying forecast data")
    query = {
        'targets': ['pct next week', 'cases next week'],
        'types': ['point']
    }
    job = project.submit_query(QueryType.FORECASTS, query)
    busy_poll_job(job)  # does refresh()
    rows = job.download_data()
    print(f"- got {len(rows)} forecast rows. as a dataframe:")
    print(dataframe_from_rows(rows))

    # query truth data
    print(f"\n* querying truth data")
    query = {'targets': ['pct next week', 'cases next week']}
    job = project.submit_query(QueryType.TRUTH, query)
    busy_poll_job(job)  # does refresh()
    rows = job.download_data()
    print(f"- got {len(rows)} truth rows. as a dataframe:")
    print(dataframe_from_rows(rows))

    #
    # try out destructive functions
    #

    # create a sandbox project to play with, deleting the existing one if any: docs-project.json
    project = [
        project for project in conn.projects if project.name == 'My project'
    ]
    project = project[0] if project else None
    if project:
        print(f"\n* deleting project {project}")
        project.delete()
        print("- deleted project")

    print(f"\n* creating project")
    project = create_project(
        conn, "examples/docs-project.json")  # "name": "My project"
    print(f"- created project: {project}")

    # upload truth
    print(f"\n* uploading truth")
    with open('tests/docs-ground-truth.csv') as csv_fp:
        job = project.upload_truth_data(csv_fp)
    busy_poll_job(job)
    print(f"- upload truth done")

    # create a model, upload a forecast, query the project, then delete it
    print(f"\n* creating model")
    with open("examples/example-model-config.json") as fp:
        model = project.create_model(json.load(fp))
    print(f"- created model: {model}")

    print(f"\n* uploading forecast. pre-upload forecasts: {model.forecasts}")
    with open("examples/docs-predictions.json") as fp:
        json_io_dict = json.load(fp)
        job = model.upload_forecast(json_io_dict, "docs-predictions.json",
                                    "2011-10-02", "some predictions")
    busy_poll_job(job)
    new_forecast = job.created_forecast()
    print(f"- uploaded forecast: {new_forecast}")

    model.refresh()
    print(f'\n* post-upload forecasts: {model.forecasts}')

    print(f"\n* deleting forecast: {new_forecast}")
    job = new_forecast.delete()
    busy_poll_job(job)
    print(f"- deleting forecast: done")

    # clean up by deleting the sandbox project. NB: This will delete all of the data associated with the project without
    # warning, including models and forecasts
    print(f"\n* deleting project {project}")
    project.delete()
    print("- deleted project")

    print("\n* app done!")
def connect2Zoltar():
    env_user = '******'
    env_pass = '******'
    conn = ZoltarConnection()
    conn.authenticate(os.environ.get(env_user), os.environ.get(env_pass))
    return conn