Repository: Lightning-AI/pytorch-lightning
File: pytorch_lightning/callbacks/model_checkpoint.py (Python)

Code before:
        monitor_candidates: Dict[str, Any],
        epoch: int,
        step: int,
        del_filepath: Optional[str] = None
    ) -> str:
        filepath = self.format_checkpoint_name(epoch, step, monitor_candidates)
        version = self.STARTING_VERSION
        while self._fs.exists(filepath) and filepath != del_filepath:
            filepath = self.format_checkpoint_name(epoch, step, monitor_candidates, ver=version)
            version += 1
        return filepath

    def _monitor_candidates(self, trainer):
        monitor_candidates = deepcopy(trainer.logger_connector.callback_metrics)
        monitor_candidates.update(step=trainer.global_step, epoch=trainer.current_epoch)
        return monitor_candidates

    def _save_last_checkpoint(self, trainer, pl_module, monitor_candidates):
        should_save_last = self.monitor is None or self.save_last
        if not should_save_last:
            return

        # when user ALSO asked for the 'last.ckpt' change the name
        if self.save_last:
            last_filepath = self._format_checkpoint_name(
                self.CHECKPOINT_NAME_LAST,
                trainer.current_epoch,
                trainer.global_step,
                monitor_candidates,
                prefix=self.prefix,
            )
            last_filepath = os.path.join(self.dirpath, f"{last_filepath}{self.FILE_EXTENSION}")
        else:
            last_filepath = self._get_metric_interpolated_filepath_name(
                monitor_candidates, trainer.current_epoch, trainer.global_step
            )

        accelerator_backend = trainer.accelerator_backend

        if accelerator_backend is not None and accelerator_backend.rpc_enabled:
            # RPCPlugin manages saving all model states
            accelerator_backend.ddp_plugin.rpc_save_model(self._save_model, last_filepath, trainer, pl_module)
        else:
            self._save_model(last_filepath, trainer, pl_module)
        if (
            self.last_model_path
            and self.last_model_path != last_filepath
            and (self.save_top_k != -1 or self.save_last)
            and trainer.is_global_zero
        ):
            self._del_model(self.last_model_path)

Review comment (suggestion):
```suggestion
        monitor_candidates = deepcopy(trainer.callback_metrics)
```
trainer.callback_metrics is a property

Code after:

        # validate metric
        if self.monitor is not None and not self._is_valid_monitor_key(metrics):
            m = (
                f"ModelCheckpoint(monitor='{self.monitor}') not found in the returned metrics:"
                f" {list(metrics.keys())}. "
                f"HINT: Did you call self.log('{self.monitor}', tensor) in the LightningModule?"
            )
            raise MisconfigurationException(m)

    def _get_metric_interpolated_filepath_name(
        self,
        monitor_candidates: Dict[str, Any],
        epoch: int,
        step: int,
        del_filepath: Optional[str] = None
    ) -> str:
        filepath = self.format_checkpoint_name(epoch, step, monitor_candidates)
        version = self.STARTING_VERSION
        while self._fs.exists(filepath) and filepath != del_filepath:
            filepath = self.format_checkpoint_name(epoch, step, monitor_candidates, ver=version)
            version += 1
        return filepath

    def _monitor_candidates(self, trainer):
        monitor_candidates = deepcopy(trainer.logger_connector.callback_metrics)
        monitor_candidates.update(step=trainer.global_step, epoch=trainer.current_epoch)
        return monitor_candidates

    def _save_last_checkpoint(self, trainer, pl_module, monitor_candidates):
        should_save_last = self.monitor is None or self.save_last
        if not should_save_last:
            return

        # when user ALSO asked for the 'last.ckpt' change the name
        if self.save_last:
            last_filepath = self._format_checkpoint_name(
                self.CHECKPOINT_NAME_LAST,
                trainer.current_epoch,
                trainer.global_step,
                monitor_candidates,
                prefix=self.prefix,
            )
            last_filepath = os.path.join(self.dirpath, f"{last_filepath}{self.FILE_EXTENSION}")
        else:
            last_filepath = self._get_metric_interpolated_filepath_name(
                monitor_candidates, trainer.current_epoch, trainer.global_step
            )

        accelerator_backend = trainer.accelerator_backend