Ejemplo n.º 1
0
def _list_experiments():
    request_message = _get_request_message(ListExperiments())
    experiment_entities = _get_tracking_store().list_experiments(request_message.view_type)
    response_message = ListExperiments.Response()
    response_message.experiments.extend([e.to_proto() for e in experiment_entities])
    response = Response(mimetype='application/json')
    response.set_data(message_to_json(response_message))
    return response
Ejemplo n.º 2
0
def _list_experiments():
    request_message = _get_request_message(ListExperiments())
    # `ListFields` returns a list of (FieldDescriptor, value) tuples for *present* fields:
    # https://googleapis.dev/python/protobuf/latest/google/protobuf/message.html
    # #google.protobuf.message.Message.ListFields
    params = {field.name: val for field, val in request_message.ListFields()}
    experiment_entities = _get_tracking_store().list_experiments(**params)
    response_message = ListExperiments.Response()
    response_message.experiments.extend([e.to_proto() for e in experiment_entities])
    if experiment_entities.token:
        response_message.next_page_token = experiment_entities.token
    response = Response(mimetype="application/json")
    response.set_data(message_to_json(response_message))
    return response
Ejemplo n.º 3
0
 def list_experiments(
     self,
     view_type=ViewType.ACTIVE_ONLY,
     max_results=None,
     page_token=None,
 ):
     """
     :param view_type: Qualify requested type of experiments.
     :param max_results: If passed, specifies the maximum number of experiments desired. If not
                         passed, the server will pick a maximum number of results to return.
     :param page_token: Token specifying the next page of results. It should be obtained from
                         a ``list_experiments`` call.
     :return: A :py:class:`PagedList <mlflow.store.entities.PagedList>` of
              :py:class:`Experiment <mlflow.entities.Experiment>` objects. The pagination token
              for the next page can be obtained via the ``token`` attribute of the object.
     """
     req_body = message_to_json(
         ListExperiments(view_type=view_type,
                         max_results=max_results,
                         page_token=page_token))
     response_proto = self._call_endpoint(ListExperiments, req_body)
     experiments = [
         Experiment.from_proto(x) for x in response_proto.experiments
     ]
     # If the response doesn't contain `next_page_token`, `response_proto.next_page_token`
     # returns an empty string (default value for a string proto field).
     token = (response_proto.next_page_token
              if response_proto.HasField("next_page_token") else None)
     return PagedList(experiments, token)
Ejemplo n.º 4
0
 def list_experiments(self, view_type=ViewType.ACTIVE_ONLY):
     """
     :return: a list of all known Experiment objects
     """
     req_body = message_to_json(ListExperiments(view_type=view_type))
     response_proto = self._call_endpoint(ListExperiments, req_body)
     return [Experiment.from_proto(experiment_proto)
             for experiment_proto in response_proto.experiments]
Ejemplo n.º 5
0
def _list_experiments():
    response_message = ListExperiments.Response()
    experiment_entities = _get_store().list_experiments()
    response_message.experiments.extend(
        [e.to_proto() for e in experiment_entities])
    response = Response(mimetype='application/json')
    response.set_data(
        MessageToJson(response_message, preserving_proto_field_name=True))
    return response
Ejemplo n.º 6
0
    def test_get_experiment_by_name(self, store_class):
        creds = MlflowHostCreds('https://hello')
        store = store_class(lambda: creds)
        with mock.patch('mlflow.store.rest_store.http_request') as mock_http:
            response = mock.MagicMock
            response.status_code = 200
            experiment = Experiment(
                experiment_id="123", name="abc", artifact_location="/abc",
                lifecycle_stage=LifecycleStage.ACTIVE)
            response.text = json.dumps({
                "experiment": json.loads(message_to_json(experiment.to_proto()))})
            mock_http.return_value = response
            result = store.get_experiment_by_name("abc")
            expected_message0 = GetExperimentByName(experiment_name="abc")
            self._verify_requests(mock_http, creds,
                                  "experiments/get-by-name", "GET",
                                  message_to_json(expected_message0))
            assert result.experiment_id == experiment.experiment_id
            assert result.name == experiment.name
            assert result.artifact_location == experiment.artifact_location
            assert result.lifecycle_stage == experiment.lifecycle_stage
            # Test GetExperimentByName against nonexistent experiment
            mock_http.reset_mock()
            nonexistent_exp_response = mock.MagicMock
            nonexistent_exp_response.status_code = 404
            nonexistent_exp_response.text =\
                MlflowException("Exp doesn't exist!", RESOURCE_DOES_NOT_EXIST).serialize_as_json()
            mock_http.return_value = nonexistent_exp_response
            assert store.get_experiment_by_name("nonexistent-experiment") is None
            expected_message1 = GetExperimentByName(experiment_name="nonexistent-experiment")
            self._verify_requests(mock_http, creds,
                                  "experiments/get-by-name", "GET",
                                  message_to_json(expected_message1))
            assert mock_http.call_count == 1

            # Test REST client behavior against a mocked old server, which has handler for
            # ListExperiments but not GetExperimentByName
            mock_http.reset_mock()
            list_exp_response = mock.MagicMock
            list_exp_response.text = json.dumps({
                "experiments": [json.loads(message_to_json(experiment.to_proto()))]})
            list_exp_response.status_code = 200

            def response_fn(*args, **kwargs):
                # pylint: disable=unused-argument
                if kwargs.get('endpoint') == "/api/2.0/mlflow/experiments/get-by-name":
                    raise MlflowException("GetExperimentByName is not implemented",
                                          ENDPOINT_NOT_FOUND)
                else:
                    return list_exp_response

            mock_http.side_effect = response_fn
            result = store.get_experiment_by_name("abc")
            expected_message2 = ListExperiments(view_type=ViewType.ALL)
            self._verify_requests(mock_http, creds,
                                  "experiments/get-by-name", "GET",
                                  message_to_json(expected_message0))
            self._verify_requests(mock_http, creds,
                                  "experiments/list", "GET",
                                  message_to_json(expected_message2))
            assert result.experiment_id == experiment.experiment_id
            assert result.name == experiment.name
            assert result.artifact_location == experiment.artifact_location
            assert result.lifecycle_stage == experiment.lifecycle_stage

            # Verify that REST client won't fall back to ListExperiments for 429 errors (hitting
            # rate limits)
            mock_http.reset_mock()

            def rate_limit_response_fn(*args, **kwargs):
                # pylint: disable=unused-argument
                raise MlflowException("Hit rate limit on GetExperimentByName",
                                      REQUEST_LIMIT_EXCEEDED)

            mock_http.side_effect = rate_limit_response_fn
            with pytest.raises(MlflowException) as exc_info:
                store.get_experiment_by_name("imspamming")
            assert exc_info.value.error_code == ErrorCode.Name(REQUEST_LIMIT_EXCEEDED)
            assert mock_http.call_count == 1