2020-10-13 11:18:07 +00:00
|
|
|
# Copyright The PyTorch Lightning team.
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
2020-07-09 11:15:41 +00:00
|
|
|
import os
|
2021-01-10 12:30:06 +00:00
|
|
|
from unittest.mock import DEFAULT, patch
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
2020-07-09 11:15:41 +00:00
|
|
|
from pytorch_lightning import Trainer
|
2020-03-03 01:49:14 +00:00
|
|
|
from pytorch_lightning.loggers import CometLogger
|
2020-03-31 12:57:48 +00:00
|
|
|
from pytorch_lightning.utilities.exceptions import MisconfigurationException
|
2021-02-09 10:10:52 +00:00
|
|
|
from tests.helpers import BoringModel
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
|
2020-10-05 03:23:58 +00:00
|
|
|
def _patch_comet_atexit(monkeypatch):
|
|
|
|
""" Prevent comet logger from trying to print at exit, since pytest's stdout/stderr redirection breaks it. """
|
|
|
|
import atexit
|
|
|
|
monkeypatch.setattr(atexit, "register", lambda _: None)
|
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_logger_online(comet):
|
2020-03-03 01:49:14 +00:00
|
|
|
"""Test comet online with mocks."""
|
|
|
|
# Test api_key given
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment') as comet_experiment:
|
2020-09-18 21:26:29 +00:00
|
|
|
logger = CometLogger(api_key='key', workspace='dummy-test', project_name='general')
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
_ = logger.experiment
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
comet_experiment.assert_called_once_with(api_key='key', workspace='dummy-test', project_name='general')
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
# Test both given
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment') as comet_experiment:
|
2020-09-18 21:26:29 +00:00
|
|
|
logger = CometLogger(save_dir='test', api_key='key', workspace='dummy-test', project_name='general')
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
_ = logger.experiment
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
comet_experiment.assert_called_once_with(api_key='key', workspace='dummy-test', project_name='general')
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
# Test already exists
|
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExistingExperiment') as comet_existing:
|
|
|
|
logger = CometLogger(
|
|
|
|
experiment_key='test',
|
|
|
|
experiment_name='experiment',
|
|
|
|
api_key='key',
|
|
|
|
workspace='dummy-test',
|
2020-09-18 21:26:29 +00:00
|
|
|
project_name='general',
|
2020-03-03 01:49:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
_ = logger.experiment
|
|
|
|
|
|
|
|
comet_existing.assert_called_once_with(
|
2020-09-18 21:26:29 +00:00
|
|
|
api_key='key', workspace='dummy-test', project_name='general', previous_experiment='test'
|
2020-03-03 01:49:14 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
comet_existing().set_name.assert_called_once_with('experiment')
|
|
|
|
|
|
|
|
with patch('pytorch_lightning.loggers.comet.API') as api:
|
2020-09-18 21:26:29 +00:00
|
|
|
CometLogger(api_key='key', workspace='dummy-test', project_name='general', rest_api_key='rest')
|
2020-03-03 01:49:14 +00:00
|
|
|
|
|
|
|
api.assert_called_once_with('rest')
|
2020-07-09 11:15:41 +00:00
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_logger_no_api_key_given(comet):
|
|
|
|
""" Test that CometLogger fails to initialize if both api key and save_dir are missing. """
|
2021-02-02 17:06:11 +00:00
|
|
|
with pytest.raises(MisconfigurationException, match='requires either api_key or save_dir'):
|
2020-10-06 03:00:54 +00:00
|
|
|
comet.config.get_api_key.return_value = None
|
|
|
|
CometLogger(workspace='dummy-test', project_name='general')
|
|
|
|
|
|
|
|
|
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_logger_experiment_name(comet):
|
2020-09-18 21:26:29 +00:00
|
|
|
"""Test that Comet Logger experiment name works correctly."""
|
|
|
|
|
|
|
|
api_key = "key"
|
|
|
|
experiment_name = "My Name"
|
|
|
|
|
|
|
|
# Test api_key given
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment') as comet_experiment:
|
2021-02-06 11:07:26 +00:00
|
|
|
logger = CometLogger(
|
|
|
|
api_key=api_key,
|
|
|
|
experiment_name=experiment_name,
|
|
|
|
)
|
2020-09-18 21:26:29 +00:00
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
_ = logger.experiment
|
2020-10-06 03:00:54 +00:00
|
|
|
comet_experiment.assert_called_once_with(api_key=api_key, project_name=None)
|
|
|
|
comet_experiment().set_name.assert_called_once_with(experiment_name)
|
2020-09-18 21:26:29 +00:00
|
|
|
|
|
|
|
|
2020-10-27 14:30:56 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_logger_manual_experiment_key(comet):
|
|
|
|
"""Test that Comet Logger respects manually set COMET_EXPERIMENT_KEY."""
|
|
|
|
|
|
|
|
api_key = "key"
|
|
|
|
experiment_key = "96346da91469407a85641afe5766b554"
|
|
|
|
|
|
|
|
instantation_environ = {}
|
|
|
|
|
|
|
|
def save_os_environ(*args, **kwargs):
|
|
|
|
nonlocal instantation_environ
|
|
|
|
instantation_environ = os.environ.copy()
|
|
|
|
|
|
|
|
return DEFAULT
|
|
|
|
|
|
|
|
# Test api_key given
|
|
|
|
with patch.dict(os.environ, {"COMET_EXPERIMENT_KEY": experiment_key}):
|
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment', side_effect=save_os_environ) as comet_experiment:
|
|
|
|
logger = CometLogger(api_key=api_key)
|
|
|
|
assert logger.version == experiment_key
|
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
_ = logger.experiment
|
|
|
|
comet_experiment.assert_called_once_with(api_key=api_key, project_name=None)
|
|
|
|
|
|
|
|
assert instantation_environ["COMET_EXPERIMENT_KEY"] == experiment_key
|
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.CometOfflineExperiment')
|
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_logger_dirs_creation(comet, comet_experiment, tmpdir, monkeypatch):
|
2020-07-09 11:15:41 +00:00
|
|
|
""" Test that the logger creates the folders and files in the right place. """
|
2020-10-05 03:23:58 +00:00
|
|
|
_patch_comet_atexit(monkeypatch)
|
2020-07-09 11:15:41 +00:00
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
comet.config.get_api_key.return_value = None
|
|
|
|
comet.generate_guid.return_value = "4321"
|
|
|
|
|
2020-07-09 11:15:41 +00:00
|
|
|
logger = CometLogger(project_name='test', save_dir=tmpdir)
|
|
|
|
assert not os.listdir(tmpdir)
|
|
|
|
assert logger.mode == 'offline'
|
|
|
|
assert logger.save_dir == tmpdir
|
2020-10-06 03:00:54 +00:00
|
|
|
assert logger.name == 'test'
|
|
|
|
assert logger.version == "4321"
|
2020-07-09 11:15:41 +00:00
|
|
|
|
|
|
|
_ = logger.experiment
|
2020-10-06 03:00:54 +00:00
|
|
|
|
|
|
|
comet_experiment.assert_called_once_with(offline_directory=tmpdir, project_name='test')
|
|
|
|
|
|
|
|
# mock return values of experiment
|
|
|
|
logger.experiment.id = '1'
|
|
|
|
logger.experiment.project_name = 'test'
|
2020-07-09 11:15:41 +00:00
|
|
|
|
2021-02-05 10:32:31 +00:00
|
|
|
model = BoringModel()
|
|
|
|
trainer = Trainer(default_root_dir=tmpdir, logger=logger, max_epochs=1, limit_train_batches=3, limit_val_batches=3)
|
2021-02-02 17:06:11 +00:00
|
|
|
assert trainer.log_dir == logger.save_dir
|
2020-07-09 11:15:41 +00:00
|
|
|
trainer.fit(model)
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
assert trainer.checkpoint_callback.dirpath == (tmpdir / 'test' / "1" / 'checkpoints')
|
2021-02-05 10:32:31 +00:00
|
|
|
assert set(os.listdir(trainer.checkpoint_callback.dirpath)) == {'epoch=0-step=2.ckpt'}
|
2021-02-02 17:06:11 +00:00
|
|
|
assert trainer.log_dir == logger.save_dir
|
2020-09-15 12:30:42 +00:00
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_name_default(comet):
|
2020-09-18 21:26:29 +00:00
|
|
|
""" Test that CometLogger.name don't create an Experiment and returns a default value. """
|
|
|
|
|
|
|
|
api_key = "key"
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment'):
|
2020-09-18 21:26:29 +00:00
|
|
|
logger = CometLogger(api_key=api_key)
|
|
|
|
assert logger._experiment is None
|
|
|
|
assert logger.name == "comet-default"
|
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_name_project_name(comet):
|
2020-09-18 21:26:29 +00:00
|
|
|
""" Test that CometLogger.name does not create an Experiment and returns project name if passed. """
|
|
|
|
|
|
|
|
api_key = "key"
|
|
|
|
project_name = "My Project Name"
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment'):
|
2020-09-18 21:26:29 +00:00
|
|
|
logger = CometLogger(api_key=api_key, project_name=project_name)
|
|
|
|
assert logger._experiment is None
|
|
|
|
assert logger.name == project_name
|
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_version_without_experiment(comet):
|
2020-09-18 21:26:29 +00:00
|
|
|
""" Test that CometLogger.version does not create an Experiment. """
|
|
|
|
|
|
|
|
api_key = "key"
|
|
|
|
experiment_name = "My Name"
|
2020-10-06 03:00:54 +00:00
|
|
|
comet.generate_guid.return_value = "1234"
|
2020-09-18 21:26:29 +00:00
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
with patch('pytorch_lightning.loggers.comet.CometExperiment'):
|
2020-09-18 21:26:29 +00:00
|
|
|
logger = CometLogger(api_key=api_key, experiment_name=experiment_name)
|
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
first_version = logger.version
|
|
|
|
assert first_version is not None
|
|
|
|
assert logger.version == first_version
|
|
|
|
assert logger._experiment is None
|
|
|
|
|
|
|
|
_ = logger.experiment
|
|
|
|
|
|
|
|
logger.reset_experiment()
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
second_version = logger.version == "1234"
|
2020-09-18 21:26:29 +00:00
|
|
|
assert second_version is not None
|
|
|
|
assert second_version != first_version
|
|
|
|
|
|
|
|
|
2020-10-06 03:00:54 +00:00
|
|
|
@patch("pytorch_lightning.loggers.comet.CometExperiment")
|
|
|
|
@patch('pytorch_lightning.loggers.comet.comet_ml')
|
|
|
|
def test_comet_epoch_logging(comet, comet_experiment, tmpdir, monkeypatch):
|
2020-09-15 12:30:42 +00:00
|
|
|
""" Test that CometLogger removes the epoch key from the metrics dict and passes it as argument. """
|
2020-10-05 03:23:58 +00:00
|
|
|
_patch_comet_atexit(monkeypatch)
|
2020-10-06 03:00:54 +00:00
|
|
|
logger = CometLogger(project_name="test", save_dir=tmpdir)
|
|
|
|
logger.log_metrics({"test": 1, "epoch": 1}, step=123)
|
|
|
|
logger.experiment.log_metrics.assert_called_once_with({"test": 1}, epoch=1, step=123)
|