From 8a236f44ab2dc1fbf6599271612ba7012128de1a Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 12 Sep 2023 15:17:46 +0100 Subject: [PATCH 001/136] Added the `tasks` sub-package --- minerva/tasks/__init__.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 minerva/tasks/__init__.py diff --git a/minerva/tasks/__init__.py b/minerva/tasks/__init__.py new file mode 100644 index 000000000..b5b9af18c --- /dev/null +++ b/minerva/tasks/__init__.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +""":mod:`tasks` is a repositry of downstream tasks for evaluating models in :mod:`minerva` with a generic IO.""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" From 189f52dbd88fd7c7c215e8bbeffa590e1e5b8c89 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 12 Sep 2023 16:46:04 +0100 Subject: [PATCH 002/136] NEW: `MinervaTask` --- minerva/tasks/core.py | 148 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 minerva/tasks/core.py diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py new file mode 100644 index 000000000..e4c182a6b --- /dev/null +++ b/minerva/tasks/core.py @@ -0,0 +1,148 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +"""""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +import abc +from abc import ABC +from typing import ( + Any, + Callable, + Dict, + Iterable, + Optional, + Sequence, + Tuple, + Union, + overload, +) + +import torch.distributed as dist + +from minerva.logger import MinervaLogger +from minerva.metrics import MinervaMetrics +from minerva.utils.utils import func_by_str + + +# ===================================================================================================================== +# CLASSES +# ===================================================================================================================== +class MinervaTask(ABC): + def __init__( + self, + model, + batch_size: int, + n_batches: int, + model_type: str, + sample_pairs: bool, + **params, + ) -> None: + self.model = model + self.params = params + + # Corrects the batch size if this is a distributed job to account for batches being split across devices. + if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + self.batch_size = batch_size // dist.get_world_size() # type: ignore[attr-defined] + + self.n_batches = n_batches + self.model_type = model_type + self.sample_pairs = sample_pairs + + self.metric_logger: MinervaMetrics = self.make_metric_logger() + self.logger: MinervaLogger = self.get_logger() + self.modelio = self.get_io_func() + + def make_metric_logger(self) -> MinervaMetrics: + """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. + + Returns: + MinervaMetrics: Constructed metric logger. + """ + + # Gets the size of the input data to the network (without batch dimension). + data_size = self.params["input_size"] + + # Gets constructor of the metric logger from name in the config. + _metric_logger: Callable[..., Any] = func_by_str( + "minerva.metrics", self.params["metrics"] + ) + + # Initialises the metric logger with arguments. + metric_logger: MinervaMetrics = _metric_logger( + self.n_batches, + batch_size=self.batch_size, + data_size=data_size, + model_type=self.model_type, + sample_pairs=self.sample_pairs, + ) + + return metric_logger + + def get_logger(self) -> Callable[..., Any]: + """Creates an object to log the results from each step of model fitting during an epoch. + + Returns: + ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logger.MinervaLogger` + to be intialised within the epoch. + """ + logger: Callable[..., Any] = func_by_str( + "minerva.logger", self.params["logger"] + ) + return logger + + def get_io_func(self) -> Callable[..., Any]: + """Fetches a func to handle IO for the type of model used in the experiment. + + Returns: + ~typing.Callable[..., ~typing.Any]: Model IO function requested from parameters. + """ + io_func: Callable[..., Any] = func_by_str( + "minerva.modelio", self.params["model_io"] + ) + return io_func + + @abc.abstractmethod + def step(self) -> None: + pass + + def __call__(self) -> Any: + return self.step() + + @property + def get_logs(self) -> Dict[str, Any]: + return self.logger.get_logs + + def __repr__(self) -> str: + return self.__class__.__name__ From 987fe8348a3ff8d5bfb6b611263fd39214847884 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 12 Sep 2023 16:46:22 +0100 Subject: [PATCH 003/136] Added module for KNN --- minerva/tasks/knn.py | 244 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 minerva/tasks/knn.py diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py new file mode 100644 index 000000000..a1bef2a86 --- /dev/null +++ b/minerva/tasks/knn.py @@ -0,0 +1,244 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +"""""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +from typing import TYPE_CHECKING, Any, Dict, Optional + +import pandas as pd +import torch +import torch.distributed as dist +import torch.nn.functional as ptfunc +from alive_progress import alive_it +from torch import Tensor +from torch.nn.parallel import DistributedDataParallel as DDP + +if TYPE_CHECKING: # pragma: no cover + from torch.utils.tensorboard.writer import SummaryWriter + +from torchinfo import summary +from wandb.sdk.lib import RunDisabled +from wandb.sdk.wandb_run import Run + +from minerva.datasets import make_loaders +from minerva.logger import KNNLogger, MinervaLogger +from minerva.metrics import MinervaMetrics +from minerva.models import MinervaDataParallel, MinervaSiamese +from minerva.utils import AUX_CONFIGS, utils + +from .core import MinervaTask + + +# ===================================================================================================================== +# CLASSES +# ===================================================================================================================== +class WeightedKNN(MinervaTask): + def step( + self, + temp: float = 0.5, + k: int = 200, + mode: str = "val", + record_int: bool = True, + record_float: bool = False, + ) -> Optional[Dict[str, Any]]: + """Trains a KNN using the model to validate a SSL model. + + Adapted from https://github.com/yaohungt/Barlow-Twins-HSIC for use in :mod:`minerva`. + + Args: + temp (float, optional): Temperature of the similarity loss. Defaults to 0.5. + k (int, optional): Number of similar images to use to predict images. Defaults to 200. + mode (str, optional): Mode of model fitting this has been called on. Defaults to "val". + record_int (bool, optional): Whether to record integer values. Defaults to True. + record_float (bool, optional): Whether to record floating point values. Warning! + This may result in memory issues on large amounts of data! Defaults to False. + + Returns: + dict[str, ~typing.Any] | None: Results dictionary from the epoch logger if ``record_int`` + or ``record_float`` are ``True``. + """ + + # Puts the model in evaluation mode so no back passes are made. + self.model.eval() + + # Get the number of classes from the data config. + n_classes = len(AUX_CONFIGS["data_config"]["classes"]) + + batch_size = self.batch_size + + # Calculates the number of samples. + n_samples = self.n_batches[mode] * batch_size + + # Uses the special `KNNLogger` to log the results from the KNN. + epoch_logger = KNNLogger( + self.n_batches[mode], + batch_size, + n_samples, + record_int=record_int, + record_float=record_float, + writer=self.writer, + ) + + total_num = 0 + feature_list = [] + target_list = [] + + with torch.no_grad(): + # Generate feature bank and target bank. + feat_bar = alive_it(self.loaders["val"]) + for batch in feat_bar: + val_data: Tensor = batch["image"].to(self.device, non_blocking=True) + val_target: Tensor = batch["mask"].to(self.device, non_blocking=True) + target_list.append( + torch.mode(torch.flatten(val_target, start_dim=1)).values + ) + + # Get features from passing the input data through the model. + if utils.check_substrings_in_string(self.model_type, "siamese"): + # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. + if isinstance(self.model, MinervaDataParallel): # pragma: no cover + assert isinstance(self.model.model.module, MinervaSiamese) + else: + assert isinstance(self.model, MinervaSiamese) + + # Ensures that the data is parsed through a single head of the model rather than paired. + feature, _ = self.model.forward_single(val_data) # type: ignore[operator] + else: + feature, _ = self.model(val_data) + + # The masks from segmentation models will need to be flattened. + if utils.check_substrings_in_string(self.model_type, "segmentation"): + feature = feature.flatten(1, -1) + + feature_list.append(feature) + + # [D, N] + feature_bank = torch.cat(feature_list, dim=0).t().contiguous() + + # [N] + feature_labels = ( + torch.cat(target_list, dim=0).contiguous().to(feature_bank.device) + ) + + # Loop test data to predict the label by weighted KNN search. + test_bar = alive_it(self.loaders["test"]) + for batch in test_bar: + test_data: Tensor = batch["image"].to(self.device, non_blocking=True) + test_target: Tensor = torch.mode( + torch.flatten( + batch["mask"].to(self.device, non_blocking=True), start_dim=1 + ) + ).values + + # Get features from passing the input data through the model. + if utils.check_substrings_in_string(self.model_type, "siamese"): + # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. + if isinstance(self.model, MinervaDataParallel): # pragma: no cover + assert isinstance(self.model.model.module, MinervaSiamese) + else: + assert isinstance(self.model, MinervaSiamese) + + # Ensures that the data is parsed through a single head of the model rather than paired. + feature, _ = self.model.forward_single(test_data) # type: ignore[operator] + else: + feature, _ = self.model(test_data) + + # The masks from segmentation models will need to be flattened. + if utils.check_substrings_in_string(self.model_type, "segmentation"): + feature = feature.flatten(1, -1) + + total_num += batch_size + + # compute cos similarity between each feature vector and feature bank ---> [B, N] + sim_matrix = torch.mm(feature, feature_bank) + + # [B, K] + sim_weight, sim_indices = sim_matrix.topk(k=k, dim=-1) + + # [B, K] + sim_labels = torch.gather( + feature_labels.expand(test_data.size(0), -1), + dim=-1, + index=sim_indices, + ) + + sim_weight = (sim_weight / temp).exp() + + # Counts for each class + one_hot_label = torch.zeros( + test_data.size(0) * k, n_classes, device=sim_labels.device + ) + + # [B*K, C] + one_hot_label = one_hot_label.scatter( + dim=-1, index=sim_labels.view(-1, 1), value=1.0 + ) + + # Weighted score ---> [B, C] + pred_scores = torch.sum( + one_hot_label.view(test_data.size(0), -1, n_classes) + * sim_weight.unsqueeze(dim=-1), + dim=1, + ) + pred_scores = ptfunc.normalize( + pred_scores.nan_to_num(nan=0.0, posinf=1.0, neginf=0.0), + ) + + # Calculate loss between predicted and ground truth labels by KNN. + criterion = torch.nn.CrossEntropyLoss() + loss = criterion(pred_scores, test_target) + + # Pack results together for the logger. + results = (loss, pred_scores, test_target, _) + + # Gathers the losses across devices together if a distributed job. + if dist.is_available() and dist.is_initialized(): # pragma: no cover + loss = results[0].data.clone() + dist.all_reduce(loss.div_(dist.get_world_size())) + results = (loss, *results[1:]) + + # Sends results to logger. + epoch_logger.log(mode, self.step_num[mode], *results) + + # Update global step number for this mode of model fitting. + self.step_num[mode] += 1 + + # Send the logs to the metric logger. + self.metric_logger(mode, epoch_logger.get_logs) + + if record_int or record_float: + return epoch_logger.get_results + else: + return None From 8059f284a2f77ab4d2fd04b62732d6a25a01b8ba Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 13 Sep 2023 17:21:55 +0100 Subject: [PATCH 004/136] Added more attributes to `MinervaTask` --- minerva/tasks/core.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index e4c182a6b..3407a3451 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -49,10 +49,13 @@ overload, ) +import torch import torch.distributed as dist +from torch.utils.data import DataLoader from minerva.logger import MinervaLogger from minerva.metrics import MinervaMetrics +from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils.utils import func_by_str @@ -62,11 +65,15 @@ class MinervaTask(ABC): def __init__( self, - model, + model: Union[MinervaModel, MinervaDataParallel], batch_size: int, n_batches: int, model_type: str, sample_pairs: bool, + loader: DataLoader, + device: torch.device, + record_int: bool, + record_float: bool, **params, ) -> None: self.model = model @@ -84,6 +91,14 @@ def __init__( self.logger: MinervaLogger = self.get_logger() self.modelio = self.get_io_func() + self.loader = loader + self.device = device + + self.record_int = record_int + self.record_float = record_float + + self.step_num = 0 + def make_metric_logger(self) -> MinervaMetrics: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. @@ -134,11 +149,22 @@ def get_io_func(self) -> Callable[..., Any]: return io_func @abc.abstractmethod - def step(self) -> None: + def step(self) -> Dict[str, Any]: pass + def _generic_step(self) -> Optional[Dict[str, Any]]: + self.step() + + # Send the logs to the metric logger. + self.metric_logger(mode, self.logger.get_logs) + + if self.record_int or self.record_float: + return self.logger.get_results + else: + return None + def __call__(self) -> Any: - return self.step() + return self._generic_step() @property def get_logs(self) -> Dict[str, Any]: From 4cfafdd1bdca611b4c1ac15575e360fbbe8d0c4b Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 13 Sep 2023 17:23:05 +0100 Subject: [PATCH 005/136] Added `__init__` --- minerva/tasks/knn.py | 61 ++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index a1bef2a86..588924623 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -35,27 +35,19 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -from typing import TYPE_CHECKING, Any, Dict, Optional +from typing import Any, Dict, Optional -import pandas as pd import torch import torch.distributed as dist import torch.nn.functional as ptfunc from alive_progress import alive_it from torch import Tensor -from torch.nn.parallel import DistributedDataParallel as DDP - -if TYPE_CHECKING: # pragma: no cover - from torch.utils.tensorboard.writer import SummaryWriter - -from torchinfo import summary -from wandb.sdk.lib import RunDisabled -from wandb.sdk.wandb_run import Run +from torch.utils.data import DataLoader from minerva.datasets import make_loaders from minerva.logger import KNNLogger, MinervaLogger from minerva.metrics import MinervaMetrics -from minerva.models import MinervaDataParallel, MinervaSiamese +from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese from minerva.utils import AUX_CONFIGS, utils from .core import MinervaTask @@ -65,6 +57,31 @@ # CLASSES # ===================================================================================================================== class WeightedKNN(MinervaTask): + def __init__( + self, + model: MinervaModel, + batch_size: int, + n_batches: int, + model_type: str, + sample_pairs: bool, + loader: DataLoader, + device: torch.device, + **params, + ) -> None: + super().__init__( + model, + batch_size, + n_batches, + model_type, + sample_pairs, + loader, + device, + **params, + ) + + self.temp = self.params["temp"] + self.k = self.params["k"] + def step( self, temp: float = 0.5, @@ -96,15 +113,13 @@ def step( # Get the number of classes from the data config. n_classes = len(AUX_CONFIGS["data_config"]["classes"]) - batch_size = self.batch_size - # Calculates the number of samples. - n_samples = self.n_batches[mode] * batch_size + n_samples = self.n_batches * self.batch_size # Uses the special `KNNLogger` to log the results from the KNN. epoch_logger = KNNLogger( - self.n_batches[mode], - batch_size, + self.n_batches, + self.batch_size, n_samples, record_int=record_int, record_float=record_float, @@ -179,7 +194,7 @@ def step( if utils.check_substrings_in_string(self.model_type, "segmentation"): feature = feature.flatten(1, -1) - total_num += batch_size + total_num += self.batch_size # compute cos similarity between each feature vector and feature bank ---> [B, N] sim_matrix = torch.mm(feature, feature_bank) @@ -230,15 +245,7 @@ def step( results = (loss, *results[1:]) # Sends results to logger. - epoch_logger.log(mode, self.step_num[mode], *results) + epoch_logger.log(mode, self.step_num, *results) # Update global step number for this mode of model fitting. - self.step_num[mode] += 1 - - # Send the logs to the metric logger. - self.metric_logger(mode, epoch_logger.get_logs) - - if record_int or record_float: - return epoch_logger.get_results - else: - return None + self.step_num += 1 From 4ca13b589ef28f3654d45533e1bd6b537a9501da Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Fri, 15 Sep 2023 13:31:05 +0100 Subject: [PATCH 006/136] `step` now requires `mode` input --- minerva/tasks/core.py | 38 +++++++++++++++++--------------------- minerva/tasks/knn.py | 35 +++++++++++++++++------------------ 2 files changed, 34 insertions(+), 39 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 3407a3451..8b1dc8ca5 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -37,21 +37,15 @@ # ===================================================================================================================== import abc from abc import ABC -from typing import ( - Any, - Callable, - Dict, - Iterable, - Optional, - Sequence, - Tuple, - Union, - overload, -) +from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, Optional, Union + +if TYPE_CHECKING: # pragma: no cover + from torch.utils.tensorboard.writer import SummaryWriter import torch import torch.distributed as dist from torch.utils.data import DataLoader +from wandb.sdk.wandb_run import Run from minerva.logger import MinervaLogger from minerva.metrics import MinervaMetrics @@ -69,11 +63,11 @@ def __init__( batch_size: int, n_batches: int, model_type: str, - sample_pairs: bool, - loader: DataLoader, + loader: DataLoader[Iterable[Any]], device: torch.device, - record_int: bool, - record_float: bool, + writer: Optional[Union[SummaryWriter, Run]] = None, + record_int: bool = True, + record_float: bool = False, **params, ) -> None: self.model = model @@ -85,7 +79,7 @@ def __init__( self.n_batches = n_batches self.model_type = model_type - self.sample_pairs = sample_pairs + self.sample_pairs = self.params.get("sample_pairs", False) self.metric_logger: MinervaMetrics = self.make_metric_logger() self.logger: MinervaLogger = self.get_logger() @@ -97,6 +91,8 @@ def __init__( self.record_int = record_int self.record_float = record_float + self.writer = writer + self.step_num = 0 def make_metric_logger(self) -> MinervaMetrics: @@ -149,11 +145,11 @@ def get_io_func(self) -> Callable[..., Any]: return io_func @abc.abstractmethod - def step(self) -> Dict[str, Any]: + def step(self, mode: str) -> None: pass - def _generic_step(self) -> Optional[Dict[str, Any]]: - self.step() + def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: + self.step(mode) # Send the logs to the metric logger. self.metric_logger(mode, self.logger.get_logs) @@ -163,8 +159,8 @@ def _generic_step(self) -> Optional[Dict[str, Any]]: else: return None - def __call__(self) -> Any: - return self._generic_step() + def __call__(self, mode: str) -> Any: + return self._generic_step(mode) @property def get_logs(self) -> Dict[str, Any]: diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 588924623..a5c31b518 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -35,7 +35,7 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -from typing import Any, Dict, Optional +from typing import TYPE_CHECKING, Any, Iterable, Optional, Union import torch import torch.distributed as dist @@ -43,10 +43,12 @@ from alive_progress import alive_it from torch import Tensor from torch.utils.data import DataLoader +from wandb.sdk.wandb_run import Run -from minerva.datasets import make_loaders -from minerva.logger import KNNLogger, MinervaLogger -from minerva.metrics import MinervaMetrics +if TYPE_CHECKING: # pragma: no cover + from torch.utils.tensorboard.writer import SummaryWriter + +from minerva.logger import KNNLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese from minerva.utils import AUX_CONFIGS, utils @@ -63,9 +65,11 @@ def __init__( batch_size: int, n_batches: int, model_type: str, - sample_pairs: bool, - loader: DataLoader, + loader: DataLoader[Iterable[Any]], device: torch.device, + writer: Optional[Union[SummaryWriter, Run]] = None, + record_int: bool = True, + record_float: bool = False, **params, ) -> None: super().__init__( @@ -73,7 +77,6 @@ def __init__( batch_size, n_batches, model_type, - sample_pairs, loader, device, **params, @@ -84,12 +87,8 @@ def __init__( def step( self, - temp: float = 0.5, - k: int = 200, - mode: str = "val", - record_int: bool = True, - record_float: bool = False, - ) -> Optional[Dict[str, Any]]: + mode: str, + ) -> None: """Trains a KNN using the model to validate a SSL model. Adapted from https://github.com/yaohungt/Barlow-Twins-HSIC for use in :mod:`minerva`. @@ -121,8 +120,8 @@ def step( self.n_batches, self.batch_size, n_samples, - record_int=record_int, - record_float=record_float, + record_int=self.record_int, + record_float=self.record_float, writer=self.writer, ) @@ -200,7 +199,7 @@ def step( sim_matrix = torch.mm(feature, feature_bank) # [B, K] - sim_weight, sim_indices = sim_matrix.topk(k=k, dim=-1) + sim_weight, sim_indices = sim_matrix.topk(k=self.k, dim=-1) # [B, K] sim_labels = torch.gather( @@ -209,11 +208,11 @@ def step( index=sim_indices, ) - sim_weight = (sim_weight / temp).exp() + sim_weight = (sim_weight / self.temp).exp() # Counts for each class one_hot_label = torch.zeros( - test_data.size(0) * k, n_classes, device=sim_labels.device + test_data.size(0) * self.k, n_classes, device=sim_labels.device ) # [B*K, C] From 56b8796497d73456cdbbd4e62d7fbe6f62a1eda8 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Sep 2023 14:53:20 +0100 Subject: [PATCH 007/136] Feature bank creation --> `generate_feature_bank` --- minerva/tasks/knn.py | 83 ++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index a5c31b518..5aa5283b9 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -35,7 +35,7 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -from typing import TYPE_CHECKING, Any, Iterable, Optional, Union +from typing import TYPE_CHECKING, Any, Iterable, Optional, Tuple, Union import torch import torch.distributed as dist @@ -79,12 +79,56 @@ def __init__( model_type, loader, device, + writer, + record_int, + record_float, **params, ) self.temp = self.params["temp"] self.k = self.params["k"] + def generate_feature_bank(self) -> Tuple[Tensor, Tensor]: + feature_list = [] + target_list = [] + + feat_bar = alive_it(self.loaders["val"]) + for batch in feat_bar: + val_data: Tensor = batch["image"].to(self.device, non_blocking=True) + val_target: Tensor = batch["mask"].to(self.device, non_blocking=True) + target_list.append( + torch.mode(torch.flatten(val_target, start_dim=1)).values + ) + + # Get features from passing the input data through the model. + if utils.check_substrings_in_string(self.model_type, "siamese"): + # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. + if isinstance(self.model, MinervaDataParallel): # pragma: no cover + assert isinstance(self.model.model.module, MinervaSiamese) + else: + assert isinstance(self.model, MinervaSiamese) + + # Ensures that the data is parsed through a single head of the model rather than paired. + feature, _ = self.model.forward_single(val_data) # type: ignore[operator] + else: + feature, _ = self.model(val_data) + + # The masks from segmentation models will need to be flattened. + if utils.check_substrings_in_string(self.model_type, "segmentation"): + feature = feature.flatten(1, -1) + + feature_list.append(feature) + + # [D, N] + feature_bank = torch.cat(feature_list, dim=0).t().contiguous() + + # [N] + feature_labels = ( + torch.cat(target_list, dim=0).contiguous().to(feature_bank.device) + ) + + return feature_bank, feature_labels + def step( self, mode: str, @@ -126,45 +170,10 @@ def step( ) total_num = 0 - feature_list = [] - target_list = [] with torch.no_grad(): # Generate feature bank and target bank. - feat_bar = alive_it(self.loaders["val"]) - for batch in feat_bar: - val_data: Tensor = batch["image"].to(self.device, non_blocking=True) - val_target: Tensor = batch["mask"].to(self.device, non_blocking=True) - target_list.append( - torch.mode(torch.flatten(val_target, start_dim=1)).values - ) - - # Get features from passing the input data through the model. - if utils.check_substrings_in_string(self.model_type, "siamese"): - # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. - if isinstance(self.model, MinervaDataParallel): # pragma: no cover - assert isinstance(self.model.model.module, MinervaSiamese) - else: - assert isinstance(self.model, MinervaSiamese) - - # Ensures that the data is parsed through a single head of the model rather than paired. - feature, _ = self.model.forward_single(val_data) # type: ignore[operator] - else: - feature, _ = self.model(val_data) - - # The masks from segmentation models will need to be flattened. - if utils.check_substrings_in_string(self.model_type, "segmentation"): - feature = feature.flatten(1, -1) - - feature_list.append(feature) - - # [D, N] - feature_bank = torch.cat(feature_list, dim=0).t().contiguous() - - # [N] - feature_labels = ( - torch.cat(target_list, dim=0).contiguous().to(feature_bank.device) - ) + feature_bank, feature_labels = self.generate_feature_bank() # Loop test data to predict the label by weighted KNN search. test_bar = alive_it(self.loaders["test"]) From 9bfa8cf7585369a6584a51984ea0900eefdbdb34 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Sep 2023 14:59:26 +0100 Subject: [PATCH 008/136] singlular `loader` --> `loaders` --- minerva/tasks/core.py | 4 ++-- minerva/tasks/knn.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 8b1dc8ca5..e1c5424b8 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -63,7 +63,7 @@ def __init__( batch_size: int, n_batches: int, model_type: str, - loader: DataLoader[Iterable[Any]], + loaders: Dict[str, DataLoader[Iterable[Any]]], device: torch.device, writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, @@ -85,7 +85,7 @@ def __init__( self.logger: MinervaLogger = self.get_logger() self.modelio = self.get_io_func() - self.loader = loader + self.loaders = loaders self.device = device self.record_int = record_int diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 5aa5283b9..a9b7960e9 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -35,7 +35,7 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -from typing import TYPE_CHECKING, Any, Iterable, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Tuple, Union import torch import torch.distributed as dist @@ -65,7 +65,7 @@ def __init__( batch_size: int, n_batches: int, model_type: str, - loader: DataLoader[Iterable[Any]], + loaders: Dict[str, DataLoader[Iterable[Any]]], device: torch.device, writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, @@ -77,7 +77,7 @@ def __init__( batch_size, n_batches, model_type, - loader, + loaders, device, writer, record_int, From 92674ebed2ccef71e84eae8919338b732a9f6c8b Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Sep 2023 16:40:06 +0100 Subject: [PATCH 009/136] Make loaders from parameters --- minerva/tasks/core.py | 23 +++++++++++++++-------- minerva/tasks/knn.py | 13 +++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index e1c5424b8..953cb5722 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -37,16 +37,16 @@ # ===================================================================================================================== import abc from abc import ABC -from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter import torch import torch.distributed as dist -from torch.utils.data import DataLoader from wandb.sdk.wandb_run import Run +from minerva.datasets import make_loaders from minerva.logger import MinervaLogger from minerva.metrics import MinervaMetrics from minerva.models import MinervaDataParallel, MinervaModel @@ -61,29 +61,36 @@ def __init__( self, model: Union[MinervaModel, MinervaDataParallel], batch_size: int, - n_batches: int, - model_type: str, - loaders: Dict[str, DataLoader[Iterable[Any]]], device: torch.device, + rank: int = 0, + world_size: int = 1, writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, record_float: bool = False, **params, ) -> None: self.model = model - self.params = params + + # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. + loaders, n_batches, class_dist, new_params = make_loaders( + rank, world_size, **params + ) + + self.loaders = loaders + self.params = new_params + self.class_dist = class_dist # Corrects the batch size if this is a distributed job to account for batches being split across devices. if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover self.batch_size = batch_size // dist.get_world_size() # type: ignore[attr-defined] self.n_batches = n_batches - self.model_type = model_type + self.model_type = self.params["model_type"] self.sample_pairs = self.params.get("sample_pairs", False) self.metric_logger: MinervaMetrics = self.make_metric_logger() - self.logger: MinervaLogger = self.get_logger() self.modelio = self.get_io_func() + self.logger: MinervaLogger self.loaders = loaders self.device = device diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index a9b7960e9..9a4113cb3 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -35,14 +35,13 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Tuple, Union +from typing import TYPE_CHECKING, Optional, Tuple, Union import torch import torch.distributed as dist import torch.nn.functional as ptfunc from alive_progress import alive_it from torch import Tensor -from torch.utils.data import DataLoader from wandb.sdk.wandb_run import Run if TYPE_CHECKING: # pragma: no cover @@ -63,10 +62,9 @@ def __init__( self, model: MinervaModel, batch_size: int, - n_batches: int, - model_type: str, - loaders: Dict[str, DataLoader[Iterable[Any]]], device: torch.device, + rank: int = 0, + world_size: int = 1, writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, record_float: bool = False, @@ -75,10 +73,9 @@ def __init__( super().__init__( model, batch_size, - n_batches, - model_type, - loaders, device, + rank, + world_size, writer, record_int, record_float, From 8ac940b777a2d5ed880eb71eb3ad050725ef3010 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Sep 2023 16:57:01 +0100 Subject: [PATCH 010/136] Added abstract `adapt_model` method --- minerva/tasks/core.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 953cb5722..73b100db0 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -102,6 +102,16 @@ def __init__( self.step_num = 0 + @abc.abstractmethod + def adapt_model(self) -> None: + """Adapt the model for this particular task. + + .. note:: + May not be needed in all tasks. + + """ + pass + def make_metric_logger(self) -> MinervaMetrics: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. From 270fb7d162292bcdb93ee95c3cb61ab230a8e416 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 15 Sep 2023 17:18:31 +0100 Subject: [PATCH 011/136] Updated docstrings --- minerva/tasks/core.py | 81 ++++++++++++++++++++++++++++++++++++++++++- minerva/tasks/knn.py | 81 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 2 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 73b100db0..e543ece2c 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -23,7 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""""" +"""Core functionality of :mod:`tasks`, defining the abstract :class:`MinervaTask` class""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -57,6 +57,85 @@ # CLASSES # ===================================================================================================================== class MinervaTask(ABC): + """An abstract definition of a task to fit or evalulate a model within :mod:`minerva`. + + Attributes: + params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be + constructed, trained and evaluated. These should be defined via config ``YAML`` files. + model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. + batch_size (int): Size of each batch of samples supplied to the model. + loaders (dict[str, ~torch.utils.data.DataLoader]): :class:`dict` containing + :class:`~torch.utils.data.DataLoader` (s) for each dataset. + n_batches (dict[str, int]): Dictionary of the number of batches to supply to the model for train, + validation and testing. + metrics (dict[str, ~typing.Any]): Dictionary to hold the loss and accuracy results from training, + validation and testing. + device: The CUDA device on which to fit the model. + verbose (bool): Provides more prints to stdout if ``True``. + class_dist (~typing.Any): Distribution of classes within the data. + sample_pairs (bool): Whether samples are paired together for Siamese learning. + modes (tuple[str, ...]): The different *modes* of fitting in this experiment specified by the config. + writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wandb_run.Run | None): The *writer* + to perform logging for this experiment. For use with either :mod:`tensorboard` or :mod:`wandb`. + stopper (~pytorchtools.EarlyStopping | None): Early stopping function. + early_stop (bool): Whether early stopping has been triggered. Will end model training if ``True``. + n_samples (dict[str, int]): Number of samples in each mode of model fitting. + metric_logger (~logger.MinervaLogger): Object to calculate and log metrics to track the performance + of the model. + modelio_func (~typing.Callable[..., ~typing.Any]): Function to handle the input/ output to the model. + steps (dict[str, int]): :class:`dict` to hold the global step number for each mode of model fitting. + model_type (str): Type of the model that determines how to handle IO, metric calculations etc. + + Args: + model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. + rank (int): Optional; The rank of this process across all devices in the distributed run. + world_size (int): Optional; The total number of processes across the distributed run. + writer (~wandb.sdk.wandb_run.Run | RunDisabled): Optional; Run object for Weights and Biases. + params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be + constructed, trained and evaluated. These should be defined via config ``YAML`` files. + + Keyword Args: + batch_size (int): Number of samples in each batch. + elim (bool): Will eliminate classes that have no samples in and reorder the class labels so they + still run from ``0`` to ``n-1`` classes where ``n`` is the reduced number of classes. + :mod:`minerva` ensures that labels are converted between the old and new schemes seamlessly. + model_type (str): Defines the type of the model. If ``siamese``, ensures inappropiate functionality is not used. + dataset_params (dict[str, ~typing.Any]): Parameters to construct each dataset. + See documentation on structure of these. + collator (dict[str, ~typing.Any]): Defines the collator to use that will collate samples together into batches. + Contains the ``module`` key to define the import path and the ``name`` key + for name of the collation function. + sample_pairs (bool): Activates paired sampling for Siamese models. Only used for ``train`` datasets. + stopping (dict[str, ~typing.Any]): Dictionary to hold the parameters defining the early stopping functionality. + If no dictionary is given, it is assumed that there will be no early stopping. + pre_train_name (str): Name of the pre-trained model to use. + reload (bool): Reloads the weights in the cache matching ``pre_train_name`` to continue model fitting. + loss_func (str): Name of the loss function to use. + optim_func (str): Name of the optimiser function to use. + lr (float): Learning rate of optimiser. + optim_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the optimiser, + other than the already handled learning rate -- ``lr``. Place them in the ``params`` key. + If using a non-torch optimiser, use the ``module`` key to specify the import path to the optimiser function. + loss_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the loss function + in the ``params`` key. If using a non-torch loss function, you need to specify the import path + with the ``module`` key. + balance (bool): Activates class balancing. For ``model_type="scene classifer"`` or ``model_type="mlp"``, + over and under sampling will be used. For ``model_type="segmentation"``, class weighting will be + used on the loss function. + patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. + input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. + Should align with the values given for ``patch_size``. + metrics (str): Specify the metric logger to use. Must be the name of a :class:`~metrics.MinervaMetric` class + within :mod:`metrics`. + logger (str): Specify the logger to use. Must be the name of a :class:`~logger.MinervaLogger` class + within :mod:`logger`. + modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name + of a function within :mod:`modelio`. + record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. + record_float (bool): Store the floating point results of each epoch in memory + such as the raw predicted probabilities. + """ + def __init__( self, model: Union[MinervaModel, MinervaDataParallel], diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 9a4113cb3..1da5a7fe5 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -23,7 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""""" +"""KNN Validation task""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -58,6 +58,85 @@ # CLASSES # ===================================================================================================================== class WeightedKNN(MinervaTask): + """A KNN Validation task. + + Attributes: + params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be + constructed, trained and evaluated. These should be defined via config ``YAML`` files. + model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. + batch_size (int): Size of each batch of samples supplied to the model. + loaders (dict[str, ~torch.utils.data.DataLoader]): :class:`dict` containing + :class:`~torch.utils.data.DataLoader` (s) for each dataset. + n_batches (dict[str, int]): Dictionary of the number of batches to supply to the model for train, + validation and testing. + metrics (dict[str, ~typing.Any]): Dictionary to hold the loss and accuracy results from training, + validation and testing. + device: The CUDA device on which to fit the model. + verbose (bool): Provides more prints to stdout if ``True``. + class_dist (~typing.Any): Distribution of classes within the data. + sample_pairs (bool): Whether samples are paired together for Siamese learning. + modes (tuple[str, ...]): The different *modes* of fitting in this experiment specified by the config. + writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wandb_run.Run | None): The *writer* + to perform logging for this experiment. For use with either :mod:`tensorboard` or :mod:`wandb`. + stopper (~pytorchtools.EarlyStopping | None): Early stopping function. + early_stop (bool): Whether early stopping has been triggered. Will end model training if ``True``. + n_samples (dict[str, int]): Number of samples in each mode of model fitting. + metric_logger (~logger.MinervaLogger): Object to calculate and log metrics to track the performance + of the model. + modelio_func (~typing.Callable[..., ~typing.Any]): Function to handle the input/ output to the model. + steps (dict[str, int]): :class:`dict` to hold the global step number for each mode of model fitting. + model_type (str): Type of the model that determines how to handle IO, metric calculations etc. + + Args: + model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. + rank (int): Optional; The rank of this process across all devices in the distributed run. + world_size (int): Optional; The total number of processes across the distributed run. + writer (~wandb.sdk.wandb_run.Run | RunDisabled): Optional; Run object for Weights and Biases. + params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be + constructed, trained and evaluated. These should be defined via config ``YAML`` files. + + Keyword Args: + batch_size (int): Number of samples in each batch. + elim (bool): Will eliminate classes that have no samples in and reorder the class labels so they + still run from ``0`` to ``n-1`` classes where ``n`` is the reduced number of classes. + :mod:`minerva` ensures that labels are converted between the old and new schemes seamlessly. + model_type (str): Defines the type of the model. If ``siamese``, ensures inappropiate functionality is not used. + dataset_params (dict[str, ~typing.Any]): Parameters to construct each dataset. + See documentation on structure of these. + collator (dict[str, ~typing.Any]): Defines the collator to use that will collate samples together into batches. + Contains the ``module`` key to define the import path and the ``name`` key + for name of the collation function. + sample_pairs (bool): Activates paired sampling for Siamese models. Only used for ``train`` datasets. + stopping (dict[str, ~typing.Any]): Dictionary to hold the parameters defining the early stopping functionality. + If no dictionary is given, it is assumed that there will be no early stopping. + pre_train_name (str): Name of the pre-trained model to use. + reload (bool): Reloads the weights in the cache matching ``pre_train_name`` to continue model fitting. + loss_func (str): Name of the loss function to use. + optim_func (str): Name of the optimiser function to use. + lr (float): Learning rate of optimiser. + optim_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the optimiser, + other than the already handled learning rate -- ``lr``. Place them in the ``params`` key. + If using a non-torch optimiser, use the ``module`` key to specify the import path to the optimiser function. + loss_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the loss function + in the ``params`` key. If using a non-torch loss function, you need to specify the import path + with the ``module`` key. + balance (bool): Activates class balancing. For ``model_type="scene classifer"`` or ``model_type="mlp"``, + over and under sampling will be used. For ``model_type="segmentation"``, class weighting will be + used on the loss function. + patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. + input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. + Should align with the values given for ``patch_size``. + metrics (str): Specify the metric logger to use. Must be the name of a :class:`~metrics.MinervaMetric` class + within :mod:`metrics`. + logger (str): Specify the logger to use. Must be the name of a :class:`~logger.MinervaLogger` class + within :mod:`logger`. + modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name + of a function within :mod:`modelio`. + record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. + record_float (bool): Store the floating point results of each epoch in memory + such as the raw predicted probabilities. + """ + def __init__( self, model: MinervaModel, From c5a3dbfeda1a1957c61953f2562a63d05c02cc05 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 18 Sep 2023 15:42:58 +0100 Subject: [PATCH 012/136] Added `gpu` to arguments --- minerva/tasks/core.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index e543ece2c..e03e262c6 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -141,6 +141,7 @@ def __init__( model: Union[MinervaModel, MinervaDataParallel], batch_size: int, device: torch.device, + gpu: int = 0, rank: int = 0, world_size: int = 1, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -155,6 +156,8 @@ def __init__( rank, world_size, **params ) + self.gpu = gpu + self.loaders = loaders self.params = new_params self.class_dist = class_dist @@ -242,7 +245,7 @@ def get_io_func(self) -> Callable[..., Any]: @abc.abstractmethod def step(self, mode: str) -> None: - pass + raise NotImplementedError def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: self.step(mode) From e975398581b389b95ae2ebc827349a918e311966 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 18 Sep 2023 15:44:41 +0100 Subject: [PATCH 013/136] Added `StandardEpoch` task --- minerva/tasks/__init__.py | 9 +++ minerva/tasks/epoch.py | 129 ++++++++++++++++++++++++++++++++++++++ minerva/tasks/knn.py | 2 + 3 files changed, 140 insertions(+) create mode 100644 minerva/tasks/epoch.py diff --git a/minerva/tasks/__init__.py b/minerva/tasks/__init__.py index b5b9af18c..fccce6567 100644 --- a/minerva/tasks/__init__.py +++ b/minerva/tasks/__init__.py @@ -31,3 +31,12 @@ __contact__ = "hjb1d20@soton.ac.uk" __license__ = "MIT License" __copyright__ = "Copyright (C) 2023 Harry Baker" +__all__ = [ + "MinervaTask", + "StandardEpoch", + "WeightedKNN", +] + +from .core import MinervaTask +from .epoch import StandardEpoch +from .knn import WeightedKNN diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py new file mode 100644 index 000000000..b16a81c26 --- /dev/null +++ b/minerva/tasks/epoch.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +"""""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" +__all__ = ["StandardEpoch"] + + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +from contextlib import nullcontext +from typing import TYPE_CHECKING, Any, Callable, Optional, Union + +import torch +import torch.distributed as dist +from alive_progress import alive_bar +from wandb.sdk.wandb_run import Run + +if TYPE_CHECKING: # pragma: no cover + from torch.utils.tensorboard.writer import SummaryWriter + +from minerva.logger import MinervaLogger +from minerva.models import MinervaDataParallel, MinervaModel +from minerva.utils import utils + +from .core import MinervaTask + + +# ===================================================================================================================== +# CLASSES +# ===================================================================================================================== +class StandardEpoch(MinervaTask): + def step( + self, + mode: str, + ) -> None: + """All encompassing function for any type of epoch, be that train, validation or testing. + + Args: + mode (str): Either train, val or test. + Defines the type of epoch to run on the model. + """ + batch_size = self.batch_size + if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] + + # Calculates the number of samples + n_samples = self.n_batches[mode] * batch_size + + # Creates object to log the results from each step of this epoch. + _epoch_logger: Callable[..., Any] = self.get_logger() + epoch_logger: MinervaLogger = _epoch_logger( + self.n_batches[mode], + batch_size, + n_samples, + self.model.output_shape, + self.model.n_classes, + record_int=self.record_int, + record_float=self.record_float, + collapse_level=self.sample_pairs, + euclidean=self.sample_pairs, + model_type=self.model_type, + writer=self.writer, + ) + + # Initialises a progress bar for the epoch. + with alive_bar( + self.n_batches[mode], bar="blocks" + ) if self.gpu == 0 else nullcontext() as bar: + # Sets the model up for training or evaluation modes. + if mode == "train": + self.model.train() + else: + self.model.eval() + + # Core of the epoch. + for batch in self.loaders[mode]: + results = self.modelio( + batch, self.model, self.device, mode, **self.params + ) + + if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + loss = results[0].data.clone() + dist.all_reduce(loss.div_(dist.get_world_size())) # type: ignore[attr-defined] + results = (loss, *results[1:]) + + epoch_logger.log(mode, self.step_num, *results) + + self.step_num += 1 + + # Updates progress bar that batch has been processed. + if self.gpu == 0: + bar() # type: ignore + + # Updates metrics with epoch results. + self.metric_logger(mode, epoch_logger.get_logs) + + # If configured to do so, calculates the grad norms. + if self.params.get("calc_norm", False): + _ = utils.calc_grad(self.model) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 1da5a7fe5..a924c786f 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -142,6 +142,7 @@ def __init__( model: MinervaModel, batch_size: int, device: torch.device, + gpu: int = 0, rank: int = 0, world_size: int = 1, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -153,6 +154,7 @@ def __init__( model, batch_size, device, + gpu, rank, world_size, writer, From 3f882e834e68f8d9166eba0cd491d3f91b6c9b58 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 18 Sep 2023 18:44:40 +0100 Subject: [PATCH 014/136] Added `get_task` --- minerva/tasks/__init__.py | 3 ++- minerva/tasks/core.py | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/minerva/tasks/__init__.py b/minerva/tasks/__init__.py index fccce6567..20063cdbd 100644 --- a/minerva/tasks/__init__.py +++ b/minerva/tasks/__init__.py @@ -35,8 +35,9 @@ "MinervaTask", "StandardEpoch", "WeightedKNN", + "get_task", ] -from .core import MinervaTask +from .core import MinervaTask, get_task from .epoch import StandardEpoch from .knn import WeightedKNN diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index e03e262c6..b3f8a56aa 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -267,3 +267,23 @@ def get_logs(self) -> Dict[str, Any]: def __repr__(self) -> str: return self.__class__.__name__ + + +# ===================================================================================================================== +# METHODS +# ===================================================================================================================== +def get_task(task: str, params: Dict[str, Any]) -> MinervaTask: + """Get the requested :class:`MinervaTask` by name. + + Args: + task (str): Name of the task. + params (Dict[str, Any]): Parameters for the task to be initialised. + + Returns: + MinervaTask: Constructed :class:`MinervaTask` object. + """ + _task = func_by_str("minerva.tasks", task) + + task = _task(**params) + assert isinstance(task, MinervaTask) + return task From c808f9ac1e8e9f8e9ffc9f0474e294d11b45f64a Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 18 Sep 2023 18:45:17 +0100 Subject: [PATCH 015/136] Converting `fit` to `MinervaTask` use --- minerva/trainer.py | 177 +++++++++++++++++++++++---------------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/minerva/trainer.py b/minerva/trainer.py index 9143aa930..4be5808d2 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -39,7 +39,7 @@ # IMPORTS # ===================================================================================================================== import os -from contextlib import nullcontext +from copy import deepcopy from pathlib import Path from typing import ( TYPE_CHECKING, @@ -85,6 +85,7 @@ MinervaWrapper, ) from minerva.pytorchtools import EarlyStopping +from minerva.tasks import MinervaTask, get_task from minerva.utils import AUX_CONFIGS, universal_path, utils, visutils # ===================================================================================================================== @@ -631,93 +632,99 @@ def get_io_func(self) -> Callable[..., Any]: ) return io_func - def epoch( - self, - mode: str, - record_int: bool = False, - record_float: bool = False, - ) -> Optional[Dict[str, Any]]: - """All encompassing function for any type of epoch, be that train, validation or testing. - - Args: - mode (str): Either train, val or test. - Defines the type of epoch to run on the model. - record_int (bool): Optional; Whether to record the integer results - (i.e. ground truth and predicted labels). - record_float (bool): Optional; Whether to record the floating point results i.e. class probabilities. - - Returns: - dict[str, ~typing.Any] | None: If ``record_int=True`` or ``record_float=True``, returns the predicted - and ground truth labels, and the patch IDs supplied to the model. Else, returns ``None``. - """ - batch_size = self.batch_size - if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] - - # Calculates the number of samples - n_samples = self.n_batches[mode] * batch_size - - # Creates object to log the results from each step of this epoch. - _epoch_logger: Callable[..., Any] = self.get_logger() - epoch_logger: MinervaLogger = _epoch_logger( - self.n_batches[mode], - batch_size, - n_samples, - self.model.output_shape, - self.model.n_classes, - record_int=record_int, - record_float=record_float, - collapse_level=self.sample_pairs, - euclidean=self.sample_pairs, - model_type=self.model_type, - writer=self.writer, - ) - - # Initialises a progress bar for the epoch. - with alive_bar( - self.n_batches[mode], bar="blocks" - ) if self.gpu == 0 else nullcontext() as bar: - # Sets the model up for training or evaluation modes. - if mode == "train": - self.model.train() - else: - self.model.eval() - - # Core of the epoch. - for batch in self.loaders[mode]: - results = self.modelio_func( - batch, self.model, self.device, mode, **self.params - ) - - if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - loss = results[0].data.clone() - dist.all_reduce(loss.div_(dist.get_world_size())) # type: ignore[attr-defined] - results = (loss, *results[1:]) - - epoch_logger.log(mode, self.step_num[mode], *results) - - self.step_num[mode] += 1 - - # Updates progress bar that batch has been processed. - if self.gpu == 0: - bar() # type: ignore - - # Updates metrics with epoch results. - self.metric_logger(mode, epoch_logger.get_logs) - - # If configured to do so, calculates the grad norms. - if self.params.get("calc_norm", False): - _ = utils.calc_grad(self.model) - - # Returns the results of the epoch if configured to do so. Else, returns None. - if record_int or record_float: - epoch_results: Dict[str, Any] = epoch_logger.get_results - return epoch_results - else: - return None + # def epoch( + # self, + # mode: str, + # record_int: bool = False, + # record_float: bool = False, + # ) -> Optional[Dict[str, Any]]: + # """All encompassing function for any type of epoch, be that train, validation or testing. + + # Args: + # mode (str): Either train, val or test. + # Defines the type of epoch to run on the model. + # record_int (bool): Optional; Whether to record the integer results + # (i.e. ground truth and predicted labels). + # record_float (bool): Optional; Whether to record the floating point results i.e. class probabilities. + + # Returns: + # dict[str, ~typing.Any] | None: If ``record_int=True`` or ``record_float=True``, returns the predicted + # and ground truth labels, and the patch IDs supplied to the model. Else, returns ``None``. + # """ + # batch_size = self.batch_size + # if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + # batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] + + # # Calculates the number of samples + # n_samples = self.n_batches[mode] * batch_size + + # # Creates object to log the results from each step of this epoch. + # _epoch_logger: Callable[..., Any] = self.get_logger() + # epoch_logger: MinervaLogger = _epoch_logger( + # self.n_batches[mode], + # batch_size, + # n_samples, + # self.model.output_shape, + # self.model.n_classes, + # record_int=record_int, + # record_float=record_float, + # collapse_level=self.sample_pairs, + # euclidean=self.sample_pairs, + # model_type=self.model_type, + # writer=self.writer, + # ) + + # # Initialises a progress bar for the epoch. + # with alive_bar( + # self.n_batches[mode], bar="blocks" + # ) if self.gpu == 0 else nullcontext() as bar: + # # Sets the model up for training or evaluation modes. + # if mode == "train": + # self.model.train() + # else: + # self.model.eval() + + # # Core of the epoch. + # for batch in self.loaders[mode]: + # results = self.modelio_func( + # batch, self.model, self.device, mode, **self.params + # ) + + # if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + # loss = results[0].data.clone() + # dist.all_reduce(loss.div_(dist.get_world_size())) # type: ignore[attr-defined] + # results = (loss, *results[1:]) + + # epoch_logger.log(mode, self.step_num[mode], *results) + + # self.step_num[mode] += 1 + + # # Updates progress bar that batch has been processed. + # if self.gpu == 0: + # bar() # type: ignore + + # # Updates metrics with epoch results. + # self.metric_logger(mode, epoch_logger.get_logs) + + # # If configured to do so, calculates the grad norms. + # if self.params.get("calc_norm", False): + # _ = utils.calc_grad(self.model) + + # # Returns the results of the epoch if configured to do so. Else, returns None. + # if record_int or record_float: + # epoch_results: Dict[str, Any] = epoch_logger.get_results + # return epoch_results + # else: + # return None def fit(self) -> None: """Fits the model by running ``max_epochs`` number of training and validation epochs.""" + fit_params = deepcopy(self.params["tasks"]["fit"]) + + tasks: Dict[str, MinervaTask] = {} + for mode in ("train", "val"): + tasks[mode] = get_task(fit_params[mode].pop("type"), fit_params[mode]) + for epoch in range(self.max_epochs): self.print( f"\nEpoch: {epoch + 1}/{self.max_epochs} ==========================================================" From 14b5d8e65376834b02bea9295f0041de5bae8834 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 18 Sep 2023 18:45:37 +0100 Subject: [PATCH 016/136] Converted for `MinervaTask` use --- minerva/inbuilt_cfgs/example_config.yml | 198 ++++++++++++++---------- 1 file changed, 112 insertions(+), 86 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 58bfe2620..6304fb678 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -82,93 +82,119 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 120 - - image: - transforms: false - images_1: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - image2: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: false - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset +# === TASKS =================================================================== +tasks: + fit: + val_freq: 1 + train: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + train: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 120 + + image: + transforms: false + images_1: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + image2: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + val: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + val: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: false - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + test: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: From eb41631d5f434cfa83388f192009057d678d8f87 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 16:53:44 +0100 Subject: [PATCH 017/136] Integrated `MinervaTask` into `trainer` --- minerva/inbuilt_cfgs/example_config.yml | 67 ++-- minerva/trainer.py | 410 ++++-------------------- 2 files changed, 89 insertions(+), 388 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 6304fb678..8048690f2 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -162,39 +162,40 @@ tasks: params: res: 1.0 - test: - type: StandardEpoch - # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg - - # ---+ Dataset Parameters +---------------------------------------- - dataset_params: - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: false - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + tests: + test: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + test: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/trainer.py b/minerva/trainer.py index 4be5808d2..d28004977 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -632,91 +632,6 @@ def get_io_func(self) -> Callable[..., Any]: ) return io_func - # def epoch( - # self, - # mode: str, - # record_int: bool = False, - # record_float: bool = False, - # ) -> Optional[Dict[str, Any]]: - # """All encompassing function for any type of epoch, be that train, validation or testing. - - # Args: - # mode (str): Either train, val or test. - # Defines the type of epoch to run on the model. - # record_int (bool): Optional; Whether to record the integer results - # (i.e. ground truth and predicted labels). - # record_float (bool): Optional; Whether to record the floating point results i.e. class probabilities. - - # Returns: - # dict[str, ~typing.Any] | None: If ``record_int=True`` or ``record_float=True``, returns the predicted - # and ground truth labels, and the patch IDs supplied to the model. Else, returns ``None``. - # """ - # batch_size = self.batch_size - # if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - # batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] - - # # Calculates the number of samples - # n_samples = self.n_batches[mode] * batch_size - - # # Creates object to log the results from each step of this epoch. - # _epoch_logger: Callable[..., Any] = self.get_logger() - # epoch_logger: MinervaLogger = _epoch_logger( - # self.n_batches[mode], - # batch_size, - # n_samples, - # self.model.output_shape, - # self.model.n_classes, - # record_int=record_int, - # record_float=record_float, - # collapse_level=self.sample_pairs, - # euclidean=self.sample_pairs, - # model_type=self.model_type, - # writer=self.writer, - # ) - - # # Initialises a progress bar for the epoch. - # with alive_bar( - # self.n_batches[mode], bar="blocks" - # ) if self.gpu == 0 else nullcontext() as bar: - # # Sets the model up for training or evaluation modes. - # if mode == "train": - # self.model.train() - # else: - # self.model.eval() - - # # Core of the epoch. - # for batch in self.loaders[mode]: - # results = self.modelio_func( - # batch, self.model, self.device, mode, **self.params - # ) - - # if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - # loss = results[0].data.clone() - # dist.all_reduce(loss.div_(dist.get_world_size())) # type: ignore[attr-defined] - # results = (loss, *results[1:]) - - # epoch_logger.log(mode, self.step_num[mode], *results) - - # self.step_num[mode] += 1 - - # # Updates progress bar that batch has been processed. - # if self.gpu == 0: - # bar() # type: ignore - - # # Updates metrics with epoch results. - # self.metric_logger(mode, epoch_logger.get_logs) - - # # If configured to do so, calculates the grad norms. - # if self.params.get("calc_norm", False): - # _ = utils.calc_grad(self.model) - - # # Returns the results of the epoch if configured to do so. Else, returns None. - # if record_int or record_float: - # epoch_results: Dict[str, Any] = epoch_logger.get_results - # return epoch_results - # else: - # return None - def fit(self) -> None: """Fits the model by running ``max_epochs`` number of training and validation epochs.""" fit_params = deepcopy(self.params["tasks"]["fit"]) @@ -732,58 +647,20 @@ def fit(self) -> None: # Conduct training or validation epoch. for mode in ("train", "val"): - # Only run a KNN validation epoch at set frequency of epochs. Goes to next epoch if not. - if ( - mode == "val" - and utils.check_substrings_in_string( - self.model_type, "ssl", "siamese" - ) - and (epoch + 1) % self.val_freq != 0 - ): + # Only run a validation epoch at set frequency of epochs. Goes to next epoch if not. + if mode == "val" and (epoch + 1) % self.val_freq != 0: break - results: Dict[str, Any] = {} + results: Optional[Dict[str, Any]] - # If final epoch and configured to plot, runs the epoch with recording of integer results turned on. - if self.params.get("plot_last_epoch", False): - result: Optional[Dict[str, Any]] - if mode == "val" and utils.check_substrings_in_string( - self.model_type, "ssl", "siamese" - ): - result = self.weighted_knn_validation( - k=self.params.get("knn_k", None), - record_int=True, - record_float=self.params.get("record_float", False), - ) - else: - result = self.epoch( - mode, - record_int=True, - record_float=self.params.get("record_float", False), - ) - assert result is not None - results = result - - else: - if mode == "val" and utils.check_substrings_in_string( - self.model_type, "ssl", "siamese" - ): - self.weighted_knn_validation( - k=self.params.get("knn_k", None), - record_int=False, - record_float=False, - ) - else: - self.epoch(mode, record_int=False, record_float=False) + results = tasks[mode](mode) # Add epoch number to metrics. self.metric_logger.log_epoch_number(mode, epoch) # Print epoch results. if self.gpu == 0: - if mode == "val" and utils.check_substrings_in_string( - self.model_type, "ssl", "siamese" - ): + if mode == "val": epoch_no = epoch // self.val_freq else: epoch_no = epoch @@ -791,9 +668,7 @@ def fit(self) -> None: # Sends validation loss to the stopper and updates early stop bool. if mode == "val" and self.stopper is not None: - if mode == "val" and utils.check_substrings_in_string( - self.model_type, "ssl", "siamese" - ): + if mode == "val": epoch_no = epoch // self.val_freq else: epoch_no = epoch @@ -830,6 +705,8 @@ def fit(self) -> None: # Amends the results' directory to add a new level for train or validation. results_dir = self.exp_fn.parent / mode + assert results is not None + if self.gpu == 0: # Plots the results of this epoch. visutils.plot_results( @@ -866,56 +743,61 @@ def test(self, save: bool = True, show: bool = False) -> None: """ self.print("\r\nTESTING") - # Runs test epoch on model, returning the predicted labels, ground truth labels supplied - # and the IDs of the samples supplied. - results: Optional[Dict[str, Any]] = self.epoch( - "test", record_int=True, record_float=True - ) - assert results is not None + test_params = deepcopy(self.params["tasks"]["tests"]) - # Prints test loss and accuracy to stdout. - self.metric_logger.print_epoch_results("test", 0) + for _task in test_params: + task = get_task(test_params[_task]["type"], test_params[_task].pop("type")) - # Add epoch number to testing results. - self.metric_logger.log_epoch_number("test", 0) + # Runs test epoch on model, returning the predicted labels, ground truth labels supplied + # and the IDs of the samples supplied. + results = task("test") - # Now experiment is complete, saves model parameters and config file to disk in case error is - # encountered in plotting of results. - self.close() + assert results is not None - if self.gpu == 0: - if "z" in results and "y" in results: - self.print("\nMAKING CLASSIFICATION REPORT") - self.compute_classification_report(results["z"], results["y"]) + # Prints test loss and accuracy to stdout. + self.metric_logger.print_epoch_results("test", 0) - # Gets the dict from params that defines which plots to make from the results. - plots = self.params.get("plots", {}).copy() + # Add epoch number to testing results. + self.metric_logger.log_epoch_number("test", 0) - # Ensure history is not plotted again. - plots["History"] = False + if self.gpu == 0: + if "z" in results and "y" in results: + self.print("\nMAKING CLASSIFICATION REPORT") + self.compute_classification_report(results["z"], results["y"]) - if utils.check_substrings_in_string( - self.model_type, "scene classifier", "mlp", "MLP" - ): - plots["Mask"] = False - - # Amends the results' directory to add a new level for test results. - results_dir = self.exp_fn.parent / "test" - - # Plots the results. - visutils.plot_results( - plots, - mode="test", - class_names=self.params["classes"], - colours=self.params["colours"], - save=save, - show=show, - model_name=self.params["model_name"], - timestamp=self.params["timestamp"], - results_dir=results_dir, - **results, - ) + # Gets the dict from params that defines which plots to make from the results. + plots = self.params.get("plots", {}).copy() + + # Ensure history is not plotted again. + plots["History"] = False + + if utils.check_substrings_in_string( + self.model_type, "scene classifier", "mlp", "MLP" + ): + plots["Mask"] = False + + # Amends the results' directory to add a new level for test results. + results_dir = self.exp_fn.parent / "test" + + # Plots the results. + visutils.plot_results( + plots, + mode="test", + class_names=self.params["classes"], + colours=self.params["colours"], + save=save, + show=show, + model_name=self.params["model_name"], + timestamp=self.params["timestamp"], + results_dir=results_dir, + **results, + ) + # Now experiment is complete, saves model parameters and config file to disk in case error is + # encountered in plotting of results. + self.close() + + if self.gpu == 0: # Checks whether to run TensorBoard on the log from the experiment. If defined as optional in the config, # a user confirmation is required to run TensorBoard with a 60s timeout. if self.params.get("run_tensorboard", False) in ( @@ -990,188 +872,6 @@ def tsne_cluster(self, mode: str = "test") -> None: filename=str(results_dir / "tsne_cluster_vis.png"), ) - def weighted_knn_validation( - self, - temp: float = 0.5, - k: int = 200, - mode: str = "val", - record_int: bool = True, - record_float: bool = False, - ) -> Optional[Dict[str, Any]]: - """Trains a KNN using the model to validate a SSL model. - - Adapted from https://github.com/yaohungt/Barlow-Twins-HSIC for use in :mod:`minerva`. - - Args: - temp (float, optional): Temperature of the similarity loss. Defaults to 0.5. - k (int, optional): Number of similar images to use to predict images. Defaults to 200. - mode (str, optional): Mode of model fitting this has been called on. Defaults to "val". - record_int (bool, optional): Whether to record integer values. Defaults to True. - record_float (bool, optional): Whether to record floating point values. Warning! - This may result in memory issues on large amounts of data! Defaults to False. - - Returns: - dict[str, ~typing.Any] | None: Results dictionary from the epoch logger if ``record_int`` - or ``record_float`` are ``True``. - """ - - # Puts the model in evaluation mode so no back passes are made. - self.model.eval() - - # Get the number of classes from the data config. - n_classes = len(AUX_CONFIGS["data_config"]["classes"]) - - batch_size = self.batch_size - - # Corrects the batch size if this is a distributed job to account for batches being split across devices. - if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] - - # Calculates the number of samples. - n_samples = self.n_batches[mode] * batch_size - - # Uses the special `KNNLogger` to log the results from the KNN. - epoch_logger = KNNLogger( - self.n_batches[mode], - batch_size, - n_samples, - record_int=record_int, - record_float=record_float, - writer=self.writer, - ) - - total_num = 0 - feature_list = [] - target_list = [] - - with torch.no_grad(): - # Generate feature bank and target bank. - feat_bar = alive_it(self.loaders["val"]) - for batch in feat_bar: - val_data: Tensor = batch["image"].to(self.device, non_blocking=True) - val_target: Tensor = batch["mask"].to(self.device, non_blocking=True) - target_list.append( - torch.mode(torch.flatten(val_target, start_dim=1)).values - ) - - # Get features from passing the input data through the model. - if utils.check_substrings_in_string(self.model_type, "siamese"): - # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. - if isinstance(self.model, MinervaDataParallel): # pragma: no cover - assert isinstance(self.model.model.module, MinervaSiamese) - else: - assert isinstance(self.model, MinervaSiamese) - - # Ensures that the data is parsed through a single head of the model rather than paired. - feature, _ = self.model.forward_single(val_data) # type: ignore[operator] - else: - feature, _ = self.model(val_data) - - # The masks from segmentation models will need to be flattened. - if utils.check_substrings_in_string(self.model_type, "segmentation"): - feature = feature.flatten(1, -1) - - feature_list.append(feature) - - # [D, N] - feature_bank = torch.cat(feature_list, dim=0).t().contiguous() - - # [N] - feature_labels = ( - torch.cat(target_list, dim=0).contiguous().to(feature_bank.device) - ) - - # Loop test data to predict the label by weighted KNN search. - test_bar = alive_it(self.loaders["test"]) - for batch in test_bar: - test_data: Tensor = batch["image"].to(self.device, non_blocking=True) - test_target: Tensor = torch.mode( - torch.flatten( - batch["mask"].to(self.device, non_blocking=True), start_dim=1 - ) - ).values - - # Get features from passing the input data through the model. - if utils.check_substrings_in_string(self.model_type, "siamese"): - # Checks that the model is of type ``MinervaSiamese`` so a call to `forward_single` will work. - if isinstance(self.model, MinervaDataParallel): # pragma: no cover - assert isinstance(self.model.model.module, MinervaSiamese) - else: - assert isinstance(self.model, MinervaSiamese) - - # Ensures that the data is parsed through a single head of the model rather than paired. - feature, _ = self.model.forward_single(test_data) # type: ignore[operator] - else: - feature, _ = self.model(test_data) - - # The masks from segmentation models will need to be flattened. - if utils.check_substrings_in_string(self.model_type, "segmentation"): - feature = feature.flatten(1, -1) - - total_num += batch_size - - # compute cos similarity between each feature vector and feature bank ---> [B, N] - sim_matrix = torch.mm(feature, feature_bank) - - # [B, K] - sim_weight, sim_indices = sim_matrix.topk(k=k, dim=-1) - - # [B, K] - sim_labels = torch.gather( - feature_labels.expand(test_data.size(0), -1), - dim=-1, - index=sim_indices, - ) - - sim_weight = (sim_weight / temp).exp() - - # Counts for each class - one_hot_label = torch.zeros( - test_data.size(0) * k, n_classes, device=sim_labels.device - ) - - # [B*K, C] - one_hot_label = one_hot_label.scatter( - dim=-1, index=sim_labels.view(-1, 1), value=1.0 - ) - - # Weighted score ---> [B, C] - pred_scores = torch.sum( - one_hot_label.view(test_data.size(0), -1, n_classes) - * sim_weight.unsqueeze(dim=-1), - dim=1, - ) - pred_scores = ptfunc.normalize( - pred_scores.nan_to_num(nan=0.0, posinf=1.0, neginf=0.0), - ) - - # Calculate loss between predicted and ground truth labels by KNN. - criterion = torch.nn.CrossEntropyLoss() - loss = criterion(pred_scores, test_target) - - # Pack results together for the logger. - results = (loss, pred_scores, test_target, _) - - # Gathers the losses across devices together if a distributed job. - if dist.is_available() and dist.is_initialized(): # pragma: no cover - loss = results[0].data.clone() - dist.all_reduce(loss.div_(dist.get_world_size())) - results = (loss, *results[1:]) - - # Sends results to logger. - epoch_logger.log(mode, self.step_num[mode], *results) - - # Update global step number for this mode of model fitting. - self.step_num[mode] += 1 - - # Send the logs to the metric logger. - self.metric_logger(mode, epoch_logger.get_logs) - - if record_int or record_float: - return epoch_logger.get_results - else: - return None - def close(self) -> None: """Closes the experiment, saving experiment parameters and model to file.""" if _tensorflow_exist: From c97d97ad29dc495aaa572aa0bf5f49be37591b11 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 16:55:04 +0100 Subject: [PATCH 018/136] Removed now unused imports --- minerva/trainer.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/minerva/trainer.py b/minerva/trainer.py index d28004977..99e957361 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -55,10 +55,7 @@ import pandas as pd import torch -import torch.distributed as dist -import torch.nn.functional as ptfunc import yaml -from alive_progress import alive_bar, alive_it from inputimeout import TimeoutOccurred, inputimeout from nptyping import Int, NDArray from torch import Tensor @@ -74,19 +71,17 @@ from wandb.sdk.wandb_run import Run from minerva.datasets import make_loaders -from minerva.logger import KNNLogger, MinervaLogger from minerva.metrics import MinervaMetrics from minerva.models import ( MinervaBackbone, MinervaDataParallel, MinervaModel, MinervaOnnxModel, - MinervaSiamese, MinervaWrapper, ) from minerva.pytorchtools import EarlyStopping from minerva.tasks import MinervaTask, get_task -from minerva.utils import AUX_CONFIGS, universal_path, utils, visutils +from minerva.utils import universal_path, utils, visutils # ===================================================================================================================== # GLOBALS From c9cd54fbfaa1190aa59e3d2e5adae783811153f5 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 18:27:45 +0100 Subject: [PATCH 019/136] Added `exp_fn` to args --- minerva/tasks/core.py | 4 ++++ minerva/tasks/knn.py | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index b3f8a56aa..cd548eb88 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -37,6 +37,7 @@ # ===================================================================================================================== import abc from abc import ABC +from pathlib import Path from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union if TYPE_CHECKING: # pragma: no cover @@ -141,6 +142,7 @@ def __init__( model: Union[MinervaModel, MinervaDataParallel], batch_size: int, device: torch.device, + exp_fn: Path, gpu: int = 0, rank: int = 0, world_size: int = 1, @@ -156,6 +158,8 @@ def __init__( rank, world_size, **params ) + self.exp_fn = exp_fn + self.gpu = gpu self.loaders = loaders diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index a924c786f..8648111b7 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -31,6 +31,9 @@ __contact__ = "hjb1d20@soton.ac.uk" __license__ = "MIT License" __copyright__ = "Copyright (C) 2023 Harry Baker" +__all__ = ["WeightedKNN"] + +from pathlib import Path # ===================================================================================================================== # IMPORTS @@ -142,6 +145,7 @@ def __init__( model: MinervaModel, batch_size: int, device: torch.device, + exp_fn: Path, gpu: int = 0, rank: int = 0, world_size: int = 1, @@ -154,6 +158,7 @@ def __init__( model, batch_size, device, + exp_fn, gpu, rank, world_size, From d7fae4768809ba823df257e42eab34bd96dbb451 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 18:27:58 +0100 Subject: [PATCH 020/136] Removed unused imports --- minerva/tasks/epoch.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index b16a81c26..5202bacca 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -38,18 +38,12 @@ # IMPORTS # ===================================================================================================================== from contextlib import nullcontext -from typing import TYPE_CHECKING, Any, Callable, Optional, Union +from typing import Any, Callable -import torch import torch.distributed as dist from alive_progress import alive_bar -from wandb.sdk.wandb_run import Run - -if TYPE_CHECKING: # pragma: no cover - from torch.utils.tensorboard.writer import SummaryWriter from minerva.logger import MinervaLogger -from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils import utils from .core import MinervaTask From 25260da0058bc0bd061ea9f7bfeae46be0b909aa Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 18:29:33 +0100 Subject: [PATCH 021/136] Added `TSNEVis` task --- minerva/tasks/__init__.py | 2 + minerva/tasks/tsne.py | 81 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 minerva/tasks/tsne.py diff --git a/minerva/tasks/__init__.py b/minerva/tasks/__init__.py index 20063cdbd..bd76f5c05 100644 --- a/minerva/tasks/__init__.py +++ b/minerva/tasks/__init__.py @@ -35,9 +35,11 @@ "MinervaTask", "StandardEpoch", "WeightedKNN", + "TSNEVis", "get_task", ] from .core import MinervaTask, get_task from .epoch import StandardEpoch from .knn import WeightedKNN +from .tsne import TSNEVis diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py new file mode 100644 index 000000000..188723c37 --- /dev/null +++ b/minerva/tasks/tsne.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +"""TSNE Clustering task.""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" +__all__ = ["TSNEVis"] + + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +from torch import Tensor + +from minerva.utils.visutils import plot_embedding + +from .core import MinervaTask + + +# ===================================================================================================================== +# CLASSES +# ===================================================================================================================== +class TSNEVis(MinervaTask): + def step(self, mode: str) -> None: + """Perform TSNE clustering on the embeddings from the model and visualise. + + Passes a batch from the test dataset through the model in eval mode to get the embeddings. + Passes these embeddings to :mod:`visutils` to train a TSNE algorithm and then visual the cluster. + + Args: + mode (str): The mode of model fitting that the embeddings come from. + """ + # Get a batch of data. + data = next(iter(self.loaders[mode])) + + # Make sure the model is in evaluation mode. + self.model.eval() + + # Pass the batch of data through the model to get the embeddings. + embeddings: Tensor = self.model(data["image"].to(self.device))[0] + + # Flatten embeddings. + embeddings = embeddings.flatten(start_dim=1) + + # Get the results directory. + results_dir = self.exp_fn.parent / mode + + plot_embedding( + embeddings.detach().cpu(), + data["bbox"], + mode, + show=True, + filename=str(results_dir / "tsne_cluster_vis.png"), + ) From b95c5970d1a63f50677cc4c9c19d68b1f39ccea6 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 18:48:52 +0100 Subject: [PATCH 022/136] Removed `adapt_model` abstract method --- minerva/tasks/core.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index cd548eb88..35080287c 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -188,16 +188,6 @@ def __init__( self.step_num = 0 - @abc.abstractmethod - def adapt_model(self) -> None: - """Adapt the model for this particular task. - - .. note:: - May not be needed in all tasks. - - """ - pass - def make_metric_logger(self) -> MinervaMetrics: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. @@ -276,7 +266,7 @@ def __repr__(self) -> str: # ===================================================================================================================== # METHODS # ===================================================================================================================== -def get_task(task: str, params: Dict[str, Any]) -> MinervaTask: +def get_task(task: str, *args, **params) -> MinervaTask: """Get the requested :class:`MinervaTask` by name. Args: @@ -288,6 +278,6 @@ def get_task(task: str, params: Dict[str, Any]) -> MinervaTask: """ _task = func_by_str("minerva.tasks", task) - task = _task(**params) + task = _task(*args, **params) assert isinstance(task, MinervaTask) return task From 9b85efd7a101ac58c9f323e3b8c1c3d5a409c061 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 20 Sep 2023 18:49:55 +0100 Subject: [PATCH 023/136] Adapted existing TSNE method for `TSNEVis` --- minerva/tasks/tsne.py | 37 ++++++++++++++++++++++++ minerva/trainer.py | 65 +++++++++++++++++++++++++++---------------- 2 files changed, 78 insertions(+), 24 deletions(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 188723c37..1a85b58f4 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -37,8 +37,15 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== +from pathlib import Path +from typing import Union + +import torch from torch import Tensor +from torch.utils.tensorboard.writer import SummaryWriter +from wandb.sdk.wandb_run import Run +from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils.visutils import plot_embedding from .core import MinervaTask @@ -48,6 +55,36 @@ # CLASSES # ===================================================================================================================== class TSNEVis(MinervaTask): + def __init__( + self, + model: Union[MinervaModel, MinervaDataParallel], + batch_size: int, + device: torch.device, + exp_fn: Path, + gpu: int = 0, + rank: int = 0, + world_size: int = 1, + writer: Union[SummaryWriter, Run, None] = None, + record_int: bool = True, + record_float: bool = False, + **params, + ) -> None: + super().__init__( + model, + batch_size, + device, + exp_fn, + gpu, + rank, + world_size, + writer, + record_int, + record_float, + **params, + ) + if self.params.get("data", None): + self.loaders["test"] = self.params["data"] + def step(self, mode: str) -> None: """Perform TSNE clustering on the embeddings from the model and visualise. diff --git a/minerva/trainer.py b/minerva/trainer.py index 99e957361..13c473d87 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -80,7 +80,7 @@ MinervaWrapper, ) from minerva.pytorchtools import EarlyStopping -from minerva.tasks import MinervaTask, get_task +from minerva.tasks import MinervaTask, TSNEVis, get_task from minerva.utils import universal_path, utils, visutils # ===================================================================================================================== @@ -257,6 +257,8 @@ def __init__( # Sets the global GPU number for distributed computing. In single process, this will just be 0. self.gpu: int = gpu + self.rank = rank + self.world_size = world_size # Finds and sets the CUDA device to be used. self.device = utils.get_cuda_device(gpu) @@ -633,7 +635,18 @@ def fit(self) -> None: tasks: Dict[str, MinervaTask] = {} for mode in ("train", "val"): - tasks[mode] = get_task(fit_params[mode].pop("type"), fit_params[mode]) + tasks[mode] = get_task( + fit_params[mode].pop("type"), + self.model, + self.batch_size, + self.device, + self.exp_fn, + self.gpu, + self.rank, + self.world_size, + self.writer, + fit_params[mode], + ) for epoch in range(self.max_epochs): self.print( @@ -646,6 +659,11 @@ def fit(self) -> None: if mode == "val" and (epoch + 1) % self.val_freq != 0: break + if mode == "train": + self.model.train() + else: + self.model.eval() + results: Optional[Dict[str, Any]] results = tasks[mode](mode) @@ -741,7 +759,18 @@ def test(self, save: bool = True, show: bool = False) -> None: test_params = deepcopy(self.params["tasks"]["tests"]) for _task in test_params: - task = get_task(test_params[_task]["type"], test_params[_task].pop("type")) + task = get_task( + test_params[_task].pop("type"), + self.model, + self.batch_size, + self.device, + self.exp_fn, + self.gpu, + self.rank, + self.world_size, + self.writer, + test_params[_task], + ) # Runs test epoch on model, returning the predicted labels, ground truth labels supplied # and the IDs of the samples supplied. @@ -844,27 +873,15 @@ def tsne_cluster(self, mode: str = "test") -> None: Args: mode (str): The mode of model fitting that the embeddings come from. """ - # Get a batch of data. - data = next(iter(self.loaders[mode])) - - # Make sure the model is in evaluation mode. - self.model.eval() - - # Pass the batch of data through the model to get the embeddings. - embeddings: Tensor = self.model(data["image"].to(self.device))[0] - - # Flatten embeddings. - embeddings = embeddings.flatten(start_dim=1) - - # Get the results directory. - results_dir = self.exp_fn.parent / mode - - visutils.plot_embedding( - embeddings.detach().cpu(), - data["bbox"], - mode, - show=True, - filename=str(results_dir / "tsne_cluster_vis.png"), + task = TSNEVis( + self.model, + self.batch_size, + self.device, + self.exp_fn, + self.gpu, + self.rank, + self.world_size, + self.writer, ) def close(self) -> None: From b5c0a8f8f8d83f439f5c93343abf550be7188f71 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 21 Sep 2023 11:43:59 +0100 Subject: [PATCH 024/136] Added missing call to `task` in `tsne_cluster` --- minerva/trainer.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/minerva/trainer.py b/minerva/trainer.py index 13c473d87..cccfdcf23 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -884,6 +884,8 @@ def tsne_cluster(self, mode: str = "test") -> None: self.writer, ) + task(mode) + def close(self) -> None: """Closes the experiment, saving experiment parameters and model to file.""" if _tensorflow_exist: From 9676f28de29cc466c0c9135f64548dfcf93a0781 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 21 Sep 2023 17:56:57 +0100 Subject: [PATCH 025/136] Name simplifications --- minerva/datasets/factory.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index a11a6924b..5bfee23af 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -481,9 +481,9 @@ def make_loaders( utils.print_class_dist(class_dist) params["n_classes"] = len(new_classes) - model_params_params = params["model_params"].get("params", {}) - model_params_params["n_classes"] = len(new_classes) - params["model_params"]["params"] = model_params_params + model_params = params["model_params"].get("params", {}) + model_params["n_classes"] = len(new_classes) + params["model_params"]["params"] = model_params params["classes"] = new_classes params["colours"] = new_colours @@ -532,8 +532,6 @@ def get_manifest(manifest_path: Union[str, Path]) -> DataFrame: print("CONSTRUCTING MISSING MANIFEST") mf_config = CONFIG.copy() - mf_config["dataloader_params"] = CONFIG["loader_params"] - manifest = make_manifest(mf_config) print(f"MANIFEST TO FILE -----> {manifest_path}") @@ -558,7 +556,7 @@ def make_manifest(mf_config: Dict[Any, Any]) -> DataFrame: ~pandas.DataFrame: The completed manifest as a :class:`~pandas.DataFrame`. """ batch_size: int = mf_config["batch_size"] - dataloader_params: Dict[str, Any] = mf_config["dataloader_params"] + loader_params: Dict[str, Any] = mf_config["loader_params"] dataset_params: Dict[str, Any] = mf_config["dataset_params"] collator_params: Dict[str, Any] = mf_config["collator"] @@ -580,7 +578,7 @@ def make_manifest(mf_config: Dict[Any, Any]) -> DataFrame: mf_config["dir"]["data"], dataset_params[keys[0]], sampler_params, - dataloader_params, + loader_params, batch_size, collator_params=collator_params, ) From 56498cd8340dc838f604742350eeb28b20f0f6dd Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 21 Sep 2023 17:57:19 +0100 Subject: [PATCH 026/136] Ensured `SummaryWriter` is defined --- minerva/tasks/core.py | 5 ++++- minerva/tasks/knn.py | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 35080287c..901733d0c 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -42,6 +42,8 @@ if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter +else: # pragma: no cover + SummaryWriter = None import torch import torch.distributed as dist @@ -89,6 +91,8 @@ class MinervaTask(ABC): Args: model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. + batch_size (int): Number of samples in each batch. + device: The CUDA device on which to fit the model. rank (int): Optional; The rank of this process across all devices in the distributed run. world_size (int): Optional; The total number of processes across the distributed run. writer (~wandb.sdk.wandb_run.Run | RunDisabled): Optional; Run object for Weights and Biases. @@ -96,7 +100,6 @@ class MinervaTask(ABC): constructed, trained and evaluated. These should be defined via config ``YAML`` files. Keyword Args: - batch_size (int): Number of samples in each batch. elim (bool): Will eliminate classes that have no samples in and reorder the class labels so they still run from ``0`` to ``n-1`` classes where ``n`` is the reduced number of classes. :mod:`minerva` ensures that labels are converted between the old and new schemes seamlessly. diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 8648111b7..8c030ff13 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -49,6 +49,8 @@ if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter +else: # pragma: no cover + SummaryWriter = None from minerva.logger import KNNLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese From b9c9bcb7c0d1834a42eda3b0e03da9da5045d501 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 21 Sep 2023 17:57:54 +0100 Subject: [PATCH 027/136] Added docstring to `TSNEVis` --- minerva/tasks/tsne.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 1a85b58f4..97fe73a53 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -55,6 +55,12 @@ # CLASSES # ===================================================================================================================== class TSNEVis(MinervaTask): + """TSNE clustering task. + + Passes a batch of data through the model in eval mode to get the embeddings. + Passes these embeddings to :mod:`visutils` to train a TSNE algorithm and then visual the cluster. + """ + def __init__( self, model: Union[MinervaModel, MinervaDataParallel], From ce73ffc0bec70678a363dcaa2bf788294c726b72 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 21 Sep 2023 18:02:31 +0100 Subject: [PATCH 028/136] Removed methods for getting logger and IO function --- minerva/trainer.py | 65 ++++++---------------------------------------- 1 file changed, 8 insertions(+), 57 deletions(-) diff --git a/minerva/trainer.py b/minerva/trainer.py index cccfdcf23..84be2c634 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -251,9 +251,9 @@ def __init__( assert not isinstance(wandb_run, RunDisabled) # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. - loaders, n_batches, class_dist, new_params = make_loaders( - rank, world_size, **params - ) + # loaders, n_batches, class_dist, new_params = make_loaders( + # rank, world_size, **params + # ) # Sets the global GPU number for distributed computing. In single process, this will just be 0. self.gpu: int = gpu @@ -274,9 +274,9 @@ def __init__( utils.print_config(new_params) self.params: Dict[str, Any] = new_params - self.class_dist = class_dist - self.loaders: Dict[str, DataLoader[Iterable[Any]]] = loaders - self.n_batches = n_batches + # self.class_dist = class_dist + # self.loaders: Dict[str, DataLoader[Iterable[Any]]] = loaders + # self.n_batches = n_batches self.batch_size: int = self.params["batch_size"] self.model_type: str = self.params["model_type"] self.val_freq: int = self.params.get("val_freq", 1) @@ -360,8 +360,8 @@ def __init__( } # Initialise the metric logger and model IO for the experiment. - self.metric_logger = self.make_metric_logger() - self.modelio_func = self.get_io_func() + # self.metric_logger = self.make_metric_logger() + # self.modelio_func = self.get_io_func() # Stores the step number for that mode of fitting. To be used for logging. self.step_num = {mode: 0 for mode in self.modes} @@ -580,55 +580,6 @@ def make_optimiser(self) -> None: optimiser(self.model.parameters(), **optimiser_params["params"]) ) - def make_metric_logger(self) -> MinervaMetrics: - """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. - - Returns: - MinervaMetrics: Constructed metric logger. - """ - - # Gets the size of the input data to the network (without batch dimension). - data_size = self.params["input_size"] - - # Gets constructor of the metric logger from name in the config. - _metric_logger: Callable[..., Any] = utils.func_by_str( - "minerva.metrics", self.params["metrics"] - ) - - # Initialises the metric logger with arguments. - metric_logger: MinervaMetrics = _metric_logger( - self.n_batches, - batch_size=self.batch_size, - data_size=data_size, - model_type=self.model_type, - sample_pairs=self.sample_pairs, - ) - - return metric_logger - - def get_logger(self) -> Callable[..., Any]: - """Creates an object to log the results from each step of model fitting during an epoch. - - Returns: - ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logger.MinervaLogger` - to be intialised within the epoch. - """ - logger: Callable[..., Any] = utils.func_by_str( - "minerva.logger", self.params["logger"] - ) - return logger - - def get_io_func(self) -> Callable[..., Any]: - """Fetches a func to handle IO for the type of model used in the experiment. - - Returns: - ~typing.Callable[..., ~typing.Any]: Model IO function requested from parameters. - """ - io_func: Callable[..., Any] = utils.func_by_str( - "minerva.modelio", self.params["model_io"] - ) - return io_func - def fit(self) -> None: """Fits the model by running ``max_epochs`` number of training and validation epochs.""" fit_params = deepcopy(self.params["tasks"]["fit"]) From e0ab5b61cf43d4156d6026bb500d95b1952d477a Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 22 Sep 2023 18:22:12 +0100 Subject: [PATCH 029/136] Decouple `Trainer` from metrics, logging, datasets --- minerva/trainer.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/minerva/trainer.py b/minerva/trainer.py index 84be2c634..e900631e8 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -271,9 +271,9 @@ def __init__( print( "\n==+ Experiment Parameters +=====================================================" ) - utils.print_config(new_params) + utils.print_config(dict(params)) - self.params: Dict[str, Any] = new_params + self.params: Dict[str, Any] = dict(params) # self.class_dist = class_dist # self.loaders: Dict[str, DataLoader[Iterable[Any]]] = loaders # self.n_batches = n_batches @@ -355,9 +355,9 @@ def __init__( ) # Calculates number of samples in each mode of fitting. - self.n_samples = { - mode: self.n_batches[mode] * self.batch_size for mode in self.modes - } + # self.n_samples = { + # mode: self.n_batches[mode] * self.batch_size for mode in self.modes + # } # Initialise the metric logger and model IO for the experiment. # self.metric_logger = self.make_metric_logger() From b5ae4fada8495cb6fbd5b477e81a26990cea917f Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 22 Sep 2023 18:23:06 +0100 Subject: [PATCH 030/136] Moving loggers into metric loggers --- minerva/metrics.py | 32 ++++++++++++++++---------------- minerva/tasks/core.py | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/minerva/metrics.py b/minerva/metrics.py index 86342e202..b62efe2b0 100644 --- a/minerva/metrics.py +++ b/minerva/metrics.py @@ -42,7 +42,9 @@ # ===================================================================================================================== import abc from abc import ABC -from typing import Any, Dict, List, Tuple +from typing import Any, Dict, List, Optional, Tuple + +from minerva.logger import MinervaLogger # ===================================================================================================================== @@ -63,7 +65,7 @@ class MinervaMetrics(ABC): n_batches (dict[str, int]): Dictionary of the number of batches in each mode of fitting. batch_size (int): Batch size. data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. - + logger_params (dict[str, ~typing.Any]): Optional; Parameters for a logger other than the default for these metrics. """ __metaclass__ = abc.ABCMeta @@ -73,9 +75,11 @@ class MinervaMetrics(ABC): def __init__( self, - n_batches: Dict[str, int], + n_batches: int, batch_size: int, data_size: Tuple[int, int, int], + task_name: str, + logger_params: Optional[Dict[str, Any]] = None, **params, ) -> None: super(MinervaMetrics, self).__init__() @@ -87,36 +91,33 @@ def __init__( self.model_type = params.get("model_type", "scene_classifier") self.sample_pairs = params.get("sample_pairs", False) - self.modes = params.get("modes", ["train", "val", "test"]) + self.logger = MinervaLogger() if self.sample_pairs: self.metric_types += self.special_metric_types # Creates a dict to hold the loss and accuracy results from training, validation and testing. self.metrics: Dict[str, Any] = {} - for mode in self.modes: - for metric in self.metric_types: - self.metrics[f"{mode}_{metric}"] = {"x": [], "y": []} + for metric in self.metric_types: + self.metrics[f"{task_name}_{metric}"] = {"x": [], "y": []} - def __call__(self, mode: str, logs: Dict[str, Any]) -> None: - self.calc_metrics(mode, logs) + def __call__(self, logs: Dict[str, Any]) -> None: + self.calc_metrics(logs) @abc.abstractmethod - def calc_metrics(self, mode: str, logs: Dict[str, Any]) -> None: + def calc_metrics(self, logs: Dict[str, Any]) -> None: """Updates metrics with epoch results. Args: - mode (str): Mode of model fitting. - logs (dict[str, ~typing.Any]): Logs of the results from the epoch of fitting to calculate metrics from. + logs (dict[str, ~typing.Any]): Logs of the results from the epoch of the task to calculate metrics from. """ pass # pragma: no cover @abc.abstractmethod - def log_epoch_number(self, mode: str, epoch_no: int) -> None: + def log_epoch_number(self, epoch_no: int) -> None: """Logs the epoch number to ``metrics``. Args: - mode (str): Mode of model fitting. epoch_no (int): Epoch number to log. """ pass # pragma: no cover @@ -152,11 +153,10 @@ def get_sub_metrics( return sub_metrics @abc.abstractmethod - def print_epoch_results(self, mode: str, epoch_no: int) -> None: + def print_epoch_results(self, epoch_no: int) -> None: """Prints the results from an epoch to ``stdout``. Args: - mode (str): Mode of fitting to print results from. epoch_no (int): Epoch number to print results from. """ pass # pragma: no cover diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 901733d0c..f6e644fc6 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -179,7 +179,6 @@ def __init__( self.metric_logger: MinervaMetrics = self.make_metric_logger() self.modelio = self.get_io_func() - self.logger: MinervaLogger self.loaders = loaders self.device = device From 4b445464a5ada8844a9d5b9d47ccdf839cd51a9e Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 24 Sep 2023 23:56:57 +0100 Subject: [PATCH 031/136] Integrated a `MinervaLogger` into `MinervaMetrics` classes --- minerva/logger.py | 41 +++++--- minerva/metrics.py | 216 ++++++++++++++++++++++++++++++------------ minerva/tasks/core.py | 18 +--- 3 files changed, 184 insertions(+), 91 deletions(-) diff --git a/minerva/logger.py b/minerva/logger.py index 7d6a53055..57f0019dd 100644 --- a/minerva/logger.py +++ b/minerva/logger.py @@ -70,6 +70,7 @@ from wandb.sdk.wandb_run import Run from minerva.utils import utils +from minerva.utils.utils import func_by_str # ===================================================================================================================== # GLOBALS @@ -124,6 +125,7 @@ def __init__( n_batches: int, batch_size: int, n_samples: int, + task_name: str, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -135,28 +137,27 @@ def __init__( self.n_batches = n_batches self.batch_size = batch_size self.n_samples = n_samples + self.task_name = task_name self.writer = writer self.logs: Dict[str, Any] = {} self.results: Dict[str, Any] = {} - def __call__(self, mode: str, step_num: int, loss: Tensor, *args) -> None: + def __call__(self, step_num: int, loss: Tensor, *args) -> None: """Call :meth:`log`. Args: - mode (str): Mode of model fitting. step_num (int): The global step number of for the mode of model fitting. loss (~torch.Tensor): Loss from this step of model fitting. Returns: None """ - self.log(mode, step_num, loss, *args) + self.log(step_num, loss, *args) @abc.abstractmethod def log( self, - mode: str, step_num: int, loss: Tensor, z: Optional[Tensor] = None, @@ -168,7 +169,6 @@ def log( """Abstract logging method, the core functionality of a logger. Must be overwritten. Args: - mode (str): Mode of model fitting. step_num (int): The global step number of for the mode of model fitting. loss (~torch.Tensor): Loss from this step of model fitting. z (~torch.Tensor): Optional; Output tensor from the model. @@ -181,12 +181,11 @@ def log( pass # pragma: no cover def write_metric( - self, mode: str, key: str, value: SupportsFloat, step_num: Optional[int] = None + self, key: str, value: SupportsFloat, step_num: Optional[int] = None ): """Write metric values to logging backends after calculation. Args: - mode (str): Mode of model fitting. key (str): Key for the metric that ``value`` belongs to. value (SupportsFloat): Metric to write to logger. step_num (int): Optional; Global step number for this ``mode`` of fitting. @@ -202,12 +201,17 @@ def write_metric( and self.writer ): self.writer.add_scalar( # type: ignore[attr-defined] - tag=f"{mode}_{key}", + tag=f"{self.task_name}_{key}", scalar_value=value, # type: ignore[attr-defined] global_step=step_num, ) if isinstance(self.writer, Run): - self.writer.log({f"{mode}/step": step_num, f"{mode}/{key}": value}) + self.writer.log( + { + f"{self.task_name}/step": step_num, + f"{self.task_name}/{key}": value, + } + ) if mlflow.active_run(): # If running in Azure Machine Learning, tracking URI / experiment ID set already @@ -361,7 +365,7 @@ def __init__( def log( self, - mode: str, + task_name: str, step_num: int, loss: Tensor, z: Optional[Tensor] = None, @@ -428,12 +432,12 @@ def log( ) # noqa: E501 type: ignore[attr-defined] self.logs["total_miou"] += miou - self.write_metric(mode, "miou", miou / len(y), step_num=step_num) + self.write_metric(task_name, "miou", miou / len(y), step_num=step_num) # Writes loss and correct predictions to the writer. - self.write_metric(mode, "loss", ls, step_num=step_num) + self.write_metric(task_name, "loss", ls, step_num=step_num) self.write_metric( - mode, "acc", correct / len(torch.flatten(y)), step_num=step_num + task_name, "acc", correct / len(torch.flatten(y)), step_num=step_num ) # Adds 1 to batch number (step number). @@ -698,3 +702,14 @@ def log( # Adds 1 to the batch number (step number). self.logs["batch_num"] += 1 + + +def get_logger(name) -> Callable[..., Any]: + """Creates an object to log the results from each step of model fitting during an epoch. + + Returns: + ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logger.MinervaLogger` + to be intialised within the epoch. + """ + logger: Callable[..., Any] = func_by_str("minerva.logger", name) + return logger diff --git a/minerva/metrics.py b/minerva/metrics.py index b62efe2b0..9919d1fed 100644 --- a/minerva/metrics.py +++ b/minerva/metrics.py @@ -42,9 +42,16 @@ # ===================================================================================================================== import abc from abc import ABC -from typing import Any, Dict, List, Optional, Tuple +from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union -from minerva.logger import MinervaLogger +if TYPE_CHECKING: # pragma: no cover + from torch.utils.tensorboard.writer import SummaryWriter + +from torch import Tensor +from torchgeo.datasets.utils import BoundingBox +from wandb.sdk.wandb_run import Run + +from minerva.logger import MinervaLogger, SSLLogger, STGLogger, get_logger # ===================================================================================================================== @@ -72,6 +79,7 @@ class MinervaMetrics(ABC): metric_types: List[str] = [] special_metric_types: List[str] = [] + logger_cls: Callable[..., MinervaLogger] def __init__( self, @@ -80,18 +88,40 @@ def __init__( data_size: Tuple[int, int, int], task_name: str, logger_params: Optional[Dict[str, Any]] = None, + record_int: bool = True, + record_float: bool = False, + writer: Optional[Union[SummaryWriter, Run]] = None, **params, ) -> None: super(MinervaMetrics, self).__init__() self.n_batches = n_batches self.batch_size = batch_size + self.n_samples = self.n_batches * self.batch_size self.data_size = data_size + self.task_name = task_name self.model_type = params.get("model_type", "scene_classifier") self.sample_pairs = params.get("sample_pairs", False) - self.logger = MinervaLogger() + self.writer = writer + + if logger_params: + if logger_params.get("name", None) is not None: + self.logger_cls = get_logger(logger_params["name"]) + + else: + logger_params = {} + + self.logger = self.logger_cls( + self.n_batches, + self.batch_size, + self.n_samples, + record_int, + record_float, + self.writer, + **logger_params["params"], + ) if self.sample_pairs: self.metric_types += self.special_metric_types @@ -99,15 +129,51 @@ def __init__( # Creates a dict to hold the loss and accuracy results from training, validation and testing. self.metrics: Dict[str, Any] = {} for metric in self.metric_types: - self.metrics[f"{task_name}_{metric}"] = {"x": [], "y": []} + self.metrics[f"{self.task_name}_{metric}"] = {"x": [], "y": []} + + def step( + self, + step_num: int, + loss: Tensor, + z: Optional[Tensor] = None, + y: Optional[Tensor] = None, + bbox: Optional[BoundingBox] = None, + *args, + **kwargs, + ) -> None: + """Abstract method to log a step, using the logger. Must be overwritten. + + Args: + mode (str): Mode of model fitting. + step_num (int): The global step number of for the mode of model fitting. + loss (~torch.Tensor): Loss from this step of model fitting. + z (~torch.Tensor): Optional; Output tensor from the model. + y (~torch.Tensor): Optional; Labels to assess model output against. + bbox (~torchgeo.datasets.utils.BoundingBox): Optional; Bounding boxes of the input samples. + + Returns: + None + """ + self.logger.log( + step_num, + loss, + z, + y, + bbox, + *args, + **kwargs, + ) - def __call__(self, logs: Dict[str, Any]) -> None: - self.calc_metrics(logs) + def calc_metrics(self) -> None: + """Updates metrics with epoch results.""" + self._calc_metrics(self.logger.get_logs) @abc.abstractmethod - def calc_metrics(self, logs: Dict[str, Any]) -> None: + def _calc_metrics(self, logs: Dict[str, Any]) -> None: """Updates metrics with epoch results. + Must be defined before use. + Args: logs (dict[str, ~typing.Any]): Logs of the results from the epoch of the task to calculate metrics from. """ @@ -181,76 +247,90 @@ class SPMetrics(MinervaMetrics): """ metric_types: List[str] = ["loss", "acc", "miou"] + logger_cls = STGLogger def __init__( self, - n_batches: Dict[str, int], + n_batches: int, batch_size: int, data_size: Tuple[int, int, int], + task_name: str, + logger_params: Optional[Dict[str, Any]] = None, + record_int: bool = True, + record_float: bool = False, + writer: Optional[Union[SummaryWriter, Run]] = None, model_type: str = "segmentation", **params, ) -> None: super(SPMetrics, self).__init__( - n_batches, batch_size, data_size, model_type=model_type + n_batches, + batch_size, + data_size, + task_name, + logger_params, + record_int, + record_float, + writer, + model_type=model_type, ) - def calc_metrics(self, mode: str, logs: Dict[str, Any]) -> None: + def _calc_metrics(self, logs: Dict[str, Any]) -> None: """Updates metrics with epoch results. Args: mode (str): Mode of model fitting. logs (dict[str, ~typing.Any]): Logs of the results from the epoch of fitting to calculate metrics from. """ - self.metrics[f"{mode}_loss"]["y"].append( - logs["total_loss"] / self.n_batches[mode] + self.metrics[f"{self.task_name}_loss"]["y"].append( + logs["total_loss"] / self.n_batches ) if self.model_type == "segmentation": - self.metrics[f"{mode}_acc"]["y"].append( + self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] / ( - self.n_batches[mode] + self.n_batches * self.batch_size * self.data_size[1] * self.data_size[2] ) ) if logs.get("total_miou") is not None: - self.metrics[f"{mode}_miou"]["y"].append( - logs["total_miou"] / (self.n_batches[mode] * self.batch_size) + self.metrics[f"{self.task_name}_miou"]["y"].append( + logs["total_miou"] / (self.n_samples) ) else: - self.metrics[f"{mode}_acc"]["y"].append( - logs["total_correct"] / (self.n_batches[mode] * self.batch_size) + self.metrics[f"{self.task_name}_acc"]["y"].append( + logs["total_correct"] / (self.n_samples) ) - def log_epoch_number(self, mode: str, epoch_no: int) -> None: + def log_epoch_number(self, epoch_no: int) -> None: """Logs the epoch number to ``metrics``. Args: - mode (str): Mode of model fitting. epoch_no (int): Epoch number to log. """ - self.metrics[f"{mode}_loss"]["x"].append(epoch_no + 1) - self.metrics[f"{mode}_acc"]["x"].append(epoch_no + 1) - self.metrics[f"{mode}_miou"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_loss"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_acc"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_miou"]["x"].append(epoch_no + 1) - def print_epoch_results(self, mode: str, epoch_no: int) -> None: + def print_epoch_results(self, epoch_no: int) -> None: """Prints the results from an epoch to ``stdout``. Args: - mode (str): Mode of fitting to print results from. epoch_no (int): Epoch number to print results from. """ msg = "{} | Loss: {} | Accuracy: {}%".format( - mode, - self.metrics[f"{mode}_loss"]["y"][epoch_no], - self.metrics[f"{mode}_acc"]["y"][epoch_no] * 100.0, + self.task_name, + self.metrics[f"{self.task_name}_loss"]["y"][epoch_no], + self.metrics[f"{self.task_name}_acc"]["y"][epoch_no] * 100.0, ) if self.model_type == "segmentation": - msg += " | mIoU: {}".format(self.metrics[f"{mode}_miou"]["y"][epoch_no]) + msg += " | mIoU: {}".format( + self.metrics[f"{self.task_name}_miou"]["y"][epoch_no] + ) msg += "\n" print(msg) @@ -276,12 +356,18 @@ class SSLMetrics(MinervaMetrics): metric_types = ["loss", "acc", "top5_acc"] special_metric_types = ["collapse_level", "euc_dist"] + logger_cls = SSLLogger def __init__( self, - n_batches: Dict[str, int], + n_batches: int, batch_size: int, data_size: Tuple[int, int, int], + task_name: str, + logger_params: Optional[Dict[str, Any]] = None, + record_int: bool = True, + record_float: bool = False, + writer: Optional[Union[SummaryWriter, Run]] = None, model_type: str = "segmentation", sample_pairs: bool = False, **params, @@ -290,35 +376,39 @@ def __init__( n_batches, batch_size, data_size, + task_name, + logger_params, + record_int, + record_float, + writer, model_type=model_type, sample_pairs=sample_pairs, ) - def calc_metrics(self, mode: str, logs) -> None: + def _calc_metrics(self, logs: Dict[str, Any]) -> None: """Updates metrics with epoch results. Args: - mode (str): Mode of model fitting. logs (dict[str, ~typing.Any]): Logs of the results from the epoch of fitting to calculate metrics from. """ - self.metrics[f"{mode}_loss"]["y"].append( - logs["total_loss"] / self.n_batches[mode] + self.metrics[f"{self.task_name}_loss"]["y"].append( + logs["total_loss"] / self.n_batches ) if self.model_type == "segmentation": - self.metrics[f"{mode}_acc"]["y"].append( + self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] / ( - self.n_batches[mode] + self.n_batches * self.batch_size * self.data_size[1] * self.data_size[2] ) ) - self.metrics[f"{mode}_top5_acc"]["y"].append( + self.metrics[f"{self.task_name}_top5_acc"]["y"].append( logs["total_top5"] / ( - self.n_batches[mode] + self.n_batches * self.batch_size * self.data_size[1] * self.data_size[2] @@ -326,56 +416,56 @@ def calc_metrics(self, mode: str, logs) -> None: ) else: - self.metrics[f"{mode}_acc"]["y"].append( - logs["total_correct"] / (self.n_batches[mode] * self.batch_size) + self.metrics[f"{self.task_name}_acc"]["y"].append( + logs["total_correct"] / (self.n_samples) ) - self.metrics[f"{mode}_top5_acc"]["y"].append( - logs["total_top5"] / (self.n_batches[mode] * self.batch_size) + self.metrics[f"{self.task_name}_top5_acc"]["y"].append( + logs["total_top5"] / (self.n_samples) ) - if self.sample_pairs and mode == "train": - self.metrics[f"{mode}_collapse_level"]["y"].append(logs["collapse_level"]) - self.metrics[f"{mode}_euc_dist"]["y"].append( - logs["euc_dist"] / self.n_batches[mode] + if self.sample_pairs: + self.metrics[f"{self.task_name}_collapse_level"]["y"].append( + logs["collapse_level"] + ) + self.metrics[f"{self.task_name}_euc_dist"]["y"].append( + logs["euc_dist"] / self.n_batches ) - def log_epoch_number(self, mode: str, epoch_no: int) -> None: + def log_epoch_number(self, epoch_no: int) -> None: """Logs the epoch number to ``metrics``. Args: - mode (str): Mode of model fitting. epoch_no (int): Epoch number to log. """ - self.metrics[f"{mode}_loss"]["x"].append(epoch_no + 1) - self.metrics[f"{mode}_acc"]["x"].append(epoch_no + 1) - self.metrics[f"{mode}_top5_acc"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_loss"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_acc"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_top5_acc"]["x"].append(epoch_no + 1) - if self.sample_pairs and mode == "train": - self.metrics[f"{mode}_collapse_level"]["x"].append(epoch_no + 1) - self.metrics[f"{mode}_euc_dist"]["x"].append(epoch_no + 1) + if self.sample_pairs: + self.metrics[f"{self.task_name}_collapse_level"]["x"].append(epoch_no + 1) + self.metrics[f"{self.task_name}_euc_dist"]["x"].append(epoch_no + 1) - def print_epoch_results(self, mode: str, epoch_no: int) -> None: + def print_epoch_results(self, epoch_no: int) -> None: """Prints the results from an epoch to ``stdout``. Args: - mode (str): Mode of fitting to print results from. epoch_no (int): Epoch number to print results from. """ msg = "{} | Loss: {} | Accuracy: {}% | Top5 Accuracy: {}% ".format( - mode, - self.metrics[f"{mode}_loss"]["y"][epoch_no], - self.metrics[f"{mode}_acc"]["y"][epoch_no] * 100.0, - self.metrics[f"{mode}_top5_acc"]["y"][epoch_no] * 100.0, + self.task_name, + self.metrics[f"{self.task_name}_loss"]["y"][epoch_no], + self.metrics[f"{self.task_name}_acc"]["y"][epoch_no] * 100.0, + self.metrics[f"{self.task_name}_top5_acc"]["y"][epoch_no] * 100.0, ) - if self.sample_pairs and mode == "train": + if self.sample_pairs: msg += "\n" msg += "| Collapse Level: {}%".format( - self.metrics[f"{mode}_collapse_level"]["y"][epoch_no] * 100.0 + self.metrics[f"{self.task_name}_collapse_level"]["y"][epoch_no] * 100.0 ) msg += "| Avg. Euclidean Distance: {}".format( - self.metrics[f"{mode}_euc_dist"]["y"][epoch_no] + self.metrics[f"{self.task_name}_euc_dist"]["y"][epoch_no] ) msg += "\n" diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index f6e644fc6..3a725e064 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -216,18 +216,6 @@ def make_metric_logger(self) -> MinervaMetrics: return metric_logger - def get_logger(self) -> Callable[..., Any]: - """Creates an object to log the results from each step of model fitting during an epoch. - - Returns: - ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logger.MinervaLogger` - to be intialised within the epoch. - """ - logger: Callable[..., Any] = func_by_str( - "minerva.logger", self.params["logger"] - ) - return logger - def get_io_func(self) -> Callable[..., Any]: """Fetches a func to handle IO for the type of model used in the experiment. @@ -247,10 +235,10 @@ def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: self.step(mode) # Send the logs to the metric logger. - self.metric_logger(mode, self.logger.get_logs) + self.metric_logger.calc_metrics() if self.record_int or self.record_float: - return self.logger.get_results + return self.metric_logger.get_results else: return None @@ -259,7 +247,7 @@ def __call__(self, mode: str) -> Any: @property def get_logs(self) -> Dict[str, Any]: - return self.logger.get_logs + return self.metric_logger.get_logs def __repr__(self) -> str: return self.__class__.__name__ From b610634f1b463f358c44d48d2cf818d3635dc441 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 12:33:34 +0100 Subject: [PATCH 032/136] Created `logging` sub-package --- minerva/logging/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 minerva/logging/__init__.py diff --git a/minerva/logging/__init__.py b/minerva/logging/__init__.py new file mode 100644 index 000000000..e69de29bb From de7e677fffa520aec45bb65752d3b446150d702e Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 12:34:13 +0100 Subject: [PATCH 033/136] `metrics` --> `logging.tasklog` --- minerva/{metrics.py => logging/tasklog.py} | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) rename minerva/{metrics.py => logging/tasklog.py} (96%) diff --git a/minerva/metrics.py b/minerva/logging/tasklog.py similarity index 96% rename from minerva/metrics.py rename to minerva/logging/tasklog.py index 9919d1fed..ea6381c7d 100644 --- a/minerva/metrics.py +++ b/minerva/logging/tasklog.py @@ -32,9 +32,9 @@ __license__ = "MIT License" __copyright__ = "Copyright (C) 2023 Harry Baker" __all__ = [ - "MinervaMetrics", - "SPMetrics", - "SSLMetrics", + "MinervaTaskLogger", + "SupervisedTaskLogger", + "SSLTaskLogger", ] # ===================================================================================================================== @@ -51,13 +51,18 @@ from torchgeo.datasets.utils import BoundingBox from wandb.sdk.wandb_run import Run -from minerva.logger import MinervaLogger, SSLLogger, STGLogger, get_logger +from .steplog import ( + MinervaStepLogger, + SSLStepLogger, + SupervisedGeoStepLogger, + get_logger, +) # ===================================================================================================================== # CLASSES # ===================================================================================================================== -class MinervaMetrics(ABC): +class MinervaTaskLogger(ABC): """Abstract class for metric logging within the :mod:`minerva` framework. Attributes: @@ -79,7 +84,7 @@ class MinervaMetrics(ABC): metric_types: List[str] = [] special_metric_types: List[str] = [] - logger_cls: Callable[..., MinervaLogger] + logger_cls: Callable[..., MinervaStepLogger] def __init__( self, @@ -93,7 +98,7 @@ def __init__( writer: Optional[Union[SummaryWriter, Run]] = None, **params, ) -> None: - super(MinervaMetrics, self).__init__() + super(MinervaTaskLogger, self).__init__() self.n_batches = n_batches self.batch_size = batch_size @@ -228,7 +233,7 @@ def print_epoch_results(self, epoch_no: int) -> None: pass # pragma: no cover -class SPMetrics(MinervaMetrics): +class SupervisedTaskLogger(MinervaTaskLogger): """Metric logging for supervised models. Attributes: @@ -247,7 +252,7 @@ class SPMetrics(MinervaMetrics): """ metric_types: List[str] = ["loss", "acc", "miou"] - logger_cls = STGLogger + logger_cls = SupervisedGeoStepLogger def __init__( self, @@ -262,7 +267,7 @@ def __init__( model_type: str = "segmentation", **params, ) -> None: - super(SPMetrics, self).__init__( + super(SupervisedTaskLogger, self).__init__( n_batches, batch_size, data_size, @@ -336,7 +341,7 @@ def print_epoch_results(self, epoch_no: int) -> None: print(msg) -class SSLMetrics(MinervaMetrics): +class SSLTaskLogger(MinervaTaskLogger): """Metric logging for self-supervised models. Attributes: @@ -356,7 +361,7 @@ class SSLMetrics(MinervaMetrics): metric_types = ["loss", "acc", "top5_acc"] special_metric_types = ["collapse_level", "euc_dist"] - logger_cls = SSLLogger + logger_cls = SSLStepLogger def __init__( self, @@ -372,7 +377,7 @@ def __init__( sample_pairs: bool = False, **params, ) -> None: - super(SSLMetrics, self).__init__( + super(SSLTaskLogger, self).__init__( n_batches, batch_size, data_size, From 6299fb5cb1f202ba621e0edb5dd52d5028db4732 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 12:34:53 +0100 Subject: [PATCH 034/136] `logger` --> `logging.steplog` --- minerva/{logger.py => logging/steplog.py} | 67 +++++++++++++---------- minerva/tasks/core.py | 19 +++---- 2 files changed, 47 insertions(+), 39 deletions(-) rename minerva/{logger.py => logging/steplog.py} (93%) diff --git a/minerva/logger.py b/minerva/logging/steplog.py similarity index 93% rename from minerva/logger.py rename to minerva/logging/steplog.py index 57f0019dd..e46672658 100644 --- a/minerva/logger.py +++ b/minerva/logging/steplog.py @@ -34,10 +34,10 @@ __license__ = "MIT License" __copyright__ = "Copyright (C) 2023 Harry Baker" __all__ = [ - "MinervaLogger", - "STGLogger", - "SSLLogger", - "KNNLogger", + "MinervaStepLogger", + "SupervisedGeoStepLogger", + "SSLStepLogger", + "KNNStepLogger", ] # ===================================================================================================================== @@ -92,7 +92,7 @@ # ===================================================================================================================== # CLASSES # ===================================================================================================================== -class MinervaLogger(ABC): +class MinervaStepLogger(ABC): """Base abstract class for all :mod:`minerva` logger classes to ensure intercompatibility with :class:`~trainer.Trainer`. @@ -131,7 +131,7 @@ def __init__( writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: - super(MinervaLogger, self).__init__() + super(MinervaStepLogger, self).__init__() self.record_int = record_int self.record_float = record_float self.n_batches = n_batches @@ -237,7 +237,7 @@ def get_results(self) -> Dict[str, Any]: return self.results -class STGLogger(MinervaLogger): +class SupervisedGeoStepLogger(MinervaStepLogger): """Logger designed for supervised learning using :mod:`torchgeo` datasets. Attributes: @@ -283,6 +283,7 @@ def __init__( n_batches: int, batch_size: int, n_samples: int, + task_name: str, out_shape: Union[int, Tuple[int, ...]], n_classes: int, record_int: bool = True, @@ -290,10 +291,11 @@ def __init__( writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: - super(STGLogger, self).__init__( + super(SupervisedGeoStepLogger, self).__init__( n_batches, batch_size, n_samples, + task_name, record_int, record_float, writer, @@ -365,7 +367,6 @@ def __init__( def log( self, - task_name: str, step_num: int, loss: Tensor, z: Optional[Tensor] = None, @@ -432,19 +433,17 @@ def log( ) # noqa: E501 type: ignore[attr-defined] self.logs["total_miou"] += miou - self.write_metric(task_name, "miou", miou / len(y), step_num=step_num) + self.write_metric("miou", miou / len(y), step_num=step_num) # Writes loss and correct predictions to the writer. - self.write_metric(task_name, "loss", ls, step_num=step_num) - self.write_metric( - task_name, "acc", correct / len(torch.flatten(y)), step_num=step_num - ) + self.write_metric("loss", ls, step_num=step_num) + self.write_metric("acc", correct / len(torch.flatten(y)), step_num=step_num) # Adds 1 to batch number (step number). self.logs["batch_num"] += 1 -class KNNLogger(MinervaLogger): +class KNNStepLogger(MinervaStepLogger): """Logger specifically designed for use with the KNN validation in :meth:`trainer.Trainer.weighted_knn_validation`. @@ -481,13 +480,21 @@ def __init__( n_batches: int, batch_size: int, n_samples: int, + task_name: str, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: super().__init__( - n_batches, batch_size, n_samples, record_int, record_float, writer, **kwargs + n_batches, + batch_size, + n_samples, + task_name, + record_int, + record_float, + writer, + **kwargs, ) self.logs: Dict[str, Any] = { @@ -507,7 +514,6 @@ def __init__( def log( self, - mode: str, step_num: int, loss: Tensor, z: Optional[Tensor] = None, @@ -534,15 +540,15 @@ def log( self.logs["total_top5"] += top5 # Write results to the writer. - self.write_metric(mode, "loss", loss, step_num) - self.write_metric(mode, "acc", top1, step_num) - self.write_metric(mode, "top5", top5, step_num) + self.write_metric("loss", loss, step_num) + self.write_metric("acc", top1, step_num) + self.write_metric("top5", top5, step_num) # Adds 1 to batch number (step number). self.logs["batch_num"] += 1 -class SSLLogger(MinervaLogger): +class SSLStepLogger(MinervaStepLogger): """Logger designed for self-supervised learning. Attributes: @@ -579,6 +585,7 @@ def __init__( n_batches: int, batch_size: int, n_samples: int, + task_name: str, out_shape: Optional[Tuple[int, ...]] = None, n_classes: Optional[int] = None, record_int: bool = True, @@ -586,10 +593,11 @@ def __init__( writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: - super(SSLLogger, self).__init__( + super(SSLStepLogger, self).__init__( n_batches, batch_size, n_samples, + task_name, record_int, record_float=record_float, writer=writer, @@ -616,7 +624,6 @@ def __init__( def log( self, - mode: str, step_num: int, loss: Tensor, z: Optional[Tensor] = None, @@ -628,7 +635,6 @@ def log( """Logs the outputs and results from a step of model fitting. Overwrites abstract method. Args: - mode (str): Mode of model fitting. step_num (int): The global step number of for the mode of model fitting. loss (~torch.Tensor): Loss from this step of model fitting. z (~torch.Tensor): Optional; Output tensor from the model. @@ -662,7 +668,7 @@ def log( ) euc_dist = sum(euc_dists) / len(euc_dists) - self.write_metric(mode, "euc_dist", euc_dist, step_num) + self.write_metric("euc_dist", euc_dist, step_num) self.logs["euc_dist"] += euc_dist if self.collapse_level: @@ -687,7 +693,7 @@ def log( 0.0, 1 - math.sqrt(len(output)) * self.logs["avg_output_std"] ) - self.write_metric(mode, "collapse_level", collapse_level, step_num) + self.write_metric("collapse_level", collapse_level, step_num) self.logs["collapse_level"] = collapse_level @@ -696,14 +702,17 @@ def log( self.logs["total_top5"] += top5 # Writes the loss to the writer. - self.write_metric(mode, "loss", ls, step_num=step_num) - self.write_metric(mode, "acc", correct / 2 * len(z[0]), step_num) - self.write_metric(mode, "top5_acc", top5 / 2 * len(z[0]), step_num) + self.write_metric("loss", ls, step_num=step_num) + self.write_metric("acc", correct / 2 * len(z[0]), step_num) + self.write_metric("top5_acc", top5 / 2 * len(z[0]), step_num) # Adds 1 to the batch number (step number). self.logs["batch_num"] += 1 +# ===================================================================================================================== +# METHODS +# ===================================================================================================================== def get_logger(name) -> Callable[..., Any]: """Creates an object to log the results from each step of model fitting during an epoch. diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 3a725e064..d9494c5f4 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -50,8 +50,7 @@ from wandb.sdk.wandb_run import Run from minerva.datasets import make_loaders -from minerva.logger import MinervaLogger -from minerva.metrics import MinervaMetrics +from minerva.logging.tasklog import MinervaTaskLogger from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils.utils import func_by_str @@ -177,7 +176,7 @@ def __init__( self.model_type = self.params["model_type"] self.sample_pairs = self.params.get("sample_pairs", False) - self.metric_logger: MinervaMetrics = self.make_metric_logger() + self.logger: MinervaTaskLogger = self.make_logger() self.modelio = self.get_io_func() self.loaders = loaders @@ -190,23 +189,23 @@ def __init__( self.step_num = 0 - def make_metric_logger(self) -> MinervaMetrics: + def make_logger(self) -> MinervaTaskLogger: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. Returns: - MinervaMetrics: Constructed metric logger. + MinervaTaskLogger: Constructed metric logger. """ # Gets the size of the input data to the network (without batch dimension). data_size = self.params["input_size"] # Gets constructor of the metric logger from name in the config. - _metric_logger: Callable[..., Any] = func_by_str( + _logger: Callable[..., Any] = func_by_str( "minerva.metrics", self.params["metrics"] ) # Initialises the metric logger with arguments. - metric_logger: MinervaMetrics = _metric_logger( + logger: MinervaTaskLogger = _logger( self.n_batches, batch_size=self.batch_size, data_size=data_size, @@ -214,7 +213,7 @@ def make_metric_logger(self) -> MinervaMetrics: sample_pairs=self.sample_pairs, ) - return metric_logger + return logger def get_io_func(self) -> Callable[..., Any]: """Fetches a func to handle IO for the type of model used in the experiment. @@ -238,7 +237,7 @@ def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: self.metric_logger.calc_metrics() if self.record_int or self.record_float: - return self.metric_logger.get_results + return self.logger.get_results else: return None @@ -247,7 +246,7 @@ def __call__(self, mode: str) -> Any: @property def get_logs(self) -> Dict[str, Any]: - return self.metric_logger.get_logs + return self.logger.get_logs def __repr__(self) -> str: return self.__class__.__name__ From 3114bcd935d6d263406ab20a02dcc37aba3150a2 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 13:53:06 +0100 Subject: [PATCH 035/136] Added docstring to `logging` --- minerva/logging/__init__.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/minerva/logging/__init__.py b/minerva/logging/__init__.py index e69de29bb..469cb4cc6 100644 --- a/minerva/logging/__init__.py +++ b/minerva/logging/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +""":mod:`logging` contains functionality for logging and analysing results within :mod:`minerva`""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" +__all__ = [ + "MinervaTaskLogger", +] From cbd6f53eca0ca7e8602e73f69f0e392a15ff91a1 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 17:41:32 +0100 Subject: [PATCH 036/136] Updated `logging` `__all__` --- minerva/logging/__init__.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/minerva/logging/__init__.py b/minerva/logging/__init__.py index 469cb4cc6..2b9e0d23d 100644 --- a/minerva/logging/__init__.py +++ b/minerva/logging/__init__.py @@ -33,4 +33,18 @@ __copyright__ = "Copyright (C) 2023 Harry Baker" __all__ = [ "MinervaTaskLogger", + "SSLTaskLogger", + "SupervisedTaskLogger", + "MinervaStepLogger", + "SupervisedGeoStepLogger", + "SSLStepLogger", + "KNNStepLogger", ] + +from .steplog import ( + KNNStepLogger, + MinervaStepLogger, + SSLStepLogger, + SupervisedGeoStepLogger, +) +from .tasklog import MinervaTaskLogger, SSLTaskLogger, SupervisedTaskLogger From c2f2633dced1758ed93fcef69352dc765efafe81 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 17:41:52 +0100 Subject: [PATCH 037/136] Updated `steplog` docstring --- minerva/logging/steplog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index e46672658..40442e4ff 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -23,7 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""Module to handle the logging of results from various model types.""" +"""Loggers to handle the logging from each step of a task.""" # ===================================================================================================================== # METADATA # ===================================================================================================================== From 3ce676cd999e31c3ec1a2cc24b24399aca9143ef Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 25 Sep 2023 17:42:13 +0100 Subject: [PATCH 038/136] Updated `tasklog` docstring --- minerva/logging/tasklog.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index ea6381c7d..d15956b82 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -23,7 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""Module to calculate the metrics of a model's fitting.""" +"""These loggers are designed to handle the logging and analysis for a whole task.""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -198,10 +198,19 @@ def get_metrics(self) -> Dict[str, Any]: """Get the ``metrics`` dictionary. Returns: - dict[str, Any]: Metrics dictionary. + dict[str, ~typing.Any]: Metrics dictionary. """ return self.metrics + @property + def get_logs(self) -> Dict[str, Any]: + """Get the logs of each step from the latest epoch of the task. + + Returns: + dict[str, ~typing.Any]: Logs per step of last epoch. + """ + return self.logger.get_logs + def get_sub_metrics( self, pattern: Tuple[str, ...] = ("train", "val") ) -> Dict[str, Any]: From 56516e1621cee3703fae32c677c2b95631ebb9ed Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 16:02:50 +0100 Subject: [PATCH 039/136] `mode` --> `train` boolean --- minerva/modelio.py | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/minerva/modelio.py b/minerva/modelio.py index 48bb6e512..3158005da 100644 --- a/minerva/modelio.py +++ b/minerva/modelio.py @@ -57,7 +57,7 @@ def sup_tg( batch: Dict[Any, Any], model: MinervaModel, device: torch.device, # type: ignore[name-defined] - mode: str, + train: bool, **kwargs, ) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], Tensor, Sequence[BoundingBox]]: """Provides IO functionality for a supervised model using :mod:`torchgeo` datasets. @@ -67,7 +67,7 @@ def sup_tg( Must have ``"image"``, ``"mask"`` and ``"bbox"`` keys. model (MinervaModel): Model being fitted. device (~torch.device): `torch` device object to send data to (e.g. CUDA device). - mode (str): Mode of model fitting to use. + train (bool): True to run a step of the model in training mode. False for eval mode. Returns: tuple[~torch.Tensor, ~torch.Tensor, ~torch.Tensor, ~typing.Sequence[~torchgeo.datasets.utils.BoundingBox]]: @@ -94,13 +94,8 @@ def sup_tg( x: Tensor = x_batch.to(device) y: Tensor = y_batch.to(device) - # Runs a training epoch. - if mode == "train": - loss, z = model.step(x, y, train=True) - - # Runs a validation or test epoch. - else: - loss, z = model.step(x, y, train=False) + # Runs a step of the epoch. + loss, z = model.step(x, y, train=train) bbox: Sequence[BoundingBox] = batch["bbox"] assert isinstance(bbox, Sequence) @@ -111,7 +106,7 @@ def autoencoder_io( batch: Dict[Any, Any], model: MinervaModel, device: torch.device, # type: ignore[name-defined] - mode: str, + train: bool, **kwargs, ) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], Tensor, Sequence[BoundingBox]]: """Provides IO functionality for an autoencoder using :mod:`torchgeo` datasets by only using the same data @@ -122,7 +117,7 @@ def autoencoder_io( Must have ``"image"``, ``"mask"`` and ``"bbox"`` keys. model (MinervaModel): Model being fitted. device (~torch.device): `torch` device object to send data to (e.g. CUDA device). - mode (str): Mode of model fitting to use. + train (bool): True to run a step of the model in training mode. False for eval mode. Keyword args: autoencoder_data_key (str): Key of the data type in the sample dict to use for both input and ground truth. @@ -180,13 +175,8 @@ def autoencoder_io( f"The value of {key=} is not understood. Must be either 'mask' or 'image'" ) - # Runs a training epoch. - if mode == "train": - loss, z = model.step(x, y, train=True) - - # Runs a validation or test epoch. - else: - loss, z = model.step(x, y, train=False) + # Runs a step of the epoch. + loss, z = model.step(x, y, train=train) bbox: Sequence[BoundingBox] = batch["bbox"] assert isinstance(bbox, Sequence) @@ -197,7 +187,7 @@ def ssl_pair_tg( batch: Tuple[Dict[str, Any], Dict[str, Any]], model: MinervaModel, device: torch.device, # type: ignore[name-defined] - mode: str, + train: bool, **kwargs, ) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], None, Sequence[BoundingBox]]: """Provides IO functionality for a self-supervised Siamese model using :mod:`torchgeo` datasets. @@ -207,7 +197,7 @@ def ssl_pair_tg( Must have ``"image"`` and ``"bbox"`` keys. model (MinervaModel): Model being fitted. device (~torch.device): :mod:`torch` device object to send data to (e.g. ``CUDA`` device). - mode (str): Mode of model fitting to use. + train (bool): True to run a step of the model in training mode. False for eval mode. Returns: tuple[~torch.Tensor, ~torch.Tensor, ~torch.Tensor, ~typing.Sequence[~torchgeo.datasets.utils.BoundingBox]]: The @@ -228,12 +218,7 @@ def ssl_pair_tg( # Transfer to GPU. x = x_batch.to(device, non_blocking=True) - # Runs a training epoch. - if mode == "train": - loss, z = model.step(x, train=True) - - # Runs a validation epoch. - else: - loss, z = model.step(x, train=False) + # Runs a step of the epoch. + loss, z = model.step(x, train=train) return loss, z, None, batch[0]["bbox"] + batch[1]["bbox"] From 0dd171ff7dbd13e4b1a2c27731ae8e79b7ffc353 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 16:04:27 +0100 Subject: [PATCH 040/136] `mode` --> `train` bool and added `name` arg --- minerva/tasks/core.py | 52 ++++++++++++++++++++++++------------- minerva/tasks/epoch.py | 59 +++++++++++++----------------------------- minerva/tasks/knn.py | 45 ++++++++++---------------------- 3 files changed, 65 insertions(+), 91 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index d9494c5f4..a40cedb25 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -23,7 +23,10 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""Core functionality of :mod:`tasks`, defining the abstract :class:`MinervaTask` class""" +"""Core functionality of :mod:`tasks`, defining the abstract :class:`MinervaTask` class + +.. versionadded:: 0.27 +""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -50,7 +53,7 @@ from wandb.sdk.wandb_run import Run from minerva.datasets import make_loaders -from minerva.logging.tasklog import MinervaTaskLogger +from minerva.logging.tasklog import MinervaTaskLogger, SupervisedTaskLogger from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils.utils import func_by_str @@ -137,14 +140,20 @@ class MinervaTask(ABC): record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. record_float (bool): Store the floating point results of each epoch in memory such as the raw predicted probabilities. + + .. versionadded:: 0.27 """ + logger_cls: MinervaTaskLogger = SupervisedTaskLogger + def __init__( self, + name: str, model: Union[MinervaModel, MinervaDataParallel], batch_size: int, device: torch.device, exp_fn: Path, + train: bool = False, gpu: int = 0, rank: int = 0, world_size: int = 1, @@ -153,6 +162,8 @@ def __init__( record_float: bool = False, **params, ) -> None: + self.name = name + self.model = model # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. @@ -162,6 +173,8 @@ def __init__( self.exp_fn = exp_fn + self.train = train + self.gpu = gpu self.loaders = loaders @@ -176,39 +189,42 @@ def __init__( self.model_type = self.params["model_type"] self.sample_pairs = self.params.get("sample_pairs", False) - self.logger: MinervaTaskLogger = self.make_logger() - self.modelio = self.get_io_func() - - self.loaders = loaders - self.device = device + self.output_size = model.output_shape self.record_int = record_int self.record_float = record_float - self.writer = writer + self.modelio = self.get_io_func() + self.loaders = loaders + self.device = device + self.writer = writer self.step_num = 0 + self.logger: MinervaTaskLogger = self.make_logger() + def make_logger(self) -> MinervaTaskLogger: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. Returns: - MinervaTaskLogger: Constructed metric logger. + MinervaTaskLogger: Constructed task logger. """ - # Gets the size of the input data to the network (without batch dimension). - data_size = self.params["input_size"] - # Gets constructor of the metric logger from name in the config. - _logger: Callable[..., Any] = func_by_str( - "minerva.metrics", self.params["metrics"] + self.logger_cls = func_by_str( + "minerva.logging.tasklog", self.params.get("logger", self.logger_cls) ) # Initialises the metric logger with arguments. - logger: MinervaTaskLogger = _logger( + logger: MinervaTaskLogger = self.logger_cls( + self.name, self.n_batches, - batch_size=self.batch_size, - data_size=data_size, + self.batch_size, + self.output_size, + step_logger_params=self.params.get("step_logger"), + record_int=self.record_int, + record_float=self.record_float, + writer=self.writer, model_type=self.model_type, sample_pairs=self.sample_pairs, ) @@ -234,7 +250,7 @@ def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: self.step(mode) # Send the logs to the metric logger. - self.metric_logger.calc_metrics() + self.logger.calc_metrics() if self.record_int or self.record_float: return self.logger.get_results diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index 5202bacca..ee448b274 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -23,7 +23,10 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""""" +"""A standard epoch for use with generic model fitting. + +.. versionadded:: 0.27 +""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -38,12 +41,11 @@ # IMPORTS # ===================================================================================================================== from contextlib import nullcontext -from typing import Any, Callable import torch.distributed as dist from alive_progress import alive_bar -from minerva.logger import MinervaLogger +from minerva.logging import SupervisedTaskLogger from minerva.utils import utils from .core import MinervaTask @@ -53,53 +55,28 @@ # CLASSES # ===================================================================================================================== class StandardEpoch(MinervaTask): - def step( - self, - mode: str, - ) -> None: - """All encompassing function for any type of epoch, be that train, validation or testing. - - Args: - mode (str): Either train, val or test. - Defines the type of epoch to run on the model. - """ - batch_size = self.batch_size - if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] - - # Calculates the number of samples - n_samples = self.n_batches[mode] * batch_size - - # Creates object to log the results from each step of this epoch. - _epoch_logger: Callable[..., Any] = self.get_logger() - epoch_logger: MinervaLogger = _epoch_logger( - self.n_batches[mode], - batch_size, - n_samples, - self.model.output_shape, - self.model.n_classes, - record_int=self.record_int, - record_float=self.record_float, - collapse_level=self.sample_pairs, - euclidean=self.sample_pairs, - model_type=self.model_type, - writer=self.writer, - ) + """A standard epoch for use with generic model fitting. + + .. versionadded:: 0.27 + """ + + logger_cls = SupervisedTaskLogger + def step(self) -> None: # Initialises a progress bar for the epoch. with alive_bar( - self.n_batches[mode], bar="blocks" + self.n_batches, bar="blocks" ) if self.gpu == 0 else nullcontext() as bar: # Sets the model up for training or evaluation modes. - if mode == "train": + if self.train: self.model.train() else: self.model.eval() # Core of the epoch. - for batch in self.loaders[mode]: + for batch in self.loaders: results = self.modelio( - batch, self.model, self.device, mode, **self.params + batch, self.model, self.device, self.train, **self.params ) if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover @@ -107,7 +84,7 @@ def step( dist.all_reduce(loss.div_(dist.get_world_size())) # type: ignore[attr-defined] results = (loss, *results[1:]) - epoch_logger.log(mode, self.step_num, *results) + self.logger.step(self.step_num, *results) self.step_num += 1 @@ -116,7 +93,7 @@ def step( bar() # type: ignore # Updates metrics with epoch results. - self.metric_logger(mode, epoch_logger.get_logs) + self.logger.calc_metrics() # If configured to do so, calculates the grad norms. if self.params.get("calc_norm", False): diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 8c030ff13..fe23ea58d 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -23,7 +23,10 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -"""KNN Validation task""" +"""KNN Validation task. + +.. versionadded:: 0.27 +""" # ===================================================================================================================== # METADATA # ===================================================================================================================== @@ -52,7 +55,7 @@ else: # pragma: no cover SummaryWriter = None -from minerva.logger import KNNLogger +from minerva.logging import SSLTaskLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese from minerva.utils import AUX_CONFIGS, utils @@ -140,10 +143,15 @@ class WeightedKNN(MinervaTask): record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. record_float (bool): Store the floating point results of each epoch in memory such as the raw predicted probabilities. + + .. versionadded:: 0.27 """ + logger_cls = SSLTaskLogger + def __init__( self, + name: str, model: MinervaModel, batch_size: int, device: torch.device, @@ -157,6 +165,7 @@ def __init__( **params, ) -> None: super().__init__( + name, model, batch_size, device, @@ -214,25 +223,10 @@ def generate_feature_bank(self) -> Tuple[Tensor, Tensor]: return feature_bank, feature_labels - def step( - self, - mode: str, - ) -> None: + def step(self) -> None: """Trains a KNN using the model to validate a SSL model. Adapted from https://github.com/yaohungt/Barlow-Twins-HSIC for use in :mod:`minerva`. - - Args: - temp (float, optional): Temperature of the similarity loss. Defaults to 0.5. - k (int, optional): Number of similar images to use to predict images. Defaults to 200. - mode (str, optional): Mode of model fitting this has been called on. Defaults to "val". - record_int (bool, optional): Whether to record integer values. Defaults to True. - record_float (bool, optional): Whether to record floating point values. Warning! - This may result in memory issues on large amounts of data! Defaults to False. - - Returns: - dict[str, ~typing.Any] | None: Results dictionary from the epoch logger if ``record_int`` - or ``record_float`` are ``True``. """ # Puts the model in evaluation mode so no back passes are made. @@ -241,19 +235,6 @@ def step( # Get the number of classes from the data config. n_classes = len(AUX_CONFIGS["data_config"]["classes"]) - # Calculates the number of samples. - n_samples = self.n_batches * self.batch_size - - # Uses the special `KNNLogger` to log the results from the KNN. - epoch_logger = KNNLogger( - self.n_batches, - self.batch_size, - n_samples, - record_int=self.record_int, - record_float=self.record_float, - writer=self.writer, - ) - total_num = 0 with torch.no_grad(): @@ -338,7 +319,7 @@ def step( results = (loss, *results[1:]) # Sends results to logger. - epoch_logger.log(mode, self.step_num, *results) + self.logger.step(self.step_num, *results) # Update global step number for this mode of model fitting. self.step_num += 1 From 61c6ec7887d1b1430b826fcc1efa97bd8dc32eb9 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 16:09:54 +0100 Subject: [PATCH 041/136] Streamlined arguments between task and step loggers --- minerva/logging/steplog.py | 72 ++++++++++++++-------------- minerva/logging/tasklog.py | 96 +++++++++++++++++++++++--------------- 2 files changed, 96 insertions(+), 72 deletions(-) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index 40442e4ff..b362fc92a 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -93,7 +93,7 @@ # CLASSES # ===================================================================================================================== class MinervaStepLogger(ABC): - """Base abstract class for all :mod:`minerva` logger classes to ensure intercompatibility with + """Base abstract class for all :mod:`minerva` step logger classes to ensure intercompatibility with :class:`~trainer.Trainer`. Attributes: @@ -116,16 +116,18 @@ class MinervaStepLogger(ABC): Defaults to ``False``. writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wandb_run.Run): Optional; Writer object from :mod:`tensorboard`, a :mod:`wandb` :class:`~wandb.sdk.wandb_run.Run` object or ``None``. + + .. versionadded:: 0.27 """ __metaclass__ = abc.ABCMeta def __init__( self, + task_name: str, n_batches: int, batch_size: int, - n_samples: int, - task_name: str, + output_size: int, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -135,8 +137,14 @@ def __init__( self.record_int = record_int self.record_float = record_float self.n_batches = n_batches + self.output_size = output_size self.batch_size = batch_size - self.n_samples = n_samples + + if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover + self.batch_size = batch_size // dist.get_world_size() # type: ignore[attr-defined] + + self.n_samples = self.batch_size * self.n_batches + self.task_name = task_name self.writer = writer @@ -276,15 +284,16 @@ class SupervisedGeoStepLogger(MinervaStepLogger): MemoryError: If trying to allocate memory to hold the probabilites of predictions from the model exceeds capacity. MemoryError: If trying to allocate memory to hold the bounding boxes of samples would exceed capacity. + + .. versionadded:: 0.27 """ def __init__( self, + task_name: str, n_batches: int, batch_size: int, - n_samples: int, - task_name: str, - out_shape: Union[int, Tuple[int, ...]], + output_size: Tuple[int, int], n_classes: int, record_int: bool = True, record_float: bool = False, @@ -292,20 +301,14 @@ def __init__( **kwargs, ) -> None: super(SupervisedGeoStepLogger, self).__init__( + task_name, n_batches, batch_size, - n_samples, - task_name, + output_size, record_int, record_float, writer, ) - _out_shape: Tuple[int, ...] - - if isinstance(out_shape, int): - _out_shape = (out_shape,) - else: - _out_shape = out_shape self.logs: Dict[str, Any] = { "batch_num": 0, @@ -331,7 +334,7 @@ def __init__( if kwargs.get("model_type") == "scene classifier": int_log_shape = (self.n_batches, self.batch_size) else: - int_log_shape = (self.n_batches, self.batch_size, *_out_shape) + int_log_shape = (self.n_batches, self.batch_size, *self.output_size) self.results["z"] = np.empty(int_log_shape, dtype=np.uint8) self.results["y"] = np.empty(int_log_shape, dtype=np.uint8) @@ -346,7 +349,7 @@ def __init__( self.n_batches, self.batch_size, n_classes, - *_out_shape, + *self.output_size, ) try: @@ -473,27 +476,27 @@ class KNNStepLogger(MinervaStepLogger): Defaults to ``False``. writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wand_run.Run): Optional; Writer object from :mod:`tensorboard`, a :mod:`wandb` :class:`~wandb.sdk.wandb_run.Run` object or ``None``. + + .. versionadded:: 0.27 """ def __init__( self, + task_name: str, n_batches: int, batch_size: int, - n_samples: int, - task_name: str, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: super().__init__( + task_name, n_batches, batch_size, - n_samples, - task_name, - record_int, - record_float, - writer, + record_int=record_int, + record_float=record_float, + writer=writer, **kwargs, ) @@ -578,29 +581,28 @@ class SSLStepLogger(MinervaStepLogger): Defaults to ``False``. writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wand_run.Run): Optional; Writer object from :mod:`tensorboard`, a :mod:`wandb` :class:`~wandb.sdk.wandb_run.Run` object or ``None``. + + .. versionadded:: 0.27 """ def __init__( self, + task_name: str, n_batches: int, batch_size: int, - n_samples: int, - task_name: str, - out_shape: Optional[Tuple[int, ...]] = None, - n_classes: Optional[int] = None, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, **kwargs, ) -> None: super(SSLStepLogger, self).__init__( + task_name, n_batches, batch_size, - n_samples, - task_name, - record_int, + record_int=record_int, record_float=record_float, writer=writer, + **kwargs, ) self.logs: Dict[str, Any] = { @@ -714,11 +716,13 @@ def log( # METHODS # ===================================================================================================================== def get_logger(name) -> Callable[..., Any]: - """Creates an object to log the results from each step of model fitting during an epoch. + """Gets the constructor for a step logger to log the results from each step of model fitting during an epoch. Returns: - ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logger.MinervaLogger` + ~typing.Callable[..., ~typing.Any]: The constructor of :class:`~logging.step.log.MinervaStepLogger` to be intialised within the epoch. + + .. versionadded:: 0.27 """ - logger: Callable[..., Any] = func_by_str("minerva.logger", name) + logger: Callable[..., Any] = func_by_str("minerva.logging.steplog", name) return logger diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index d15956b82..61516a561 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -68,7 +68,7 @@ class MinervaTaskLogger(ABC): Attributes: n_batches (dict[str, int]): Dictionary of the number of batches in each mode of fitting. batch_size (int): Batch size. - data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. + output_size (tuple[int, int]): Shape of the output data in ``H x W``. metrics (dict[str, ~typing.Any]): Dictionary to hold the metrics to assess the model with for each mode of fitting. model_type (str): Type of the model. @@ -78,6 +78,8 @@ class MinervaTaskLogger(ABC): batch_size (int): Batch size. data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. logger_params (dict[str, ~typing.Any]): Optional; Parameters for a logger other than the default for these metrics. + + .. versionadded:: 0.27 """ __metaclass__ = abc.ABCMeta @@ -88,11 +90,11 @@ class MinervaTaskLogger(ABC): def __init__( self, + task_name: str, n_batches: int, batch_size: int, - data_size: Tuple[int, int, int], - task_name: str, - logger_params: Optional[Dict[str, Any]] = None, + output_size: Tuple[int, int], + step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -103,30 +105,27 @@ def __init__( self.n_batches = n_batches self.batch_size = batch_size self.n_samples = self.n_batches * self.batch_size - self.data_size = data_size + self.output_size = output_size self.task_name = task_name + self.record_int = record_int + self.record_float = record_float + self.model_type = params.get("model_type", "scene_classifier") self.sample_pairs = params.get("sample_pairs", False) self.writer = writer - if logger_params: - if logger_params.get("name", None) is not None: - self.logger_cls = get_logger(logger_params["name"]) + if step_logger_params: + if step_logger_params.get("name", None) is not None: + self.logger_cls = get_logger(step_logger_params["name"]) else: - logger_params = {} + step_logger_params = {} - self.logger = self.logger_cls( - self.n_batches, - self.batch_size, - self.n_samples, - record_int, - record_float, - self.writer, - **logger_params["params"], - ) + self.step_logger_params = step_logger_params + + self._make_logger() if self.sample_pairs: self.metric_types += self.special_metric_types @@ -136,6 +135,22 @@ def __init__( for metric in self.metric_types: self.metrics[f"{self.task_name}_{metric}"] = {"x": [], "y": []} + def _make_logger(self) -> None: + """Builds and sets the logger. + + .. note:: + Will overwrite ``self.logger`` with new logger. + """ + self.step_logger = self.logger_cls( + self.n_batches, + self.batch_size, + self.n_samples, + self.record_int, + self.record_float, + self.writer, + **self.step_logger_params["params"], + ) + def step( self, step_num: int, @@ -159,7 +174,7 @@ def step( Returns: None """ - self.logger.log( + self.step_logger.log( step_num, loss, z, @@ -171,7 +186,7 @@ def step( def calc_metrics(self) -> None: """Updates metrics with epoch results.""" - self._calc_metrics(self.logger.get_logs) + self._calc_metrics(self.step_logger.get_logs) @abc.abstractmethod def _calc_metrics(self, logs: Dict[str, Any]) -> None: @@ -209,7 +224,7 @@ def get_logs(self) -> Dict[str, Any]: Returns: dict[str, ~typing.Any]: Logs per step of last epoch. """ - return self.logger.get_logs + return self.step_logger.get_logs def get_sub_metrics( self, pattern: Tuple[str, ...] = ("train", "val") @@ -258,6 +273,8 @@ class SupervisedTaskLogger(MinervaTaskLogger): batch_size (int): Batch size. data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. model_type (str): Optional; Type of the model. + + .. versionadded:: 0.27 """ metric_types: List[str] = ["loss", "acc", "miou"] @@ -265,11 +282,11 @@ class SupervisedTaskLogger(MinervaTaskLogger): def __init__( self, + task_name: str, n_batches: int, batch_size: int, - data_size: Tuple[int, int, int], - task_name: str, - logger_params: Optional[Dict[str, Any]] = None, + output_size: Tuple[int, int], + step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -277,22 +294,22 @@ def __init__( **params, ) -> None: super(SupervisedTaskLogger, self).__init__( + task_name, n_batches, batch_size, - data_size, - task_name, - logger_params, + output_size, + step_logger_params, record_int, record_float, writer, model_type=model_type, + **params, ) def _calc_metrics(self, logs: Dict[str, Any]) -> None: """Updates metrics with epoch results. Args: - mode (str): Mode of model fitting. logs (dict[str, ~typing.Any]): Logs of the results from the epoch of fitting to calculate metrics from. """ self.metrics[f"{self.task_name}_loss"]["y"].append( @@ -366,6 +383,8 @@ class SSLTaskLogger(MinervaTaskLogger): batch_size (int): Batch size. data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. model_type (str): Optional; Type of the model. + + .. versionadded:: 0.27 """ metric_types = ["loss", "acc", "top5_acc"] @@ -374,11 +393,11 @@ class SSLTaskLogger(MinervaTaskLogger): def __init__( self, + task_name: str, n_batches: int, batch_size: int, - data_size: Tuple[int, int, int], - task_name: str, - logger_params: Optional[Dict[str, Any]] = None, + output_size: Tuple[int, int], + step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -387,16 +406,17 @@ def __init__( **params, ) -> None: super(SSLTaskLogger, self).__init__( + task_name, n_batches, batch_size, - data_size, - task_name, - logger_params, + output_size, + step_logger_params, record_int, record_float, writer, model_type=model_type, sample_pairs=sample_pairs, + **params, ) def _calc_metrics(self, logs: Dict[str, Any]) -> None: @@ -415,8 +435,8 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: / ( self.n_batches * self.batch_size - * self.data_size[1] - * self.data_size[2] + * self.output_size[0] + * self.output_size[1] ) ) self.metrics[f"{self.task_name}_top5_acc"]["y"].append( @@ -424,8 +444,8 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: / ( self.n_batches * self.batch_size - * self.data_size[1] - * self.data_size[2] + * self.output_size[0] + * self.output_size[1] ) ) From d920bfaed9c5892ff656e559279673ae54ea44da Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 17:58:03 +0100 Subject: [PATCH 042/136] Updated tests for `steplog.py` --- minerva/logging/steplog.py | 5 ++ .../test_steplog.py} | 49 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) rename tests/{test_logger.py => test_logging/test_steplog.py} (91%) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index b362fc92a..6dbfc7418 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -60,11 +60,14 @@ import mlflow import numpy as np import torch +import torch.distributed as dist from sklearn.metrics import jaccard_score from torch import Tensor if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter +else: # pragma: no cover + SummaryWriter = None from torchgeo.datasets.utils import BoundingBox from wandb.sdk.wandb_run import Run @@ -590,6 +593,7 @@ def __init__( task_name: str, n_batches: int, batch_size: int, + output_size: Tuple[int, int], record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, @@ -599,6 +603,7 @@ def __init__( task_name, n_batches, batch_size, + output_size, record_int=record_int, record_float=record_float, writer=writer, diff --git a/tests/test_logger.py b/tests/test_logging/test_steplog.py similarity index 91% rename from tests/test_logger.py rename to tests/test_logging/test_steplog.py index 5d8d647fa..e2cedaf65 100644 --- a/tests/test_logger.py +++ b/tests/test_logging/test_steplog.py @@ -59,7 +59,7 @@ from torch.nn.modules import Module from torchgeo.datasets.utils import BoundingBox -from minerva.logger import SSLLogger, STGLogger +from minerva.logging.steplog import SSLStepLogger, SupervisedGeoStepLogger from minerva.loss import SegBarlowTwinsLoss from minerva.modelio import ssl_pair_tg, sup_tg from minerva.models import FCN16ResNet18, MinervaSiamese, SimCLR18, SimConv @@ -69,9 +69,9 @@ # ===================================================================================================================== # TESTS # ===================================================================================================================== -@pytest.mark.parametrize("mode", ("train", "val", "test")) +@pytest.mark.parametrize("train", (True, False)) @pytest.mark.parametrize("model_type", ("scene_classifier", "segmentation")) -def test_STGLogger( +def test_SupervisedGeoStepLogger( simple_bbox: BoundingBox, x_entropy_loss, std_n_batches: int, @@ -79,7 +79,7 @@ def test_STGLogger( std_batch_size: int, small_patch_size: Tuple[int, int], default_device: torch.device, - mode: str, + train: bool, model_type: str, ) -> None: path = Path(tempfile.gettempdir(), "exp1") @@ -107,14 +107,11 @@ def test_STGLogger( output_shape = model.output_shape assert isinstance(output_shape, tuple) - logger = STGLogger( + logger = SupervisedGeoStepLogger( + task_name="pytest", n_batches=std_n_batches, batch_size=std_batch_size, - n_samples=std_n_batches - * std_batch_size - * small_patch_size[0] - * small_patch_size[1], - out_shape=output_shape, + output_size=output_shape, n_classes=std_n_classes, record_int=True, record_float=True, @@ -135,7 +132,7 @@ def test_STGLogger( } data.append(batch) - logger(mode, i, *sup_tg(batch, model, device=default_device, mode=mode)) + logger(i, *sup_tg(batch, model, device=default_device, train=train)) logs = logger.get_logs assert logs["batch_num"] == std_n_batches @@ -179,9 +176,9 @@ def test_STGLogger( (SimConv, "siamese-segmentation", SegBarlowTwinsLoss()), ), ) -@pytest.mark.parametrize("mode", ("train", "val", "test")) +@pytest.mark.parametrize("train", (True, False)) @pytest.mark.parametrize("extra_metrics", (True, False)) -def test_SSLLogger( +def test_SSLStepLogger( simple_bbox: BoundingBox, std_n_batches: int, std_batch_size: int, @@ -190,7 +187,7 @@ def test_SSLLogger( model_cls: MinervaSiamese, model_type: str, criterion: Module, - mode: str, + train: bool, extra_metrics: bool, ) -> None: path = Path(tempfile.gettempdir(), "exp2") @@ -214,31 +211,31 @@ def test_SSLLogger( optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) model.set_optimiser(optimiser) - logger = SSLLogger( + model.determine_output_dim(sample_pairs=True) + output_shape = model.output_shape + assert isinstance(output_shape, tuple) + + logger = SSLStepLogger( + task_name="pytest", n_batches=std_n_batches, batch_size=std_batch_size, - n_samples=std_n_batches * std_batch_size, + output_size=output_shape, record_int=True, record_float=True, - collapse_level=extra_metrics, - euclidean=extra_metrics, writer=writer, model_type=model_type, + collapse_level=extra_metrics, + euclidean=extra_metrics, ) - data = [] + for i in range(std_n_batches): images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) bboxes = [simple_bbox] * std_batch_size - batch = { - "image": images, - "bbox": bboxes, - } - data.append((batch, batch)) + batch = {"image": images, "bbox": bboxes} logger( - mode, i, - *ssl_pair_tg((batch, batch), model, device=default_device, mode=mode), + *ssl_pair_tg((batch, batch), model, device=default_device, train=train), ) logs = logger.get_logs From ee66edf9ee50154d268385e126eb34a01b4e7153 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 20:11:27 +0100 Subject: [PATCH 043/136] Made `model_type` an arg --- minerva/logging/steplog.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index 6dbfc7418..7618f497f 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -134,6 +134,7 @@ def __init__( record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, + model_type: str = "", **kwargs, ) -> None: super(MinervaStepLogger, self).__init__() @@ -151,6 +152,8 @@ def __init__( self.task_name = task_name self.writer = writer + self.model_type = model_type + self.logs: Dict[str, Any] = {} self.results: Dict[str, Any] = {} @@ -297,10 +300,11 @@ def __init__( n_batches: int, batch_size: int, output_size: Tuple[int, int], - n_classes: int, record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, + model_type: str = "", + n_classes: Optional[int] = None, **kwargs, ) -> None: super(SupervisedGeoStepLogger, self).__init__( @@ -311,7 +315,10 @@ def __init__( record_int, record_float, writer, + model_type, ) + if n_classes is None: + raise (ValueError, "`n_classes` must be specified for this type of logger!") self.logs: Dict[str, Any] = { "batch_num": 0, @@ -326,7 +333,7 @@ def __init__( "ids": [], "bounds": None, } - self.calc_miou = True if kwargs.get("model_type") == "segmentation" else False + self.calc_miou = True if self.model_type == "segmentation" else False if self.calc_miou: self.logs["total_miou"] = 0.0 @@ -334,7 +341,7 @@ def __init__( # Allocate memory for the integer values to be recorded. if self.record_int: int_log_shape: Tuple[int, ...] - if kwargs.get("model_type") == "scene classifier": + if self.model_type == "scene classifier": int_log_shape = (self.n_batches, self.batch_size) else: int_log_shape = (self.n_batches, self.batch_size, *self.output_size) @@ -384,7 +391,6 @@ def log( """Logs the outputs and results from a step of model fitting. Overwrites abstract method. Args: - mode (str): Mode of model fitting. step_num (int): The global step number of for the mode of model fitting. loss (~torch.Tensor): Loss from this step of model fitting. z (~torch.Tensor): Output tensor from the model. @@ -491,6 +497,7 @@ def __init__( record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, + model_type: str = "", **kwargs, ) -> None: super().__init__( @@ -500,6 +507,7 @@ def __init__( record_int=record_int, record_float=record_float, writer=writer, + model_type=model_type, **kwargs, ) @@ -597,6 +605,7 @@ def __init__( record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, + model_type: str = "scene_classifier", **kwargs, ) -> None: super(SSLStepLogger, self).__init__( @@ -607,6 +616,7 @@ def __init__( record_int=record_int, record_float=record_float, writer=writer, + model_type=model_type, **kwargs, ) @@ -622,8 +632,6 @@ def __init__( self.collapse_level = kwargs.get("collapse_level", False) self.euclidean = kwargs.get("euclidean", False) - self.model_type = kwargs.get("model_type", "") - if self.collapse_level: self.logs["collapse_level"] = 0 if self.euclidean: From d97bee0782a0350bf71ce7ab3daa3946d6e2b57c Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 20:12:00 +0100 Subject: [PATCH 044/136] Fixed bugs --- minerva/logging/tasklog.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index 61516a561..cdc0ee5dd 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -46,6 +46,8 @@ if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter +else: # pragma: no cover + SummaryWriter = None from torch import Tensor from torchgeo.datasets.utils import BoundingBox @@ -142,13 +144,15 @@ def _make_logger(self) -> None: Will overwrite ``self.logger`` with new logger. """ self.step_logger = self.logger_cls( + self.task_name, self.n_batches, self.batch_size, - self.n_samples, + self.output_size, self.record_int, self.record_float, self.writer, - **self.step_logger_params["params"], + self.model_type, + **self.step_logger_params.get("params", {}), ) def step( @@ -223,9 +227,22 @@ def get_logs(self) -> Dict[str, Any]: Returns: dict[str, ~typing.Any]: Logs per step of last epoch. + + .. versionadded:: 0.27 """ return self.step_logger.get_logs + @property + def get_results(self) -> Dict[str, Any]: + """Get the results of each step from the latest epoch of the task. + + Returns: + dict[str, ~typing.Any]: Logs per step of last epoch. + + .. versionadded:: 0.27 + """ + return self.step_logger.get_results + def get_sub_metrics( self, pattern: Tuple[str, ...] = ("train", "val") ) -> Dict[str, Any]: @@ -322,8 +339,8 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: / ( self.n_batches * self.batch_size - * self.data_size[1] - * self.data_size[2] + * self.output_size[0] + * self.output_size[1] ) ) if logs.get("total_miou") is not None: From ce0757b3a2c5a29d454103c510adbc9cc791559c Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 20:13:15 +0100 Subject: [PATCH 045/136] Removed disused imports --- minerva/trainer.py | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/minerva/trainer.py b/minerva/trainer.py index e900631e8..cad1fe024 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -41,17 +41,7 @@ import os from copy import deepcopy from pathlib import Path -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Dict, - Iterable, - Optional, - Sequence, - Tuple, - Union, -) +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Sequence, Tuple, Union import pandas as pd import torch @@ -61,7 +51,6 @@ from torch import Tensor from torch.nn.modules import Module from torch.nn.parallel import DistributedDataParallel as DDP -from torch.utils.data import DataLoader if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter @@ -70,8 +59,6 @@ from wandb.sdk.lib import RunDisabled from wandb.sdk.wandb_run import Run -from minerva.datasets import make_loaders -from minerva.metrics import MinervaMetrics from minerva.models import ( MinervaBackbone, MinervaDataParallel, @@ -250,11 +237,6 @@ def __init__( ) -> None: assert not isinstance(wandb_run, RunDisabled) - # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. - # loaders, n_batches, class_dist, new_params = make_loaders( - # rank, world_size, **params - # ) - # Sets the global GPU number for distributed computing. In single process, this will just be 0. self.gpu: int = gpu self.rank = rank @@ -274,9 +256,6 @@ def __init__( utils.print_config(dict(params)) self.params: Dict[str, Any] = dict(params) - # self.class_dist = class_dist - # self.loaders: Dict[str, DataLoader[Iterable[Any]]] = loaders - # self.n_batches = n_batches self.batch_size: int = self.params["batch_size"] self.model_type: str = self.params["model_type"] self.val_freq: int = self.params.get("val_freq", 1) @@ -354,15 +333,6 @@ def __init__( **self.params["stopping"], ) - # Calculates number of samples in each mode of fitting. - # self.n_samples = { - # mode: self.n_batches[mode] * self.batch_size for mode in self.modes - # } - - # Initialise the metric logger and model IO for the experiment. - # self.metric_logger = self.make_metric_logger() - # self.modelio_func = self.get_io_func() - # Stores the step number for that mode of fitting. To be used for logging. self.step_num = {mode: 0 for mode in self.modes} From 78060496cfa9577ee50f2a07e0731f016944c2d9 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 20:13:44 +0100 Subject: [PATCH 046/136] Added (blank) test modules for `tasks` --- tests/test_tasks/test_epoch.py | 0 tests/test_tasks/test_knn.py | 0 tests/test_tasks/test_tasks_core.py | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/test_tasks/test_epoch.py create mode 100644 tests/test_tasks/test_knn.py create mode 100644 tests/test_tasks/test_tasks_core.py diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_tasks/test_knn.py b/tests/test_tasks/test_knn.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/test_tasks/test_tasks_core.py b/tests/test_tasks/test_tasks_core.py new file mode 100644 index 000000000..e69de29bb From 1a0c23a5c0446835c12ec6b0eba7edfb6545dc30 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 26 Sep 2023 20:49:26 +0100 Subject: [PATCH 047/136] Merged logging tests into `test_logging` --- minerva/logging/steplog.py | 6 +- tests/test_logging.py | 361 +++++++++++++++++++++++++++++ tests/test_logging/test_steplog.py | 254 -------------------- tests/test_metrics.py | 254 -------------------- 4 files changed, 364 insertions(+), 511 deletions(-) create mode 100644 tests/test_logging.py delete mode 100644 tests/test_logging/test_steplog.py delete mode 100644 tests/test_metrics.py diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index 7618f497f..bb739c913 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -73,7 +73,7 @@ from wandb.sdk.wandb_run import Run from minerva.utils import utils -from minerva.utils.utils import func_by_str +from minerva.utils.utils import check_substrings_in_string, func_by_str # ===================================================================================================================== # GLOBALS @@ -341,7 +341,7 @@ def __init__( # Allocate memory for the integer values to be recorded. if self.record_int: int_log_shape: Tuple[int, ...] - if self.model_type == "scene classifier": + if check_substrings_in_string(self.model_type, "scene classifier"): int_log_shape = (self.n_batches, self.batch_size) else: int_log_shape = (self.n_batches, self.batch_size, *self.output_size) @@ -352,7 +352,7 @@ def __init__( # Allocate memory for the floating point values to be recorded. if self.record_float: float_log_shape: Tuple[int, ...] - if kwargs.get("model_type") == "scene classifier": + if check_substrings_in_string(self.model_type, "scene classifier"): float_log_shape = (self.n_batches, self.batch_size, n_classes) else: float_log_shape = ( diff --git a/tests/test_logging.py b/tests/test_logging.py new file mode 100644 index 000000000..f236ad3d7 --- /dev/null +++ b/tests/test_logging.py @@ -0,0 +1,361 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +r"""Tests for :mod:`minerva.logging`. +""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +import importlib +import shutil +import tempfile +from pathlib import Path + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +from typing import Any, Dict, List, Tuple, Union + +import numpy as np +import torch +from urllib3.exceptions import MaxRetryError, NewConnectionError + +# Needed to avoid connection error when importing lightly. +try: + from lightly.loss import NTXentLoss +except (OSError, NewConnectionError, MaxRetryError): + NTXentLoss = getattr(importlib.import_module("lightly.loss"), "NTXentLoss") +import pytest +from nptyping import NDArray, Shape +from numpy.testing import assert_array_equal +from torch import Tensor +from torch.nn.modules import Module +from torchgeo.datasets.utils import BoundingBox + +from minerva.logging.tasklog import SSLTaskLogger, SupervisedTaskLogger +from minerva.loss import SegBarlowTwinsLoss +from minerva.modelio import ssl_pair_tg, sup_tg +from minerva.models import FCN16ResNet18, MinervaSiamese, SimCLR18, SimConv +from minerva.utils import utils + +n_epochs = 2 + + +# ===================================================================================================================== +# TESTS +# ===================================================================================================================== +@pytest.mark.parametrize("train", (True, False)) +@pytest.mark.parametrize("model_type", ("scene_classifier", "segmentation")) +def test_SupervisedGeoStepLogger( + simple_bbox: BoundingBox, + x_entropy_loss, + std_n_batches: int, + std_n_classes: int, + std_batch_size: int, + small_patch_size: Tuple[int, int], + default_device: torch.device, + train: bool, + model_type: str, +) -> None: + path = Path(tempfile.gettempdir(), "exp1") + + if not path.exists(): + path.mkdir() + + try: + tensorboard_writer = utils._optional_import( + "torch.utils.tensorboard.writer", name="SummaryWriter", package="tensorflow" + ) + except ImportError as err: + print(err) + writer = None + else: + writer = tensorboard_writer(log_dir=path) + + model = FCN16ResNet18(x_entropy_loss, input_size=(4, *small_patch_size)).to( + default_device + ) + optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) + model.set_optimiser(optimiser) + model.determine_output_dim() + + output_shape = model.output_shape + assert isinstance(output_shape, tuple) + + logger = SupervisedTaskLogger( + task_name="pytest", + n_batches=std_n_batches, + batch_size=std_batch_size, + output_size=output_shape, + n_classes=std_n_classes, + record_int=True, + record_float=True, + writer=writer, + model_type=model_type, + step_logger_params={"params": {"n_classes": std_n_classes}}, + ) + + correct_loss = {"x": [], "y": []} + correct_acc = {"x": [], "y": []} + correct_miou = {"x": [], "y": []} + + for epoch_no in range(n_epochs): + print(f"{epoch_no=}") + data: List[Dict[str, Union[Tensor, List[Any]]]] = [] + for i in range(std_n_batches): + images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) + masks = torch.randint( # type: ignore[attr-defined] + 0, std_n_classes, (std_batch_size, *small_patch_size) + ) + bboxes = [simple_bbox] * std_batch_size + batch: Dict[str, Union[Tensor, List[Any]]] = { + "image": images, + "mask": masks, + "bbox": bboxes, + } + data.append(batch) + + logger.step(i, *sup_tg(batch, model, device=default_device, train=train)) + + logs = logger.get_logs + assert logs["batch_num"] == std_n_batches + assert type(logs["total_loss"]) is float + assert type(logs["total_correct"]) is float + + if model_type == "segmentation": + assert type(logs["total_miou"]) is float + + results = logger.get_results + assert results["z"].shape == ( + std_n_batches, + std_batch_size, + *small_patch_size, + ) + assert results["y"].shape == ( + std_n_batches, + std_batch_size, + *small_patch_size, + ) + assert np.array(results["ids"]).shape == (std_n_batches, std_batch_size) + + shape = f"{std_n_batches}, {std_batch_size}, {small_patch_size[0]}, {small_patch_size[1]}" + y: NDArray[Shape[shape], Any] = np.empty( + (std_n_batches, std_batch_size, *output_shape), dtype=np.uint8 + ) + for i in range(std_n_batches): + mask: Union[Tensor, List[Any]] = data[i]["mask"] + assert isinstance(mask, Tensor) + y[i] = mask.cpu().numpy() + + assert_array_equal(results["y"], y) + + correct_loss["x"].append(epoch_no + 1) + correct_loss["y"].append(logs["total_loss"] / std_n_batches) + + correct_acc["x"].append(epoch_no + 1) + if utils.check_substrings_in_string(model_type, "segmentation"): + correct_acc["y"].append( + logs["total_correct"] + / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + ) + else: + correct_acc["y"].append( + logs["total_correct"] / (std_n_batches * std_batch_size) + ) + + if utils.check_substrings_in_string(model_type, "segmentation"): + correct_miou["x"].append(epoch_no + 1) + correct_miou["y"].append( + logs["total_miou"] / (std_n_batches * std_batch_size) + ) + + logger.calc_metrics() + logger.log_epoch_number(epoch_no) + logger.print_epoch_results(epoch_no) + + metrics = logger.get_metrics + + assert metrics[f"pytest_loss"] == pytest.approx(correct_loss) + assert metrics[f"pytest_acc"] == pytest.approx(correct_acc) + + if model_type == "segmentation": + assert metrics[f"pytest_miou"] == pytest.approx(correct_miou) + + logger._make_logger() + + shutil.rmtree(path, ignore_errors=True) + + +@pytest.mark.parametrize( + ("model_cls", "model_type", "criterion"), + ( + (SimCLR18, "siamese", NTXentLoss()), + (SimConv, "siamese-segmentation", SegBarlowTwinsLoss()), + ), +) +@pytest.mark.parametrize("train", (True, False)) +@pytest.mark.parametrize("extra_metrics", (True, False)) +def test_SSLStepLogger( + simple_bbox: BoundingBox, + std_n_batches: int, + std_batch_size: int, + small_patch_size: Tuple[int, int], + default_device: torch.device, + model_cls: MinervaSiamese, + model_type: str, + criterion: Module, + train: bool, + extra_metrics: bool, +) -> None: + path = Path(tempfile.gettempdir(), "exp2") + + if not path.exists(): + path.mkdir() + + try: + tensorboard_writer = utils._optional_import( + "torch.utils.tensorboard.writer", name="SummaryWriter", package="tensorflow" + ) + except ImportError as err: + print(err) + writer = None + else: + writer = tensorboard_writer(log_dir=path) + + model: MinervaSiamese = model_cls(criterion, input_size=(4, *small_patch_size)).to( + default_device + ) + optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) + model.set_optimiser(optimiser) + + model.determine_output_dim(sample_pairs=True) + output_shape = model.output_shape + assert isinstance(output_shape, tuple) + + logger = SSLTaskLogger( + task_name="pytest", + n_batches=std_n_batches, + batch_size=std_batch_size, + output_size=output_shape, + record_int=True, + record_float=True, + writer=writer, + model_type=model_type, + sample_pairs=True, + step_logger_params={ + "params": { + "collapse_level": extra_metrics, + "euclidean": extra_metrics, + "sample_pairs": True, + } + }, + ) + + correct_loss = {"x": [], "y": []} + correct_acc = {"x": [], "y": []} + correct_top5 = {"x": [], "y": []} + correct_collapse_level = {"x": [], "y": []} + correct_euc_dist = {"x": [], "y": []} + + for epoch_no in range(n_epochs): + for i in range(std_n_batches): + images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) + bboxes = [simple_bbox] * std_batch_size + batch = {"image": images, "bbox": bboxes} + + logger.step( + i, + *ssl_pair_tg((batch, batch), model, device=default_device, train=train), + ) + + logs = logger.get_logs + assert logs["batch_num"] == std_n_batches + assert type(logs["total_loss"]) is float + assert type(logs["total_correct"]) is float + assert type(logs["total_top5"]) is float + + if extra_metrics: + assert type(logs["collapse_level"]) is float + assert type(logs["euc_dist"]) is float + + results = logger.get_results + assert results == {} + + correct_loss["x"].append(epoch_no + 1) + correct_acc["x"].append(epoch_no + 1) + correct_top5["x"].append(epoch_no + 1) + + correct_loss["y"].append(logs["total_loss"] / std_n_batches) + + if utils.check_substrings_in_string(model_type, "segmentation"): + correct_acc["y"].append( + logs["total_correct"] + / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + ) + correct_top5["y"].append( + logs["total_top5"] + / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + ) + + else: + correct_acc["y"].append( + logs["total_correct"] / (std_n_batches * std_batch_size) + ) + correct_top5["y"].append( + logs["total_top5"] / (std_n_batches * std_batch_size) + ) + + if extra_metrics: + correct_collapse_level["x"].append(epoch_no + 1) + correct_euc_dist["x"].append(epoch_no + 1) + correct_collapse_level["y"].append(logs["collapse_level"]) + correct_euc_dist["y"].append(logs["euc_dist"] / std_n_batches) + + logger.calc_metrics() + logger.log_epoch_number(epoch_no) + logger.print_epoch_results(epoch_no) + + metrics = logger.get_metrics + + print(metrics) + print(correct_loss) + print(correct_acc) + + assert metrics[f"pytest_loss"] == pytest.approx(correct_loss) + assert metrics[f"pytest_acc"] == pytest.approx(correct_acc) + assert metrics[f"pytest_top5_acc"] == pytest.approx(correct_top5) + + if extra_metrics: + assert metrics[f"pytest_collapse_level"] == pytest.approx( + correct_collapse_level + ) + assert metrics[f"pytest_euc_dist"] == pytest.approx(correct_euc_dist) + + shutil.rmtree(path, ignore_errors=True) diff --git a/tests/test_logging/test_steplog.py b/tests/test_logging/test_steplog.py deleted file mode 100644 index e2cedaf65..000000000 --- a/tests/test_logging/test_steplog.py +++ /dev/null @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- -# MIT License - -# Copyright (c) 2023 Harry Baker - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# @org: University of Southampton -# Created under a project funded by the Ordnance Survey Ltd. -r"""Tests for :mod:`minerva.logger`. -""" -# ===================================================================================================================== -# METADATA -# ===================================================================================================================== -__author__ = "Harry Baker" -__contact__ = "hjb1d20@soton.ac.uk" -__license__ = "MIT License" -__copyright__ = "Copyright (C) 2023 Harry Baker" - -import importlib -import shutil -import tempfile -from pathlib import Path - -# ===================================================================================================================== -# IMPORTS -# ===================================================================================================================== -from typing import Any, Dict, List, Tuple, Union - -import numpy as np -import torch -from urllib3.exceptions import MaxRetryError, NewConnectionError - -# Needed to avoid connection error when importing lightly. -try: - from lightly.loss import NTXentLoss -except (OSError, NewConnectionError, MaxRetryError): - NTXentLoss = getattr(importlib.import_module("lightly.loss"), "NTXentLoss") -import pytest -from nptyping import NDArray, Shape -from numpy.testing import assert_array_equal -from torch import Tensor -from torch.nn.modules import Module -from torchgeo.datasets.utils import BoundingBox - -from minerva.logging.steplog import SSLStepLogger, SupervisedGeoStepLogger -from minerva.loss import SegBarlowTwinsLoss -from minerva.modelio import ssl_pair_tg, sup_tg -from minerva.models import FCN16ResNet18, MinervaSiamese, SimCLR18, SimConv -from minerva.utils import utils - - -# ===================================================================================================================== -# TESTS -# ===================================================================================================================== -@pytest.mark.parametrize("train", (True, False)) -@pytest.mark.parametrize("model_type", ("scene_classifier", "segmentation")) -def test_SupervisedGeoStepLogger( - simple_bbox: BoundingBox, - x_entropy_loss, - std_n_batches: int, - std_n_classes: int, - std_batch_size: int, - small_patch_size: Tuple[int, int], - default_device: torch.device, - train: bool, - model_type: str, -) -> None: - path = Path(tempfile.gettempdir(), "exp1") - - if not path.exists(): - path.mkdir() - - try: - tensorboard_writer = utils._optional_import( - "torch.utils.tensorboard.writer", name="SummaryWriter", package="tensorflow" - ) - except ImportError as err: - print(err) - writer = None - else: - writer = tensorboard_writer(log_dir=path) - - model = FCN16ResNet18(x_entropy_loss, input_size=(4, *small_patch_size)).to( - default_device - ) - optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) - model.set_optimiser(optimiser) - model.determine_output_dim() - - output_shape = model.output_shape - assert isinstance(output_shape, tuple) - - logger = SupervisedGeoStepLogger( - task_name="pytest", - n_batches=std_n_batches, - batch_size=std_batch_size, - output_size=output_shape, - n_classes=std_n_classes, - record_int=True, - record_float=True, - model_type=model_type, - writer=writer, - ) - data: List[Dict[str, Union[Tensor, List[Any]]]] = [] - for i in range(std_n_batches): - images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) - masks = torch.randint( # type: ignore[attr-defined] - 0, std_n_classes, (std_batch_size, *small_patch_size) - ) - bboxes = [simple_bbox] * std_batch_size - batch: Dict[str, Union[Tensor, List[Any]]] = { - "image": images, - "mask": masks, - "bbox": bboxes, - } - data.append(batch) - - logger(i, *sup_tg(batch, model, device=default_device, train=train)) - - logs = logger.get_logs - assert logs["batch_num"] == std_n_batches - assert type(logs["total_loss"]) is float - assert type(logs["total_correct"]) is float - - if model_type == "segmentation": - assert type(logs["total_miou"]) is float - - results = logger.get_results - assert results["z"].shape == ( - std_n_batches, - std_batch_size, - *small_patch_size, - ) - assert results["y"].shape == ( - std_n_batches, - std_batch_size, - *small_patch_size, - ) - assert np.array(results["ids"]).shape == (std_n_batches, std_batch_size) - - shape = f"{std_n_batches}, {std_batch_size}, {small_patch_size[0]}, {small_patch_size[1]}" - y: NDArray[Shape[shape], Any] = np.empty( - (std_n_batches, std_batch_size, *output_shape), dtype=np.uint8 - ) - for i in range(std_n_batches): - mask: Union[Tensor, List[Any]] = data[i]["mask"] - assert isinstance(mask, Tensor) - y[i] = mask.cpu().numpy() - - assert_array_equal(results["y"], y) - - shutil.rmtree(path, ignore_errors=True) - - -@pytest.mark.parametrize( - ("model_cls", "model_type", "criterion"), - ( - (SimCLR18, "siamese", NTXentLoss()), - (SimConv, "siamese-segmentation", SegBarlowTwinsLoss()), - ), -) -@pytest.mark.parametrize("train", (True, False)) -@pytest.mark.parametrize("extra_metrics", (True, False)) -def test_SSLStepLogger( - simple_bbox: BoundingBox, - std_n_batches: int, - std_batch_size: int, - small_patch_size: Tuple[int, int], - default_device: torch.device, - model_cls: MinervaSiamese, - model_type: str, - criterion: Module, - train: bool, - extra_metrics: bool, -) -> None: - path = Path(tempfile.gettempdir(), "exp2") - - if not path.exists(): - path.mkdir() - - try: - tensorboard_writer = utils._optional_import( - "torch.utils.tensorboard.writer", name="SummaryWriter", package="tensorflow" - ) - except ImportError as err: - print(err) - writer = None - else: - writer = tensorboard_writer(log_dir=path) - - model: MinervaSiamese = model_cls(criterion, input_size=(4, *small_patch_size)).to( - default_device - ) - optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) - model.set_optimiser(optimiser) - - model.determine_output_dim(sample_pairs=True) - output_shape = model.output_shape - assert isinstance(output_shape, tuple) - - logger = SSLStepLogger( - task_name="pytest", - n_batches=std_n_batches, - batch_size=std_batch_size, - output_size=output_shape, - record_int=True, - record_float=True, - writer=writer, - model_type=model_type, - collapse_level=extra_metrics, - euclidean=extra_metrics, - ) - - for i in range(std_n_batches): - images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) - bboxes = [simple_bbox] * std_batch_size - batch = {"image": images, "bbox": bboxes} - - logger( - i, - *ssl_pair_tg((batch, batch), model, device=default_device, train=train), - ) - - logs = logger.get_logs - assert logs["batch_num"] == std_n_batches - assert type(logs["total_loss"]) is float - assert type(logs["total_correct"]) is float - assert type(logs["total_top5"]) is float - - if extra_metrics: - assert type(logs["collapse_level"]) is float - assert type(logs["euc_dist"]) is float - - results = logger.get_results - assert results == {} - - shutil.rmtree(path, ignore_errors=True) diff --git a/tests/test_metrics.py b/tests/test_metrics.py deleted file mode 100644 index c682182bf..000000000 --- a/tests/test_metrics.py +++ /dev/null @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- -# MIT License - -# Copyright (c) 2023 Harry Baker - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. -# -# @org: University of Southampton -# Created under a project funded by the Ordnance Survey Ltd. -r"""Tests for :mod:`minerva.metrics`. -""" -# ===================================================================================================================== -# METADATA -# ===================================================================================================================== -__author__ = "Harry Baker" -__contact__ = "hjb1d20@soton.ac.uk" -__license__ = "MIT License" -__copyright__ = "Copyright (C) 2023 Harry Baker" - -# ===================================================================================================================== -# IMPORTS -# ===================================================================================================================== -import random -from typing import Dict, List - -import pytest - -from minerva.metrics import MinervaMetrics, SPMetrics, SSLMetrics - - -# ===================================================================================================================== -# TESTS -# ===================================================================================================================== -def test_minervametrics() -> None: - assert issubclass(SPMetrics, MinervaMetrics) - - -def test_sp_metrics() -> None: - def get_random_logs() -> Dict[str, float]: - logs = { - "total_loss": random.random(), - "total_correct": random.random(), - "total_miou": random.random(), - } - - return logs - - n_epochs = 2 - - n_batches: Dict[str, int] = { - "train": 12, - "val": 4, - "test": 2, - } - - metric_loggers: List[MinervaMetrics] = [] - - metric_loggers.append( - SPMetrics(n_batches, 16, (4, 224, 224), model_type="segmentation") - ) - metric_loggers.append( - SPMetrics(n_batches, 16, (4, 224, 224), model_type="scene_classifier") - ) - - epochs = [k + 1 for k in range(n_epochs)] - - for mode in n_batches.keys(): - logs = [get_random_logs() for i in range(n_epochs)] - - correct_loss_1 = { - "x": epochs, - "y": [log["total_loss"] / n_batches[mode] for log in logs], - } - - correct_loss = [correct_loss_1, correct_loss_1] - - correct_acc = [ - { - "x": epochs, - "y": [ - log["total_correct"] / (n_batches[mode] * 16 * 224 * 224) - for log in logs - ], - }, - { - "x": epochs, - "y": [log["total_correct"] / (n_batches[mode] * 16) for log in logs], - }, - ] - - correct_miou = { - "x": epochs, - "y": [log["total_miou"] / (n_batches[mode] * 16) for log in logs], - } - - for i, metric_logger in enumerate(metric_loggers): - for j in range(len(logs)): - metric_logger(mode, logs[j]) - metric_logger.log_epoch_number(mode, j) - metric_logger.print_epoch_results(mode, j) - - metrics = metric_loggers[i].get_metrics - - assert metrics[f"{mode}_loss"] == pytest.approx(correct_loss[i]) - assert metrics[f"{mode}_acc"] == pytest.approx(correct_acc[i]) - - if i == 0: - assert metrics[f"{mode}_miou"] == pytest.approx(correct_miou) - - if mode in ("train", "val"): - sub_metrics = metric_logger.get_sub_metrics() - - assert sub_metrics[f"{mode}_loss"] == pytest.approx(correct_loss[i]) - assert sub_metrics[f"{mode}_acc"] == pytest.approx(correct_acc[i]) - - if i == 0: - assert sub_metrics[f"{mode}_miou"] == pytest.approx(correct_miou) - - -def test_ssl_metrics() -> None: - def get_random_logs() -> Dict[str, float]: - logs = { - "total_loss": random.random(), - "total_correct": random.random(), - "total_top5": random.random(), - "collapse_level": random.random(), - "euc_dist": random.random(), - } - - return logs - - n_epochs = 2 - - epochs = [k + 1 for k in range(n_epochs)] - - n_batches: Dict[str, int] = {"train": 12, "val": 4} - - metric_loggers: List[MinervaMetrics] = [] - metric_loggers.append( - SSLMetrics( - n_batches, 16, (4, 224, 224), model_type="segmentation", sample_pairs=True - ) - ) - metric_loggers.append( - SSLMetrics( - n_batches, - 16, - (4, 224, 224), - model_type="scene_classifier", - sample_pairs=True, - ) - ) - - for mode in n_batches.keys(): - logs = [get_random_logs(), get_random_logs()] - - correct_loss = { - "x": epochs, - "y": [log["total_loss"] / n_batches[mode] for log in logs], - } - - correct_acc = [] - correct_acc.append( - { - "x": epochs, - "y": [ - log["total_correct"] / (n_batches[mode] * 16 * 224 * 224) - for log in logs - ], - } - ) - - correct_acc.append( - { - "x": epochs, - "y": [log["total_correct"] / (n_batches[mode] * 16) for log in logs], - } - ) - - correct_top5 = [] - correct_top5.append( - { - "x": epochs, - "y": [ - log["total_top5"] / (n_batches[mode] * 16 * 224 * 224) - for log in logs - ], - } - ) - - correct_top5.append( - { - "x": epochs, - "y": [log["total_top5"] / (n_batches[mode] * 16) for log in logs], - } - ) - - correct_collapse_level = { - "x": epochs, - "y": [log["collapse_level"] for log in logs], - } - - correct_euc_dist = { - "x": epochs, - "y": [log["euc_dist"] / n_batches[mode] for log in logs], - } - - for i, metric_logger in enumerate(metric_loggers): - for j in range(len(logs)): - metric_logger(mode, logs[j]) - metric_logger.log_epoch_number(mode, j) - metric_logger.print_epoch_results(mode, j) - - metrics = metric_logger.get_metrics - - assert metrics[f"{mode}_loss"] == pytest.approx(correct_loss) - assert metrics[f"{mode}_acc"] == pytest.approx(correct_acc[i]) - assert metrics[f"{mode}_top5_acc"] == pytest.approx(correct_top5[i]) - - if mode == "train": - assert metrics[f"{mode}_collapse_level"] == pytest.approx( - correct_collapse_level - ) - assert metrics[f"{mode}_euc_dist"] == pytest.approx(correct_euc_dist) - - sub_metrics = metric_logger.get_sub_metrics() - - assert sub_metrics[f"{mode}_loss"] == pytest.approx(correct_loss) - assert sub_metrics[f"{mode}_acc"] == pytest.approx(correct_acc[i]) - assert sub_metrics[f"{mode}_top5_acc"] == pytest.approx(correct_top5[i]) - - if mode == "train": - assert sub_metrics[f"{mode}_collapse_level"] == pytest.approx( - correct_collapse_level - ) - assert sub_metrics[f"{mode}_euc_dist"] == pytest.approx( - correct_euc_dist - ) From 4d9eaf693f578fcb647823549e52b0673b9a2fe4 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 27 Sep 2023 01:35:48 +0100 Subject: [PATCH 048/136] Use `check_substrings_in_string` for `model_type` comparisons --- minerva/logging/steplog.py | 10 +++++++--- minerva/logging/tasklog.py | 24 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index bb739c913..461c13138 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -333,7 +333,11 @@ def __init__( "ids": [], "bounds": None, } - self.calc_miou = True if self.model_type == "segmentation" else False + self.calc_miou = ( + True + if check_substrings_in_string(self.model_type, "segmentation") + else False + ) if self.calc_miou: self.logs["total_miou"] = 0.0 @@ -605,7 +609,7 @@ def __init__( record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, - model_type: str = "scene_classifier", + model_type: str = "", **kwargs, ) -> None: super(SSLStepLogger, self).__init__( @@ -658,7 +662,7 @@ def log( """ assert z is not None - if "segmentation" in self.model_type: + if check_substrings_in_string(self.model_type, "segmentation"): z = z.flatten(1, -1) # Adds the loss for this step to the logs. diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index cdc0ee5dd..febb244a2 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -53,6 +53,8 @@ from torchgeo.datasets.utils import BoundingBox from wandb.sdk.wandb_run import Run +from minerva.utils.utils import check_substrings_in_string + from .steplog import ( MinervaStepLogger, SSLStepLogger, @@ -422,6 +424,16 @@ def __init__( sample_pairs: bool = False, **params, ) -> None: + if sample_pairs: + if not step_logger_params: + step_logger_params = {} + if "params" not in step_logger_params: + step_logger_params["params"] = {} + + step_logger_params["params"]["sample_pairs"] = sample_pairs + step_logger_params["params"]["collapse_level"] = sample_pairs + step_logger_params["params"]["euclidean"] = sample_pairs + super(SSLTaskLogger, self).__init__( task_name, n_batches, @@ -446,7 +458,17 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: logs["total_loss"] / self.n_batches ) - if self.model_type == "segmentation": + if check_substrings_in_string(self.model_type, "segmentation"): + print( + self.n_batches + * self.batch_size + * self.output_size[0] + * self.output_size[1] + ) + print(f"{self.n_batches=}") + print(f"{self.batch_size=}") + print(f"{self.output_size=}") + self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] / ( From 20cbb33bcd0b3d8319d7e4ed25be22e30a30033c Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 27 Sep 2023 01:36:13 +0100 Subject: [PATCH 049/136] Fixed bugs --- tests/test_logging.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/test_logging.py b/tests/test_logging.py index f236ad3d7..71d0dc99e 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -263,19 +263,12 @@ def test_SSLStepLogger( task_name="pytest", n_batches=std_n_batches, batch_size=std_batch_size, - output_size=output_shape, + output_size=small_patch_size, record_int=True, record_float=True, writer=writer, model_type=model_type, sample_pairs=True, - step_logger_params={ - "params": { - "collapse_level": extra_metrics, - "euclidean": extra_metrics, - "sample_pairs": True, - } - }, ) correct_loss = {"x": [], "y": []} @@ -315,6 +308,10 @@ def test_SSLStepLogger( correct_loss["y"].append(logs["total_loss"] / std_n_batches) if utils.check_substrings_in_string(model_type, "segmentation"): + print(std_n_batches * std_batch_size * np.prod(output_shape)) + print(f"{std_n_batches=}") + print(f"{std_batch_size=}") + print(f"{small_patch_size=}") correct_acc["y"].append( logs["total_correct"] / (std_n_batches * std_batch_size * np.prod(small_patch_size)) @@ -347,15 +344,21 @@ def test_SSLStepLogger( print(metrics) print(correct_loss) print(correct_acc) + print(correct_top5) assert metrics[f"pytest_loss"] == pytest.approx(correct_loss) assert metrics[f"pytest_acc"] == pytest.approx(correct_acc) assert metrics[f"pytest_top5_acc"] == pytest.approx(correct_top5) if extra_metrics: + print(correct_collapse_level) + print(correct_euc_dist) + assert metrics[f"pytest_collapse_level"] == pytest.approx( correct_collapse_level ) assert metrics[f"pytest_euc_dist"] == pytest.approx(correct_euc_dist) + logger._make_logger() + shutil.rmtree(path, ignore_errors=True) From 6fe0900bf09c907133102e196fbf893e2a0e3861 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 27 Sep 2023 18:55:12 +0100 Subject: [PATCH 050/136] Add `test_get_task` --- tests/test_tasks/test_tasks_core.py | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/tests/test_tasks/test_tasks_core.py b/tests/test_tasks/test_tasks_core.py index e69de29bb..19906e057 100644 --- a/tests/test_tasks/test_tasks_core.py +++ b/tests/test_tasks/test_tasks_core.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +r"""Tests for :mod:`minerva.tasks.core`.""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +import pytest + +from minerva.tasks import get_task + + +# ===================================================================================================================== +# TESTS +# ===================================================================================================================== +def test_get_task(): + with pytest.raises(TypeError): + _ = get_task("MinervaTask") From 8189891dba70f9f532cb0447b13de262144822ea Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 27 Sep 2023 18:55:56 +0100 Subject: [PATCH 051/136] `MinervaTask.__repr__` now includes the task name --- minerva/tasks/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index a40cedb25..2a092a5d3 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -265,7 +265,7 @@ def get_logs(self) -> Dict[str, Any]: return self.logger.get_logs def __repr__(self) -> str: - return self.__class__.__name__ + return f"{self.__class__.__name__}-{self.name}" # ===================================================================================================================== From 9e46559120ff7a2f6f2a126d672c729fbc8d29c8 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 27 Sep 2023 18:57:06 +0100 Subject: [PATCH 052/136] Attempting to add `test_standard_epoch` --- minerva/datasets/factory.py | 2 +- tests/test_datasets/test_factory.py | 4 +- tests/test_tasks/test_epoch.py | 66 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 5bfee23af..82365efbc 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -530,7 +530,7 @@ def get_manifest(manifest_path: Union[str, Path]) -> DataFrame: print(err) print("CONSTRUCTING MISSING MANIFEST") - mf_config = CONFIG.copy() + mf_config = CONFIG["tasks"]["fit"]["train"].copy() manifest = make_manifest(mf_config) diff --git a/tests/test_datasets/test_factory.py b/tests/test_datasets/test_factory.py index 8565b0611..aa2d012e8 100644 --- a/tests/test_datasets/test_factory.py +++ b/tests/test_datasets/test_factory.py @@ -171,7 +171,7 @@ def test_construct_dataloader( def test_make_loaders() -> None: - old_params = CONFIG.copy() + old_params = CONFIG["tasks"]["fit"].copy() mask_transforms = {"RandomHorizontalFlip": {"module": "torchvision.transforms"}} transform_params = { @@ -193,7 +193,7 @@ def test_make_loaders() -> None: loaders, n_batches, class_dist, params = mdt.make_loaders(**old_params) - for mode in ("train", "val", "test"): + for mode in ("train", "val"): assert isinstance(loaders[mode], DataLoader) assert type(n_batches[mode]) is int assert type(class_dist) is list diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index e69de29bb..8feb3ef2e 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +r"""Tests for :mod:`minerva.tasks.epoch`.""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +import pytest + +from minerva.tasks import MinervaTask, StandardEpoch +from minerva.utils import CONFIG, universal_path, utils + + +# ===================================================================================================================== +# TESTS +# ===================================================================================================================== +def test_standard_epoch(std_batch_size, default_device, exp_cnn): + exp_name = "{}_{}".format( + CONFIG["model_name"], utils.timestamp_now(fmt="%d-%m-%Y_%H%M") + ) + exp_fn = universal_path(CONFIG["dir"]["results"]) / exp_name / exp_name + task = StandardEpoch( + name="pytest", + model=exp_cnn, + batch_size=std_batch_size, + device=default_device, + exp_fn=exp_fn, + ) + + assert isinstance(task, MinervaTask) + + task.step() + + assert isinstance(task.get_logs, dict) + + assert repr(task) == "StandardEpoch-pytest" From c29670d9524b56547dc263a824c0976d7e1eb693 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 28 Sep 2023 13:27:02 +0100 Subject: [PATCH 053/136] Use `task_name` in `make_loaders` --- minerva/datasets/factory.py | 3 + minerva/inbuilt_cfgs/example_config.yml | 140 +++++++++++------------- minerva/tasks/core.py | 2 +- tests/test_tasks/test_epoch.py | 4 + 4 files changed, 73 insertions(+), 76 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 82365efbc..176d62daf 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -361,6 +361,7 @@ def make_loaders( rank: int = 0, world_size: int = 1, p_dist: bool = False, + task_name: Optional[str] = None, **params, ) -> Tuple[ Dict[str, DataLoader[Iterable[Any]]], @@ -375,6 +376,8 @@ def make_loaders( world_size (int): Total number of processes across all nodes. For use with :class:`~torch.nn.parallel.DistributedDataParallel`. p_dist (bool): Print to screen the distribution of classes within each dataset. + task_name (str): Optional; If specified, only create the loaders for this task, + overwriting experiment-wode parameters with those found in this task's params if found. Keyword Args: batch_size (int): Number of samples in each batch to be returned by the DataLoaders. diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 8048690f2..e75823ea2 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -69,14 +69,6 @@ wandb_log: true # Activates wandb logging. project: pytest # Define the project name for wandb. wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. -# ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: STGLogger -metrics: SPMetrics -model_io: sup_tg - -record_int: true # Store integer results in memory. -record_float: true # Store floating point results too. Beware memory overload! - # ---+ Collator +-------------------------------------------------------------- collator: module: torchgeo.datasets @@ -84,83 +76,81 @@ collator: # === TASKS =================================================================== tasks: - fit: - val_freq: 1 - train: - type: StandardEpoch - # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg - - # ---+ Dataset Parameters +---------------------------------------- - dataset_params: - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 120 - - image: - transforms: false - images_1: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - image2: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false + train: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + train: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 120 + + image: + transforms: false + images_1: module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 + name: TstImgDataset + root: NAIP params: res: 1.0 - val: - type: StandardEpoch - # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg - - # ---+ Dataset Parameters +---------------------------------------- - dataset_params: - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: false + image2: module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + val: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + val: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 tests: test: diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 2a092a5d3..e9f451432 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -168,7 +168,7 @@ def __init__( # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. loaders, n_batches, class_dist, new_params = make_loaders( - rank, world_size, **params + rank, world_size, task_name=name, **params ) self.exp_fn = exp_fn diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index 8feb3ef2e..ced5c87d6 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -49,12 +49,16 @@ def test_standard_epoch(std_batch_size, default_device, exp_cnn): CONFIG["model_name"], utils.timestamp_now(fmt="%d-%m-%Y_%H%M") ) exp_fn = universal_path(CONFIG["dir"]["results"]) / exp_name / exp_name + + params = CONFIG.copy() + task = StandardEpoch( name="pytest", model=exp_cnn, batch_size=std_batch_size, device=default_device, exp_fn=exp_fn, + **params, ) assert isinstance(task, MinervaTask) From 0cce9b35dbe4ab2cf59e81cc52886fc530ed8442 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 28 Sep 2023 19:06:29 +0100 Subject: [PATCH 054/136] `make_loaders` can now use `task_params` and `params` --- minerva/datasets/factory.py | 45 +++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 176d62daf..6b32a79e3 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -405,19 +405,29 @@ def make_loaders( * The class distribution of the entire dataset, sorted from largest to smallest class. * Unused and updated kwargs. """ + task_params = params + if task_name: + task_params[task_name] + # Gets out the parameters for the DataLoaders from params. - dataloader_params: Dict[Any, Any] = params["loader_params"] - dataset_params: Dict[str, Any] = params["dataset_params"] - batch_size: int = params["batch_size"] + dataloader_params: Dict[Any, Any] = task_params.get( + "loader_params", params["loader_params"] + ) + dataset_params: Dict[str, Any] = task_params.get( + "dataset_params", params["dataset_params"] + ) + batch_size: int = task_params.get("batch_size", params["batch_size"]) - model_type = params["model_type"] + model_type = task_params.get("model_type", params["model_type"]) class_dist: List[Tuple[int, int]] = [(0, 0)] new_classes: Dict[int, str] = {} new_colours: Dict[int, str] = {} forwards: Dict[int, int] = {} - sample_pairs: Union[bool, Any] = params.get("sample_pairs", False) + sample_pairs: Union[bool, Any] = task_params.get( + "sample_pairs", params.get("sample_pairs", False) + ) if not isinstance(sample_pairs, bool): sample_pairs = False @@ -429,7 +439,8 @@ def make_loaders( # Finds the empty classes and returns modified classes, a dict to convert between the old and new systems # and new colours. new_classes, forwards, new_colours = utils.load_data_specs( - class_dist=class_dist, elim=params.get("elim", False) + class_dist=class_dist, + elim=task_params.get("elim", params.get("elim", False)), ) # Inits dicts to hold the variables and lists for train, validation and test. @@ -437,9 +448,9 @@ def make_loaders( loaders = {} for mode in dataset_params.keys(): - if params.get("elim", False) and not utils.check_substrings_in_string( - model_type, "siamese" - ): + if task_params.get( + "elim", params.get("elim", False) + ) and not utils.check_substrings_in_string(model_type, "siamese"): class_transform = { "ClassTransform": { "module": "minerva.transforms", @@ -467,7 +478,7 @@ def make_loaders( sampler_params, dataloader_params, batch_size, - collator_params=params["collator"], + collator_params=task_params.get("collator", params["collator"]), rank=rank, world_size=world_size, sample_pairs=sample_pairs if mode == "train" else False, @@ -476,23 +487,23 @@ def make_loaders( if not utils.check_substrings_in_string(model_type, "siamese"): # Transform class dist if elimination of classes has occurred. - if params.get("elim", False): + if task_params.get("elim", params.get("elim", False)): class_dist = utils.class_dist_transform(class_dist, forwards) # Prints class distribution in a pretty text format using tabulate to stdout. if p_dist: utils.print_class_dist(class_dist) - params["n_classes"] = len(new_classes) + task_params["n_classes"] = len(new_classes) model_params = params["model_params"].get("params", {}) model_params["n_classes"] = len(new_classes) - params["model_params"]["params"] = model_params - params["classes"] = new_classes - params["colours"] = new_colours + task_params["model_params"]["params"] = model_params + task_params["classes"] = new_classes + task_params["colours"] = new_colours - params["max_pixel_value"] = IMAGERY_CONFIG["data_specs"]["max_value"] + task_params["max_pixel_value"] = IMAGERY_CONFIG["data_specs"]["max_value"] - return loaders, n_batches, class_dist, params + return loaders, n_batches, class_dist, task_params def get_manifest_path() -> str: From de936ff65ac54246139c465364873e611690586a Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 29 Sep 2023 17:03:43 +0100 Subject: [PATCH 055/136] Use `fallback_params` in `factory` --- minerva/datasets/factory.py | 64 ++++++++++++++++++++++--------------- minerva/utils/utils.py | 25 +++++++++++++++ 2 files changed, 64 insertions(+), 25 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 6b32a79e3..3aa795d91 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -406,41 +406,43 @@ def make_loaders( * Unused and updated kwargs. """ task_params = params - if task_name: - task_params[task_name] + if task_name is not None: + task_params = params["tasks"][task_name] # Gets out the parameters for the DataLoaders from params. - dataloader_params: Dict[Any, Any] = task_params.get( - "loader_params", params["loader_params"] + dataloader_params: Dict[Any, Any] = utils.fallback_params( + "loader_params", task_params, params ) - dataset_params: Dict[str, Any] = task_params.get( - "dataset_params", params["dataset_params"] + dataset_params: Dict[str, Any] = utils.fallback_params( + "dataset_params", task_params, params ) - batch_size: int = task_params.get("batch_size", params["batch_size"]) + batch_size: int = utils.fallback_params("batch_size", task_params, params) - model_type = task_params.get("model_type", params["model_type"]) + model_type = utils.fallback_params("model_type", task_params, params) class_dist: List[Tuple[int, int]] = [(0, 0)] new_classes: Dict[int, str] = {} new_colours: Dict[int, str] = {} forwards: Dict[int, int] = {} - sample_pairs: Union[bool, Any] = task_params.get( - "sample_pairs", params.get("sample_pairs", False) + sample_pairs: Union[bool, Any] = utils.fallback_params( + "sample_pairs", task_params, params, False ) if not isinstance(sample_pairs, bool): sample_pairs = False + elim = utils.fallback_params("elim", task_params, params, False) + if not utils.check_substrings_in_string(model_type, "siamese"): # Load manifest from cache for this dataset. - manifest = get_manifest(get_manifest_path()) + manifest = get_manifest(get_manifest_path(), task_name) class_dist = utils.modes_from_manifest(manifest) # Finds the empty classes and returns modified classes, a dict to convert between the old and new systems # and new colours. new_classes, forwards, new_colours = utils.load_data_specs( class_dist=class_dist, - elim=task_params.get("elim", params.get("elim", False)), + elim=elim, ) # Inits dicts to hold the variables and lists for train, validation and test. @@ -448,9 +450,7 @@ def make_loaders( loaders = {} for mode in dataset_params.keys(): - if task_params.get( - "elim", params.get("elim", False) - ) and not utils.check_substrings_in_string(model_type, "siamese"): + if elim and not utils.check_substrings_in_string(model_type, "siamese"): class_transform = { "ClassTransform": { "module": "minerva.transforms", @@ -478,7 +478,7 @@ def make_loaders( sampler_params, dataloader_params, batch_size, - collator_params=task_params.get("collator", params["collator"]), + collator_params=utils.fallback_params("collator", task_params, params), rank=rank, world_size=world_size, sample_pairs=sample_pairs if mode == "train" else False, @@ -487,7 +487,7 @@ def make_loaders( if not utils.check_substrings_in_string(model_type, "siamese"): # Transform class dist if elimination of classes has occurred. - if task_params.get("elim", params.get("elim", False)): + if elim: class_dist = utils.class_dist_transform(class_dist, forwards) # Prints class distribution in a pretty text format using tabulate to stdout. @@ -515,7 +515,9 @@ def get_manifest_path() -> str: return str(Path(CACHE_DIR, f"{utils.get_dataset_name()}_Manifest.csv")) -def get_manifest(manifest_path: Union[str, Path]) -> DataFrame: +def get_manifest( + manifest_path: Union[str, Path], task_name: Optional[str] = None +) -> DataFrame: """Attempts to return the :class:`~pandas.DataFrame` located at ``manifest_path``. If a ``csv`` file is not found at ``manifest_path``, the manifest is constructed from @@ -544,9 +546,9 @@ def get_manifest(manifest_path: Union[str, Path]) -> DataFrame: print(err) print("CONSTRUCTING MISSING MANIFEST") - mf_config = CONFIG["tasks"]["fit"]["train"].copy() + mf_config = CONFIG.copy() - manifest = make_manifest(mf_config) + manifest = make_manifest(mf_config, task_name) print(f"MANIFEST TO FILE -----> {manifest_path}") path = manifest_path.parent @@ -558,7 +560,9 @@ def get_manifest(manifest_path: Union[str, Path]) -> DataFrame: return manifest -def make_manifest(mf_config: Dict[Any, Any]) -> DataFrame: +def make_manifest( + mf_config: Dict[Any, Any], task_name: Optional[str] = None +) -> DataFrame: """Constructs a manifest of the dataset detailing each sample therein. The dataset to construct a manifest of is defined by the ``data_config`` value in the config. @@ -569,10 +573,20 @@ def make_manifest(mf_config: Dict[Any, Any]) -> DataFrame: Returns: ~pandas.DataFrame: The completed manifest as a :class:`~pandas.DataFrame`. """ - batch_size: int = mf_config["batch_size"] - loader_params: Dict[str, Any] = mf_config["loader_params"] - dataset_params: Dict[str, Any] = mf_config["dataset_params"] - collator_params: Dict[str, Any] = mf_config["collator"] + task_params = mf_config + if task_name is not None: + task_params = mf_config["tasks"][task_name] + + batch_size: int = utils.fallback_params("batch_size", task_params, mf_config) + loader_params: Dict[str, Any] = utils.fallback_params( + "loader_params", task_params, mf_config + ) + dataset_params: Dict[str, Any] = utils.fallback_params( + "dataset_params", task_params, mf_config + ) + collator_params: Dict[str, Any] = utils.fallback_params( + "collator_params", task_params, mf_config + ) # Ensure there are no errant `ClassTransform` transforms in the parameters from previous runs. # A `ClassTransform` can only be defined with a correct manifest so we cannot use an old one to diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 92d3141b4..dca9b3478 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -1928,3 +1928,28 @@ def calc_norm_euc_dist( euc_dist: float = distance.euclidean(a, b) / float(len(a)) return euc_dist + + +def fallback_params( + key: str, + params_a: Dict[str, Any], + params_b: Dict[str, Any], + fallback: Optional[Any] = None, +) -> Any: + """Search for a value associated with ``key`` from + + Args: + key (str): _description_ + params_a (dict[str, ~typing.Any]): _description_ + params_b (dict[str, ~typing.Any]): _description_ + fallback (~typing.Any): Optional; _description_. Defaults to None. + + Returns: + ~typing.Any: _description_ + """ + if key in params_a: + return params_a[key] + elif key in params_b: + return params_b[key] + else: + return fallback From c31f34a8d5df5ab01650be2dba96175727542b63 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 29 Sep 2023 17:04:05 +0100 Subject: [PATCH 056/136] `batch_size` from params --- minerva/tasks/core.py | 3 ++- tests/test_tasks/test_epoch.py | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index e9f451432..84beb585b 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -150,7 +150,6 @@ def __init__( self, name: str, model: Union[MinervaModel, MinervaDataParallel], - batch_size: int, device: torch.device, exp_fn: Path, train: bool = False, @@ -181,6 +180,8 @@ def __init__( self.params = new_params self.class_dist = class_dist + batch_size = self.params[name].get("batch_size", self.params["batch_size"]) + # Corrects the batch size if this is a distributed job to account for batches being split across devices. if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover self.batch_size = batch_size // dist.get_world_size() # type: ignore[attr-defined] diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index ced5c87d6..f23b1d181 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -44,7 +44,7 @@ # ===================================================================================================================== # TESTS # ===================================================================================================================== -def test_standard_epoch(std_batch_size, default_device, exp_cnn): +def test_standard_epoch(default_device, exp_cnn): exp_name = "{}_{}".format( CONFIG["model_name"], utils.timestamp_now(fmt="%d-%m-%Y_%H%M") ) @@ -53,9 +53,8 @@ def test_standard_epoch(std_batch_size, default_device, exp_cnn): params = CONFIG.copy() task = StandardEpoch( - name="pytest", + name="train", model=exp_cnn, - batch_size=std_batch_size, device=default_device, exp_fn=exp_fn, **params, From f0369d61ccca640d33a68b92a8e4318281f02d69 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 2 Oct 2023 01:13:03 +0100 Subject: [PATCH 057/136] Added default `modelio_cls` to tasks --- minerva/inbuilt_cfgs/example_config.yml | 12 ++++++------ minerva/tasks/core.py | 22 +++++++++++++++------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index e75823ea2..7b2d66ef1 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -79,9 +79,9 @@ tasks: train: type: StandardEpoch # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg + # logger: STGLogger + # metrics: SPMetrics + # model_io: sup_tg # ---+ Dataset Parameters +---------------------------------------- dataset_params: @@ -121,9 +121,9 @@ tasks: val: type: StandardEpoch # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg + # logger: STGLogger + # metrics: SPMetrics + # model_io: sup_tg # ---+ Dataset Parameters +---------------------------------------- dataset_params: diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 84beb585b..f9adb2c9a 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -54,8 +54,9 @@ from minerva.datasets import make_loaders from minerva.logging.tasklog import MinervaTaskLogger, SupervisedTaskLogger +from minerva.modelio import sup_tg from minerva.models import MinervaDataParallel, MinervaModel -from minerva.utils.utils import func_by_str +from minerva.utils.utils import fallback_params, func_by_str # ===================================================================================================================== @@ -145,6 +146,7 @@ class MinervaTask(ABC): """ logger_cls: MinervaTaskLogger = SupervisedTaskLogger + modelio_cls: Callable[..., Any] = sup_tg def __init__( self, @@ -180,11 +182,13 @@ def __init__( self.params = new_params self.class_dist = class_dist - batch_size = self.params[name].get("batch_size", self.params["batch_size"]) + self.batch_size = fallback_params( + "batch_size", params["tasks"][name], self.params + ) # Corrects the batch size if this is a distributed job to account for batches being split across devices. if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover - self.batch_size = batch_size // dist.get_world_size() # type: ignore[attr-defined] + self.batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] self.n_batches = n_batches self.model_type = self.params["model_type"] @@ -212,8 +216,10 @@ def make_logger(self) -> MinervaTaskLogger: """ # Gets constructor of the metric logger from name in the config. - self.logger_cls = func_by_str( - "minerva.logging.tasklog", self.params.get("logger", self.logger_cls) + self.logger_cls = ( + func_by_str("minerva.logging.tasklog", self.params["logger"]) + if "logger" in self.params + else self.logger_cls ) # Initialises the metric logger with arguments. @@ -238,8 +244,10 @@ def get_io_func(self) -> Callable[..., Any]: Returns: ~typing.Callable[..., ~typing.Any]: Model IO function requested from parameters. """ - io_func: Callable[..., Any] = func_by_str( - "minerva.modelio", self.params["model_io"] + io_func: Callable[..., Any] = ( + func_by_str("minerva.modelio", self.params["model_io"]) + if "modelio" in self.params + else self.modelio_cls ) return io_func From b8fac29191fc1dfba034e4865970908f7b5bf9b9 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 2 Oct 2023 01:14:37 +0100 Subject: [PATCH 058/136] Ensure `model_params` in `task_params` are updated --- minerva/datasets/factory.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 3aa795d91..1f80e448d 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -495,9 +495,14 @@ def make_loaders( utils.print_class_dist(class_dist) task_params["n_classes"] = len(new_classes) - model_params = params["model_params"].get("params", {}) + model_params = utils.fallback_params("model_params", task_params, params, {}) model_params["n_classes"] = len(new_classes) - task_params["model_params"]["params"] = model_params + + if "model_params" in task_params: + task_params["model_params"]["params"] = model_params + else: + task_params["model_params"] = {"params": model_params} + task_params["classes"] = new_classes task_params["colours"] = new_colours From b3013d037b7ff0803b8cdd60fa63ee411c2d99ea Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:02:01 +0100 Subject: [PATCH 059/136] Made `modelio` methods static --- minerva/modelio.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/minerva/modelio.py b/minerva/modelio.py index 3158005da..d09d8a571 100644 --- a/minerva/modelio.py +++ b/minerva/modelio.py @@ -53,6 +53,7 @@ # ===================================================================================================================== # METHODS # ===================================================================================================================== +@staticmethod def sup_tg( batch: Dict[Any, Any], model: MinervaModel, @@ -102,6 +103,7 @@ def sup_tg( return loss, z, y, bbox +@staticmethod def autoencoder_io( batch: Dict[Any, Any], model: MinervaModel, @@ -183,6 +185,7 @@ def autoencoder_io( return loss, z, y, bbox +@staticmethod def ssl_pair_tg( batch: Tuple[Dict[str, Any], Dict[str, Any]], model: MinervaModel, From 5fc1f616b7af89d90030271aed8df9f9ae83d7af Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:03:53 +0100 Subject: [PATCH 060/136] Assume single mode if "sampler" in first level of `dataset_params` --- minerva/datasets/factory.py | 76 +++++++++++---- minerva/inbuilt_cfgs/example_config.yml | 123 ++++++++++++------------ 2 files changed, 119 insertions(+), 80 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 1f80e448d..0bd387181 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -135,18 +135,20 @@ def create_subdataset( _transformations: Optional[Any], ) -> GeoDataset: copy_params = deepcopy(subdataset_params) + if "crs" in copy_params["params"]: copy_params["params"]["crs"] = CRS.from_epsg(copy_params["params"]["crs"]) + if sample_pairs: return PairedDataset( dataset_class, - root=root, + root, transforms=_transformations, **copy_params["params"], ) else: return dataset_class( - root=root, + root, transforms=_transformations, **copy_params["params"], ) @@ -364,8 +366,8 @@ def make_loaders( task_name: Optional[str] = None, **params, ) -> Tuple[ - Dict[str, DataLoader[Iterable[Any]]], - Dict[str, int], + Union[Dict[str, DataLoader[Iterable[Any]]], DataLoader[Iterable[Any]]], + Union[Dict[str, int], int], List[Tuple[int, int]], Dict[Any, Any], ]: @@ -445,11 +447,10 @@ def make_loaders( elim=elim, ) - # Inits dicts to hold the variables and lists for train, validation and test. - n_batches = {} - loaders = {} + n_batches: Union[Dict[str, int], int] + loaders: Union[Dict[str, DataLoader[Iterable[Any]]], DataLoader[Iterable[Any]]] - for mode in dataset_params.keys(): + if "sampler" in dataset_params.keys(): if elim and not utils.check_substrings_in_string(model_type, "siamese"): class_transform = { "ClassTransform": { @@ -458,33 +459,74 @@ def make_loaders( } } - if type(dataset_params[mode]["mask"].get("transforms")) != dict: - dataset_params[mode]["mask"]["transforms"] = class_transform + if type(dataset_params["mask"].get("transforms")) != dict: + dataset_params["mask"]["transforms"] = class_transform else: - dataset_params[mode]["mask"]["transforms"][ + dataset_params["mask"]["transforms"][ "ClassTransform" ] = class_transform["ClassTransform"] - sampler_params: Dict[str, Any] = dataset_params[mode]["sampler"] + sampler_params: Dict[str, Any] = dataset_params["sampler"] # Calculates number of batches. - n_batches[mode] = int(sampler_params["params"]["length"] / batch_size) + n_batches = int(sampler_params["params"]["length"] / batch_size) # --+ MAKE DATASETS +=========================================================================================+ - print(f"CREATING {mode} DATASET") - loaders[mode] = construct_dataloader( + print(f"CREATING {task_name} DATASET") + loaders = construct_dataloader( params["dir"]["data"], - dataset_params[mode], + dataset_params, sampler_params, dataloader_params, batch_size, collator_params=utils.fallback_params("collator", task_params, params), rank=rank, world_size=world_size, - sample_pairs=sample_pairs if mode == "train" else False, + sample_pairs=sample_pairs, ) print("DONE") + else: + # Inits dicts to hold the variables and lists for train, validation and test. + n_batches = {} + loaders = {} + + for mode in dataset_params.keys(): + if elim and not utils.check_substrings_in_string(model_type, "siamese"): + class_transform = { + "ClassTransform": { + "module": "minerva.transforms", + "transform": forwards, + } + } + + if type(dataset_params[mode]["mask"].get("transforms")) != dict: + dataset_params[mode]["mask"]["transforms"] = class_transform + else: + dataset_params[mode]["mask"]["transforms"][ + "ClassTransform" + ] = class_transform["ClassTransform"] + + sampler_params: Dict[str, Any] = dataset_params[mode]["sampler"] + + # Calculates number of batches. + n_batches[mode] = int(sampler_params["params"]["length"] / batch_size) + + # --+ MAKE DATASETS +=========================================================================================+ + print(f"CREATING {mode} DATASET") + loaders[mode] = construct_dataloader( + params["dir"]["data"], + dataset_params[mode], + sampler_params, + dataloader_params, + batch_size, + collator_params=utils.fallback_params("collator", task_params, params), + rank=rank, + world_size=world_size, + sample_pairs=sample_pairs if mode == "train" else False, + ) + print("DONE") + if not utils.check_substrings_in_string(model_type, "siamese"): # Transform class dist if elimination of classes has occurred. if elim: diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 7b2d66ef1..e55b152ef 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -85,39 +85,38 @@ tasks: # ---+ Dataset Parameters +---------------------------------------- dataset_params: - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 120 + + image: + transforms: false + images_1: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP params: - size: *patch_size - length: 120 - - image: - transforms: false - images_1: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - image2: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 + res: 1.0 - mask: - transforms: false + image2: module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 + name: TstImgDataset + root: NAIP params: res: 1.0 + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + val: type: StandardEpoch # ---+ Minerva Inbuilt Logging Functions +------------------------- @@ -127,7 +126,40 @@ tasks: # ---+ Dataset Parameters +---------------------------------------- dataset_params: - val: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + tests: + type: StandardEpoch + # ---+ Minerva Inbuilt Logging Functions +------------------------- + logger: STGLogger + metrics: SPMetrics + model_io: sup_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + test: sampler: module: torchgeo.samplers name: RandomGeoSampler @@ -152,41 +184,6 @@ tasks: params: res: 1.0 - tests: - test: - type: StandardEpoch - # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg - - # ---+ Dataset Parameters +---------------------------------------- - dataset_params: - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: false - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - # === PLOTTING OPTIONS ======================================================== plots: History: true # Plot of the training and validation metrics over epochs. From eb7c3768096e558bb30b04e571865762b27ea7b1 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:04:07 +0100 Subject: [PATCH 061/136] Fixed syntax error --- minerva/logging/steplog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/logging/steplog.py b/minerva/logging/steplog.py index 461c13138..588e18e22 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logging/steplog.py @@ -318,7 +318,7 @@ def __init__( model_type, ) if n_classes is None: - raise (ValueError, "`n_classes` must be specified for this type of logger!") + raise ValueError("`n_classes` must be specified for this type of logger!") self.logs: Dict[str, Any] = { "batch_num": 0, From 913094fbafbebf773ddf03902a8930493b735296 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:05:19 +0100 Subject: [PATCH 062/136] Added `n_classes` as optional arg --- minerva/logging/tasklog.py | 7 +++++-- minerva/tasks/core.py | 6 ++++-- minerva/tasks/epoch.py | 6 +++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index febb244a2..77e5455e2 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -117,15 +117,18 @@ def __init__( self.model_type = params.get("model_type", "scene_classifier") self.sample_pairs = params.get("sample_pairs", False) + self.n_classes = params.get("n_classes") self.writer = writer if step_logger_params: - if step_logger_params.get("name", None) is not None: + if step_logger_params.get("name") is not None: self.logger_cls = get_logger(step_logger_params["name"]) else: - step_logger_params = {} + step_logger_params = {"params": {}} + + step_logger_params["params"]["n_classes"] = self.n_classes self.step_logger_params = step_logger_params diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index f9adb2c9a..09c96929f 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -146,7 +146,7 @@ class MinervaTask(ABC): """ logger_cls: MinervaTaskLogger = SupervisedTaskLogger - modelio_cls: Callable[..., Any] = sup_tg + modelio: Callable[..., Any] = sup_tg def __init__( self, @@ -193,6 +193,7 @@ def __init__( self.n_batches = n_batches self.model_type = self.params["model_type"] self.sample_pairs = self.params.get("sample_pairs", False) + self.n_classes = self.params.get("n_classes") self.output_size = model.output_shape @@ -234,6 +235,7 @@ def make_logger(self) -> MinervaTaskLogger: writer=self.writer, model_type=self.model_type, sample_pairs=self.sample_pairs, + n_classes=self.n_classes, ) return logger @@ -247,7 +249,7 @@ def get_io_func(self) -> Callable[..., Any]: io_func: Callable[..., Any] = ( func_by_str("minerva.modelio", self.params["model_io"]) if "modelio" in self.params - else self.modelio_cls + else self.modelio ) return io_func diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index ee448b274..bbaaa7f4c 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -76,7 +76,11 @@ def step(self) -> None: # Core of the epoch. for batch in self.loaders: results = self.modelio( - batch, self.model, self.device, self.train, **self.params + batch, + self.model, + self.device, + self.train, + **self.params, ) if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover From 08500bb88f7dfb03b52a0fca80f0c24a94045225 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:09:09 +0100 Subject: [PATCH 063/136] Ensure `output_shape` is always a `tuple` --- minerva/models/core.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/minerva/models/core.py b/minerva/models/core.py index dea87b4a4..cb1c2c53b 100644 --- a/minerva/models/core.py +++ b/minerva/models/core.py @@ -89,7 +89,8 @@ class MinervaModel(Module, ABC): input_shape (tuple[int, ...]): Optional; Defines the shape of the input data. Typically in order of number of channels, image width, image height but may vary dependant on model specs. n_classes (int): Number of classes in input data. - output_shape: The shape of the output of the network. Determined and set by :meth:`determine_output_dim`. + output_shape (tuple[int, ...]): The shape of the output of the network. + Determined and set by :meth:`determine_output_dim`. optimiser: :mod:`torch` optimiser model will use, to be initialised with inherited model's parameters. Args: @@ -116,7 +117,7 @@ def __init__( self.n_classes = n_classes # Output shape initialised as None. Should be set by calling determine_output_dim. - self.output_shape: Optional[Union[int, Iterable[int]]] = None + self.output_shape: Optional[Tuple[int, ...]] = None # Optimiser initialised as None as the model parameters created by its init is required to init a # torch optimiser. The optimiser MUST be set by calling set_optimiser before the model can be trained. @@ -421,7 +422,7 @@ def get_output_shape( model: Module, image_dim: Union[Sequence[int], int], sample_pairs: bool = False, -) -> Union[int, Sequence[int]]: +) -> Tuple[int, ...]: """Gets the output shape of a model. Args: @@ -431,7 +432,7 @@ def get_output_shape( Will send a paired sample through the model. Returns: - int | ~typing.Sequence[int]: The shape of the output data from the model. + tuple[int, ...]: The shape of the output data from the model. """ _image_dim: Union[Sequence[int], int] = image_dim try: @@ -455,10 +456,10 @@ def get_output_shape( output: Tensor = model(random_input.to(next(model.parameters()).device)) if len(output[0].data.shape) == 1: - return output[0].data.shape[0] + return (output[0].data.shape[0],) else: - return output[0].data.shape[1:] + return tuple(output[0].data.shape[1:]) def bilinear_init(in_channels: int, out_channels: int, kernel_size: int) -> Tensor: From ca23945d5757715b0c2cb9fc9c1a1e6ab1e38ae8 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 2 Oct 2023 23:09:31 +0100 Subject: [PATCH 064/136] Setup model properly --- tests/test_tasks/test_epoch.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index f23b1d181..ccc7d69f5 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -35,8 +35,9 @@ # ===================================================================================================================== # IMPORTS # ===================================================================================================================== -import pytest +from torch.optim import SGD +from minerva.models import MinervaModel from minerva.tasks import MinervaTask, StandardEpoch from minerva.utils import CONFIG, universal_path, utils @@ -44,7 +45,12 @@ # ===================================================================================================================== # TESTS # ===================================================================================================================== -def test_standard_epoch(default_device, exp_cnn): +def test_standard_epoch(default_device, exp_cnn: MinervaModel): + exp_cnn.determine_output_dim() + optimiser = SGD(exp_cnn.parameters(), lr=1.0e-3) + exp_cnn.set_optimiser(optimiser) + exp_cnn.to(default_device) + exp_name = "{}_{}".format( CONFIG["model_name"], utils.timestamp_now(fmt="%d-%m-%Y_%H%M") ) From 23575cc70fed9763a6abed933bc35b0e2c456dc0 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 15:42:23 +0100 Subject: [PATCH 065/136] Fixed `test_depreciated` for tuple model output shape --- minerva/models/__depreciated.py | 10 +++------- tests/test_models/test_depreciated.py | 4 ++-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/minerva/models/__depreciated.py b/minerva/models/__depreciated.py index 1c0200582..60dd66259 100644 --- a/minerva/models/__depreciated.py +++ b/minerva/models/__depreciated.py @@ -217,13 +217,9 @@ def __init__( # Calculate the input of the Linear layer by sending some fake data through the network # and getting the shape of the output. - out_shape = get_output_shape(self.conv_net, self.input_size) - - if type(out_shape) is int: # pragma: no cover - self.flattened_size = out_shape - elif isinstance(out_shape, Iterable): - # Calculate the flattened size of the output from the convolutional network. - self.flattened_size = int(np.prod(list(out_shape))) + self.flattened_size = int( + np.prod(get_output_shape(self.conv_net, self.input_size)) + ) # Constructs the fully connected layers determined by the number of input channels and the features of these. for i in range(len(fc_sizes)): diff --git a/tests/test_models/test_depreciated.py b/tests/test_models/test_depreciated.py index cc5b76950..c8e28d31e 100644 --- a/tests/test_models/test_depreciated.py +++ b/tests/test_models/test_depreciated.py @@ -54,7 +54,7 @@ def test_mlp(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() - assert model.output_shape is model.n_classes + assert model.output_shape[0] is model.n_classes x = torch.rand(16, (288)) @@ -73,7 +73,7 @@ def test_cnn(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() - assert model.output_shape is model.n_classes + assert model.output_shape[0] is model.n_classes x = torch.rand(6, *input_size) y = torch.LongTensor(np.random.randint(0, 8, size=6)) From 73d61701118e067124ac575bb5f2d2843962997e Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 15:42:47 +0100 Subject: [PATCH 066/136] Added missing type hints --- tests/conftest.py | 49 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f1145c112..a92b1ac9e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -54,7 +54,7 @@ from torchgeo.datasets.utils import BoundingBox from minerva.datasets import SSL4EOS12Sentinel2, make_dataset -from minerva.models import CNN, MLP, MinervaModel +from minerva.models import CNN, MLP, FCN32ResNet18 from minerva.utils import CONFIG, utils @@ -160,7 +160,7 @@ def std_n_batches() -> int: @pytest.fixture -def x_entropy_loss(): +def x_entropy_loss() -> nn.CrossEntropyLoss: return nn.CrossEntropyLoss() @@ -171,33 +171,50 @@ def small_patch_size() -> Tuple[int, int]: @pytest.fixture def rgbi_input_size() -> Tuple[int, int, int]: - return (4, 64, 64) + return (4, 32, 32) @pytest.fixture -def exp_mlp(x_entropy_loss) -> MinervaModel: +def exp_mlp(x_entropy_loss: nn.CrossEntropyLoss) -> MLP: return MLP(x_entropy_loss, 64) @pytest.fixture -def exp_cnn(x_entropy_loss, rgbi_input_size) -> MinervaModel: +def exp_cnn( + x_entropy_loss: nn.CrossEntropyLoss, rgbi_input_size: Tuple[int, int, int] +) -> CNN: return CNN(x_entropy_loss, rgbi_input_size) @pytest.fixture -def random_mask(small_patch_size, std_n_classes) -> NDArray[Shape["32, 32"], Int]: +def exp_fcn( + x_entropy_loss: nn.CrossEntropyLoss, + rgbi_input_size: Tuple[int, int, int], + std_n_classes: int, +) -> FCN32ResNet18: + return FCN32ResNet18(x_entropy_loss, rgbi_input_size, std_n_classes) + + +@pytest.fixture +def random_mask( + small_patch_size: Tuple[int, int], std_n_classes: int +) -> NDArray[Shape["32, 32"], Int]: mask = np.random.randint(0, std_n_classes - 1, size=small_patch_size) assert isinstance(mask, np.ndarray) return mask @pytest.fixture -def random_image(small_patch_size) -> NDArray[Shape["32, 32, 3"], Float]: +def random_image( + small_patch_size: Tuple[int, int] +) -> NDArray[Shape["32, 32, 3"], Float]: return np.random.rand(*small_patch_size, 3) @pytest.fixture -def random_rgbi_image(small_patch_size) -> NDArray[Shape["32, 32, 4"], Float]: +def random_rgbi_image( + small_patch_size: Tuple[int, int] +) -> NDArray[Shape["32, 32, 4"], Float]: return np.random.rand(*small_patch_size, 4) @@ -216,7 +233,7 @@ def simple_rgb_img() -> Tensor: @pytest.fixture -def norm_simple_rgb_img(simple_rgb_img) -> Tensor: +def norm_simple_rgb_img(simple_rgb_img: Tensor) -> Tensor: norm_img = simple_rgb_img / 255 assert isinstance(norm_img, Tensor) return norm_img @@ -232,12 +249,14 @@ def flipped_rgb_img() -> Tensor: @pytest.fixture -def simple_sample(simple_rgb_img, simple_mask) -> Dict[str, Tensor]: +def simple_sample(simple_rgb_img: Tensor, simple_mask: LongTensor) -> Dict[str, Tensor]: return {"image": simple_rgb_img, "mask": simple_mask} @pytest.fixture -def flipped_simple_sample(flipped_rgb_img, flipped_simple_mask) -> Dict[str, Tensor]: +def flipped_simple_sample( + flipped_rgb_img: Tensor, flipped_simple_mask: LongTensor +) -> Dict[str, Tensor]: return {"image": flipped_rgb_img, "mask": flipped_simple_mask} @@ -249,7 +268,9 @@ def random_rgbi_batch( @pytest.fixture -def random_tensor_mask(std_n_classes: int, small_patch_size) -> LongTensor: +def random_tensor_mask( + std_n_classes: int, small_patch_size: Tuple[int, int] +) -> LongTensor: mask = torch.randint(0, std_n_classes - 1, size=small_patch_size, dtype=torch.long) assert isinstance(mask, LongTensor) return mask @@ -270,7 +291,9 @@ def random_mask_batch( @pytest.fixture -def random_scene_classification_batch(std_batch_size, std_n_classes) -> LongTensor: +def random_scene_classification_batch( + std_batch_size: int, std_n_classes: int +) -> LongTensor: batch = torch.randint(0, std_n_classes - 1, size=(std_batch_size,)) assert isinstance(batch, LongTensor) return batch From 1457945e9a195fdc3d9a2e218ea6270923e4ef07 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 15:43:03 +0100 Subject: [PATCH 067/136] Use `exp_fcn` fixture --- tests/test_tasks/test_epoch.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index ccc7d69f5..482452ebb 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -45,11 +45,11 @@ # ===================================================================================================================== # TESTS # ===================================================================================================================== -def test_standard_epoch(default_device, exp_cnn: MinervaModel): - exp_cnn.determine_output_dim() - optimiser = SGD(exp_cnn.parameters(), lr=1.0e-3) - exp_cnn.set_optimiser(optimiser) - exp_cnn.to(default_device) +def test_standard_epoch(default_device, exp_fcn: MinervaModel): + exp_fcn.determine_output_dim() + optimiser = SGD(exp_fcn.parameters(), lr=1.0e-3) + exp_fcn.set_optimiser(optimiser) + exp_fcn.to(default_device) exp_name = "{}_{}".format( CONFIG["model_name"], utils.timestamp_now(fmt="%d-%m-%Y_%H%M") @@ -60,7 +60,7 @@ def test_standard_epoch(default_device, exp_cnn: MinervaModel): task = StandardEpoch( name="train", - model=exp_cnn, + model=exp_fcn, device=default_device, exp_fn=exp_fn, **params, @@ -72,4 +72,4 @@ def test_standard_epoch(default_device, exp_cnn: MinervaModel): assert isinstance(task.get_logs, dict) - assert repr(task) == "StandardEpoch-pytest" + assert repr(task) == "StandardEpoch-train" From bda7902d93e5aa20892afa36e9c460760cb97660 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 16:57:03 +0100 Subject: [PATCH 068/136] Use fixtures, fix output shape assertions --- tests/test_models/test_core.py | 56 +++++++++++++++---------------- tests/test_models/test_resnets.py | 9 +++-- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/tests/test_models/test_core.py b/tests/test_models/test_core.py index d7600ba54..097667d63 100644 --- a/tests/test_models/test_core.py +++ b/tests/test_models/test_core.py @@ -37,6 +37,7 @@ # IMPORTS # ===================================================================================================================== import importlib +from typing import Tuple import internet_sabotage import numpy as np @@ -70,9 +71,9 @@ # ===================================================================================================================== # TESTS # ===================================================================================================================== -def test_minerva_model(x_entropy_loss) -> None: - x = torch.rand(16, (288)) - y = torch.LongTensor(np.random.randint(0, 8, size=16)) +def test_minerva_model(x_entropy_loss, std_n_classes: int, std_n_batches: int) -> None: + x = torch.rand(std_n_batches, (288)) + y = torch.LongTensor(np.random.randint(0, std_n_classes, size=std_n_batches)) with pytest.raises(NotImplementedError, match="Criterion has not been set!"): model_fail = MLP() @@ -91,37 +92,37 @@ def test_minerva_model(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() - assert model.output_shape is model.n_classes + assert model.output_shape[0] is model.n_classes - for mode in ("train", "val", "test"): - if mode == "train": - loss, z = model.step(x, y, train=True) - else: - loss, z = model.step(x, y, train=False) + for train in (True, False): + loss, z = model.step(x, y, train=train) assert type(loss.item()) is float assert isinstance(z, Tensor) - assert z.size() == (16, 8) + assert z.size() == (std_n_batches, std_n_classes) -def test_minerva_backbone() -> None: +def test_minerva_backbone(rgbi_input_size: Tuple[int, int, int]) -> None: loss_func = NTXentLoss(0.3) - input_size = (4, 64, 64) - model = SimCLR18(loss_func, input_size=input_size) + model = SimCLR18(loss_func, input_size=rgbi_input_size) assert isinstance(model.get_backbone(), Module) -def test_minerva_wrapper(x_entropy_loss) -> None: - input_size = (3, 32, 32) - n_classes = 8 +def test_minerva_wrapper( + x_entropy_loss, + small_patch_size: Tuple[int, int], + std_n_classes: int, + std_n_batches: int, +) -> None: + input_size = (3, *small_patch_size) model = MinervaWrapper( ResNetGenerator, x_entropy_loss, input_size=input_size, - n_classes=n_classes, - num_classes=n_classes, + n_classes=std_n_classes, + num_classes=std_n_classes, name="resnet-9", ) @@ -132,20 +133,17 @@ def test_minerva_wrapper(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() - assert model.output_shape is model.n_classes + assert model.output_shape[0] is model.n_classes - x = torch.rand(6, *input_size) - y = LongTensor(np.random.randint(0, 8, size=6)) + x = torch.rand(std_n_batches, *input_size) + y = LongTensor(np.random.randint(0, std_n_classes, size=std_n_batches)) - for mode in ("train", "val", "test"): - if mode == "train": - loss, z = model.step(x, y, train=True) - else: - loss, z = model.step(x, y, train=False) + for train in (True, False): + loss, z = model.step(x, y, train=train) assert type(loss.item()) is float assert isinstance(z, Tensor) - assert z.size() == (6, 8) + assert z.size() == (std_n_batches, std_n_classes) def test_get_torch_weights() -> None: @@ -170,10 +168,10 @@ def test_get_torch_weights() -> None: print(err) -def test_get_output_shape(exp_mlp) -> None: +def test_get_output_shape(exp_mlp, std_n_classes: int) -> None: output_shape = get_output_shape(exp_mlp, 64) - assert output_shape == 8 + assert output_shape == (std_n_classes,) def test_bilinear_init() -> None: diff --git a/tests/test_models/test_resnets.py b/tests/test_models/test_resnets.py index ff9325068..ab98162e3 100644 --- a/tests/test_models/test_resnets.py +++ b/tests/test_models/test_resnets.py @@ -65,7 +65,7 @@ def resnet_test( model.set_optimiser(optimiser) model.determine_output_dim() - assert model.output_shape is model.n_classes + assert model.output_shape[0] is model.n_classes loss, z = model.step(x, y, True) @@ -151,14 +151,13 @@ def test_resnet_encoder( encoder.set_optimiser(optimiser) encoder.determine_output_dim() - print(encoder.output_shape) - assert encoder.output_shape == (512, 2, 2) + assert encoder.output_shape == (512, 1, 1) assert len(encoder(random_rgbi_batch)) == 5 -def test_preload_weights() -> None: +def test_preload_weights(rgbi_input_size: Tuple[int, int, int]) -> None: resnet = ResNet(BasicBlock, [2, 2, 2, 2]) - new_resnet = _preload_weights(resnet, None, (4, 32, 32), encoder_on=False) + new_resnet = _preload_weights(resnet, None, rgbi_input_size, encoder_on=False) assert resnet == new_resnet From a5f2ca26a90b117017d664b031d5b7138bb52718 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 18:04:27 +0100 Subject: [PATCH 069/136] Fixed `make_manifest` for tasks --- minerva/datasets/factory.py | 57 +++++++++++++++++++---------- tests/test_datasets/test_factory.py | 2 +- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 0bd387181..119bad212 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -620,6 +620,13 @@ def make_manifest( Returns: ~pandas.DataFrame: The completed manifest as a :class:`~pandas.DataFrame`. """ + + def delete_class_transform(params: Dict[str, Any]) -> None: + if "transforms" in params["mask"]: + if isinstance(params["mask"]["transforms"], dict): + if "ClassTransform" in params["mask"]["transforms"]: + del params["mask"]["transforms"]["ClassTransform"] + task_params = mf_config if task_name is not None: task_params = mf_config["tasks"][task_name] @@ -638,25 +645,37 @@ def make_manifest( # Ensure there are no errant `ClassTransform` transforms in the parameters from previous runs. # A `ClassTransform` can only be defined with a correct manifest so we cannot use an old one to # sample the dataset. We need the original, un-transformed labels. - for mode in dataset_params.keys(): - if "transforms" in dataset_params[mode]["mask"]: - if isinstance(dataset_params[mode]["mask"]["transforms"], dict): - if "ClassTransform" in dataset_params[mode]["mask"]["transforms"]: - del dataset_params[mode]["mask"]["transforms"]["ClassTransform"] - - keys = list(dataset_params.keys()) - print("CONSTRUCTING DATASET") - - sampler_params = dataset_params[keys[0]]["sampler"] - - loader = construct_dataloader( - mf_config["dir"]["data"], - dataset_params[keys[0]], - sampler_params, - loader_params, - batch_size, - collator_params=collator_params, - ) + if "sampler" in dataset_params.keys(): + delete_class_transform(dataset_params) + sampler_params = dataset_params["sampler"] + + print("CONSTRUCTING DATASET") + + loader = construct_dataloader( + mf_config["dir"]["data"], + dataset_params, + sampler_params, + loader_params, + batch_size, + collator_params=collator_params, + ) + else: + for mode in dataset_params.keys(): + delete_class_transform(dataset_params[mode]) + + keys = list(dataset_params.keys()) + sampler_params = dataset_params[keys[0]]["sampler"] + + print("CONSTRUCTING DATASET") + + loader = construct_dataloader( + mf_config["dir"]["data"], + dataset_params[keys[0]], + sampler_params, + loader_params, + batch_size, + collator_params=collator_params, + ) print("FETCHING SAMPLES") df = DataFrame() diff --git a/tests/test_datasets/test_factory.py b/tests/test_datasets/test_factory.py index aa2d012e8..7f8164107 100644 --- a/tests/test_datasets/test_factory.py +++ b/tests/test_datasets/test_factory.py @@ -171,7 +171,7 @@ def test_construct_dataloader( def test_make_loaders() -> None: - old_params = CONFIG["tasks"]["fit"].copy() + old_params = CONFIG["tasks"].copy() mask_transforms = {"RandomHorizontalFlip": {"module": "torchvision.transforms"}} transform_params = { From 544fd0840fcb0dceb8189ec472d3a0cb4f49180f Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 3 Oct 2023 19:31:47 +0100 Subject: [PATCH 070/136] Fixed manifest making --- minerva/datasets/factory.py | 2 +- minerva/inbuilt_cfgs/exp_mf_config.yml | 57 +++++++++++------------- tests/test_datasets/test_factory.py | 60 +++++++++++++------------- 3 files changed, 55 insertions(+), 64 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 119bad212..76e29ad42 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -641,13 +641,13 @@ def delete_class_transform(params: Dict[str, Any]) -> None: collator_params: Dict[str, Any] = utils.fallback_params( "collator_params", task_params, mf_config ) + sampler_params = dataset_params["sampler"] # Ensure there are no errant `ClassTransform` transforms in the parameters from previous runs. # A `ClassTransform` can only be defined with a correct manifest so we cannot use an old one to # sample the dataset. We need the original, un-transformed labels. if "sampler" in dataset_params.keys(): delete_class_transform(dataset_params) - sampler_params = dataset_params["sampler"] print("CONSTRUCTING DATASET") diff --git a/minerva/inbuilt_cfgs/exp_mf_config.yml b/minerva/inbuilt_cfgs/exp_mf_config.yml index a93f9fa2a..5e572def6 100644 --- a/minerva/inbuilt_cfgs/exp_mf_config.yml +++ b/minerva/inbuilt_cfgs/exp_mf_config.yml @@ -3,43 +3,34 @@ # === PATHS =================================================================== dir: - data: - - tests - - fixtures - - data + data: tests/fixtures/data configs: data_config: minerva/inbuilt_cfgs/Chesapeake7.yml - output: - - tests - - tmp - - cache + output: tests/tmp/cache # === DATASET PARAMETERS ====================================================== -dataset_params: - make: - image: - module: minerva.datasets.__testing - name: TestImgDataset - root: NAIP - params: - res: 1.0 - mask: - module: minerva.datasets.__testing - name: TestMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - -# === SAMPLER PARAMETERS ====================================================== -sampler_params: - make: - module: torchgeo.samplers - name: GridGeoSampler - params: - size: [1000, 1000] - stride: [1000, 1000] - +tasks: + manifest: + dataset_params: + sampler: + module: torchgeo.samplers + name: GridGeoSampler + params: + size: [1000, 1000] + stride: [1000, 1000] + image: + module: minerva.datasets.__testing + name: TestImgDataset + root: NAIP + params: + res: 1.0 + mask: + module: minerva.datasets.__testing + name: TestMaskDataset + root: Chesapeake7 + params: + res: 1.0 +# Collator collator: module: torchgeo.datasets name: stack_samples diff --git a/tests/test_datasets/test_factory.py b/tests/test_datasets/test_factory.py index 7f8164107..ffb39454e 100644 --- a/tests/test_datasets/test_factory.py +++ b/tests/test_datasets/test_factory.py @@ -171,33 +171,34 @@ def test_construct_dataloader( def test_make_loaders() -> None: - old_params = CONFIG["tasks"].copy() - - mask_transforms = {"RandomHorizontalFlip": {"module": "torchvision.transforms"}} - transform_params = { - "train": { - "image": False, - "mask": mask_transforms, - }, - "val": { - "image": False, - "mask": mask_transforms, - }, - "test": { - "image": False, - "mask": False, - }, - } - - old_params["transform_params"] = transform_params - - loaders, n_batches, class_dist, params = mdt.make_loaders(**old_params) + old_params = CONFIG.copy() + + # mask_transforms = {"RandomHorizontalFlip": {"module": "torchvision.transforms"}} + # transform_params = { + # "train": { + # "image": False, + # "mask": mask_transforms, + # }, + # "val": { + # "image": False, + # "mask": mask_transforms, + # }, + # "test": { + # "image": False, + # "mask": False, + # }, + # } + + # old_params["transform_params"] = transform_params + + loader, n_batches, class_dist, params = mdt.make_loaders( + **old_params, task_name="val" + ) - for mode in ("train", "val"): - assert isinstance(loaders[mode], DataLoader) - assert type(n_batches[mode]) is int - assert type(class_dist) is list - assert isinstance(params, dict) + assert isinstance(loader, DataLoader) + assert type(n_batches) is int + assert type(class_dist) is list + assert isinstance(params, dict) def test_get_manifest_path() -> None: @@ -212,18 +213,17 @@ def test_get_manifest() -> None: if manifest_path.exists(): manifest_path.unlink() - assert isinstance(mdt.get_manifest(manifest_path), pd.DataFrame) - assert isinstance(mdt.get_manifest(manifest_path), pd.DataFrame) + assert isinstance(mdt.get_manifest(manifest_path, task_name="train"), pd.DataFrame) + assert isinstance(mdt.get_manifest(manifest_path, task_name="train"), pd.DataFrame) new_path = Path("tests", "tmp", "empty", "Chesapeake7_Manifest.csv") if new_path.exists(): - print("exists") new_path.unlink() if new_path.parent.exists(): new_path.parent.rmdir() - assert isinstance(mdt.get_manifest(new_path), pd.DataFrame) + assert isinstance(mdt.get_manifest(new_path, task_name="train"), pd.DataFrame) if new_path.exists(): new_path.unlink() From 767f8c47308ecafb64f29030865f090be8bea640 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Oct 2023 15:15:05 +0100 Subject: [PATCH 071/136] Added `refresh_step_logger` method --- minerva/logging/tasklog.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index 77e5455e2..b1b5b371d 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -149,17 +149,20 @@ def _make_logger(self) -> None: Will overwrite ``self.logger`` with new logger. """ self.step_logger = self.logger_cls( - self.task_name, - self.n_batches, - self.batch_size, - self.output_size, - self.record_int, - self.record_float, - self.writer, - self.model_type, + task_name=self.task_name, + n_batches=self.n_batches, + batch_size=self.batch_size, + output_size=self.output_size, + record_int=self.record_int, + record_float=self.record_float, + writer=self.writer, + model_type=self.model_type, **self.step_logger_params.get("params", {}), ) + def refresh_step_logger(self) -> None: + self._make_logger() + def step( self, step_num: int, From 7def636b393d26a76decb8fbb2e9f8642138a650 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Oct 2023 15:15:48 +0100 Subject: [PATCH 072/136] Added `set_criterion` method --- minerva/models/core.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/minerva/models/core.py b/minerva/models/core.py index cb1c2c53b..81467ab70 100644 --- a/minerva/models/core.py +++ b/minerva/models/core.py @@ -136,6 +136,14 @@ def set_optimiser(self, optimiser: Optimizer) -> None: """ self.optimiser = optimiser + def set_criterion(self, criterion: Module) -> None: + """Set the internal criterion. + + Args: + criterion (~torch.nn.Module): Criterion (loss function) to set. + """ + self.criterion = criterion + def determine_output_dim(self, sample_pairs: bool = False) -> None: """Uses :func:`get_output_shape` to find the dimensions of the output of this model and sets to attribute.""" From c457cc562c14028bda0484ad2de8f29287b8400c Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Oct 2023 15:16:22 +0100 Subject: [PATCH 073/136] Renamed `mode` --> `task_name` --- minerva/utils/visutils.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/minerva/utils/visutils.py b/minerva/utils/visutils.py index baa6b38e9..4439d36e7 100644 --- a/minerva/utils/visutils.py +++ b/minerva/utils/visutils.py @@ -739,7 +739,7 @@ def seg_plot( y: Union[List[int], NDArray[Any, Any]], ids: List[str], bounds: Union[Sequence[Any], NDArray[Any, Any]], - mode: str, + task_name: str, classes: Dict[int, str], colours: Dict[int, str], fn_prefix: Union[str, Path], @@ -755,7 +755,7 @@ def seg_plot( bounds (list[~torchgeo.datasets.utils.BoundingBox] | ~numpy.ndarray[~torchgeo.datasets.utils.BoundingBox]): Array of objects describing a geospatial bounding box. Must contain ``minx``, ``maxx``, ``miny`` and ``maxy`` parameters. - mode (str): Mode samples are from. Must be ``'train'``, ``'val'`` or ``'test'``. + task_name (str): Name of the task that samples are from. classes (dict[int, str]): Dictionary mapping class labels to class names. colours (dict[int, str]): Dictionary mapping class labels to colours. fn_prefix (str | ~pathlib.Path): Common filename prefix (including path to file) for all plots of this type @@ -781,7 +781,9 @@ def seg_plot( flat_ids: NDArray[Any, Any] = np.array(ids).flatten() print("\nRE-CONSTRUCTING DATASET") - dataset, _ = make_dataset(CONFIG["dir"]["data"], CONFIG["dataset_params"][mode]) + dataset, _ = make_dataset( + CONFIG["dir"]["data"], CONFIG["tasks"][task_name]["dataset_params"] + ) # Create a new projection system in lat-lon. crs = dataset.crs @@ -1248,7 +1250,7 @@ def plot_results( y: Optional[Union[List[int], NDArray[Any, Int]]] = None, metrics: Optional[Dict[str, Any]] = None, ids: Optional[List[str]] = None, - mode: str = "test", + task_name: str = "test", bounds: Optional[NDArray[Any, Any]] = None, probs: Optional[Union[List[float], NDArray[Any, Float]]] = None, embeddings: Optional[NDArray[Any, Any]] = None, @@ -1270,7 +1272,7 @@ def plot_results( the performance of a model. ids (list[str]): Optional; List of IDs defining the origin of samples to the model. Maybe either patch IDs or scene tags. - mode (str): Optional; Mode samples are from. Must be ``'train'``, ``'val'`` or ``'test'``. + task_name (str): Optional; Name of task that samples are from. bounds (~numpy.ndarray[~torchgeo.datasets.utils.BoundingBox]): Optional; Array of objects describing a geospatial bounding box for each sample. Must contain ``minx``, ``maxx``, ``miny`` and ``maxy`` parameters. @@ -1388,7 +1390,7 @@ def plot_results( assert y is not None assert ids is not None assert bounds is not None - assert mode is not None + assert task_name is not None figsize = None if DATA_CONFIG is not None: @@ -1401,7 +1403,7 @@ def plot_results( y, ids, flat_bbox, - mode, + task_name, fn_prefix=filenames["Mask"], classes=class_names, colours=colours, @@ -1411,13 +1413,13 @@ def plot_results( if plots.get("TSNE", False): assert embeddings is not None assert bounds is not None - assert mode is not None + assert task_name is not None print("\nPERFORMING TSNE CLUSTERING") plot_embedding( embeddings, bounds, - mode, + task_name, show=show, save=save, filename=filenames["TSNE"], From 4860b7d9b375236d144c7a5361b7b2a2368ffb6f Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Oct 2023 15:17:28 +0100 Subject: [PATCH 074/136] `Trainer.fit` now works --- minerva/inbuilt_cfgs/example_config.yml | 16 ++-- minerva/tasks/core.py | 109 ++++++++++++++++++---- minerva/trainer.py | 118 +++++++++++------------- tests/test_trainer.py | 3 +- 4 files changed, 158 insertions(+), 88 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index e55b152ef..3688b2971 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -34,11 +34,10 @@ n_classes: &n_classes 8 # Number of classes in dataset. max_epochs: 5 # Maximum number of training epochs. pre_train: false # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. -elim: true # Eliminates empty classes from schema. -balance: true # Balances dataset classes. +elim: false # Eliminates empty classes from schema. +balance: false # Balances dataset classes. -# ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: CrossEntropyLoss # Name of the loss function to use. +# ---+ Optimisers +--------------------------------------------------- lr: 1.0E-2 # Learning rate of optimiser. optim_func: SGD # Name of the optimiser function. @@ -56,6 +55,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: CrossEntropyLoss # Name of the loss function to use. params: # ---+ Dataloader Parameters +------------------------------------------------- @@ -76,8 +76,10 @@ collator: # === TASKS =================================================================== tasks: - train: + fit-train: type: StandardEpoch + train: true + record_float: true # ---+ Minerva Inbuilt Logging Functions +------------------------- # logger: STGLogger # metrics: SPMetrics @@ -117,8 +119,10 @@ tasks: params: res: 1.0 - val: + fit-val: type: StandardEpoch + train: false + record_float: true # ---+ Minerva Inbuilt Logging Functions +------------------------- # logger: STGLogger # metrics: SPMetrics diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 09c96929f..97c8bf337 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -50,12 +50,14 @@ import torch import torch.distributed as dist +from torch import Tensor from wandb.sdk.wandb_run import Run from minerva.datasets import make_loaders from minerva.logging.tasklog import MinervaTaskLogger, SupervisedTaskLogger from minerva.modelio import sup_tg from minerva.models import MinervaDataParallel, MinervaModel +from minerva.utils import utils from minerva.utils.utils import fallback_params, func_by_str @@ -154,14 +156,14 @@ def __init__( model: Union[MinervaModel, MinervaDataParallel], device: torch.device, exp_fn: Path, - train: bool = False, gpu: int = 0, rank: int = 0, world_size: int = 1, writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, record_float: bool = False, - **params, + train: bool = False, + **global_params, ) -> None: self.name = name @@ -169,21 +171,27 @@ def __init__( # Gets the datasets, number of batches, class distribution and the modfied parameters for the experiment. loaders, n_batches, class_dist, new_params = make_loaders( - rank, world_size, task_name=name, **params + rank, world_size, task_name=name, **global_params ) + global_params["tasks"][name] = new_params + + self.global_params = global_params + self.params = new_params + + print(new_params["classes"]) self.exp_fn = exp_fn self.train = train + del self.params["train"] self.gpu = gpu self.loaders = loaders - self.params = new_params self.class_dist = class_dist self.batch_size = fallback_params( - "batch_size", params["tasks"][name], self.params + "batch_size", self.global_params["tasks"][name], self.params ) # Corrects the batch size if this is a distributed job to account for batches being split across devices. @@ -191,14 +199,20 @@ def __init__( self.batch_size = self.batch_size // dist.get_world_size() # type: ignore[attr-defined] self.n_batches = n_batches - self.model_type = self.params["model_type"] - self.sample_pairs = self.params.get("sample_pairs", False) - self.n_classes = self.params.get("n_classes") + self.model_type = fallback_params("model_type", self.params, self.global_params) + self.sample_pairs = fallback_params( + "sample_pairs", self.params, self.global_params + ) + self.n_classes = fallback_params("n_classes", self.params, self.global_params) self.output_size = model.output_shape - self.record_int = record_int - self.record_float = record_float + self.record_int = utils.fallback_params( + "record_int", self.params, self.global_params, record_int + ) + self.record_float = utils.fallback_params( + "record_float", self.params, self.global_params, record_float + ) self.modelio = self.get_io_func() @@ -207,8 +221,55 @@ def __init__( self.writer = writer self.step_num = 0 + self.init_wandb_metrics() + + self.model.set_criterion(self.make_criterion()) + self.logger: MinervaTaskLogger = self.make_logger() + def init_wandb_metrics(self) -> None: + """Setups up the step counter for :mod:`wandb` logging.""" + if isinstance(self.writer, Run): + self.writer.define_metric(f"{self.name}/step") + self.writer.define_metric(f"{self.name}/*", step_metric=f"{self.name}/step") + + def make_criterion(self) -> Any: + """Creates a :mod:`torch` loss function based on config parameters. + + Returns: + ~typing.Any: Initialised :mod:`torch` loss function specified by config parameters. + """ + # Gets the loss function requested by config parameters. + loss_params: Dict[str, Any] = fallback_params( + "loss_params", self.params, self.global_params + ).copy() + module = loss_params.pop("module", "torch.nn") + criterion: Callable[..., Any] = func_by_str(module, loss_params["name"]) + + if not utils.check_dict_key(loss_params, "params"): + loss_params["params"] = {} + + if fallback_params( + "balance", self.params, self.global_params, False + ) and utils.check_substrings_in_string(self.model_type, "segmentation"): + print(f"Epoch {self.class_dist=}") + weights_dict = utils.class_weighting(self.class_dist, normalise=False) + + weights = [] + if fallback_params("elim", self.params, self.global_params, False): + for i in range(len(weights_dict)): + weights.append(weights_dict[i]) + else: + for i in range(self.n_classes): + weights.append(weights_dict.get(i, 0.0)) + + loss_params["params"]["weight"] = Tensor(weights) + + return criterion(**loss_params["params"]) + + else: + return criterion(**loss_params["params"]) + def make_logger(self) -> MinervaTaskLogger: """Creates an object to calculate and log the metrics from the experiment, selected by config parameters. @@ -254,27 +315,41 @@ def get_io_func(self) -> Callable[..., Any]: return io_func @abc.abstractmethod - def step(self, mode: str) -> None: + def step(self) -> None: raise NotImplementedError - def _generic_step(self, mode: str) -> Optional[Dict[str, Any]]: - self.step(mode) + def _generic_step(self, epoch_no: int) -> Optional[Dict[str, Any]]: + self.step() # Send the logs to the metric logger. self.logger.calc_metrics() + # Add epoch number to metrics. + self.logger.log_epoch_number(epoch_no) + if self.record_int or self.record_float: - return self.logger.get_results + results = self.logger.get_results else: - return None + results = None + + self.logger.refresh_step_logger() + + return results - def __call__(self, mode: str) -> Any: - return self._generic_step(mode) + def __call__(self, epoch_no: int) -> Any: + return self._generic_step(epoch_no) @property def get_logs(self) -> Dict[str, Any]: return self.logger.get_logs + @property + def get_metrics(self) -> Dict[str, Any]: + return self.logger.get_metrics + + def print_epoch_results(self, epoch_no: int) -> None: + self.logger.print_epoch_results(epoch_no) + def __repr__(self) -> str: return f"{self.__class__.__name__}-{self.name}" diff --git a/minerva/trainer.py b/minerva/trainer.py index cad1fe024..6dc9c7d55 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -264,8 +264,6 @@ def __init__( # Sets the max number of epochs of fitting. self.max_epochs = self.params.get("max_epochs", 25) - self.modes = self.params["dataset_params"].keys() - # Flag for a fine-tuning experiment. self.fine_tune = self.params.get("fine_tune", False) @@ -291,7 +289,6 @@ def __init__( if self.params.get("wandb_log", False): # Sets the `wandb` run object (or None). self.writer = wandb_run - self.init_wandb_metrics() else: if _tensorflow_exist: assert TENSORBOARD_WRITER @@ -319,7 +316,6 @@ def __init__( self.sample_pairs = sample_pairs self.model.determine_output_dim(sample_pairs=sample_pairs) - print(self.device) # Transfer to GPU. self.model.to(self.device) @@ -333,9 +329,6 @@ def __init__( **self.params["stopping"], ) - # Stores the step number for that mode of fitting. To be used for logging. - self.step_num = {mode: 0 for mode in self.modes} - # Creates and sets the optimiser for the model. self.make_optimiser() @@ -383,13 +376,6 @@ def __init__( ) self.model = MinervaDataParallel(self.model, DDP, device_ids=[gpu]) - def init_wandb_metrics(self) -> None: - """Setups up separate step counters for :mod:`wandb` logging of train, val, etc.""" - if isinstance(self.writer, Run): - for mode in self.n_batches: - self.writer.define_metric(f"{mode}/step") - self.writer.define_metric(f"{mode}/*", step_metric=f"{mode}/step") - def get_input_size(self) -> Tuple[int, ...]: """Determines the input size of the model. @@ -506,30 +492,12 @@ def make_criterion(self) -> Any: # Gets the loss function requested by config parameters. loss_params: Dict[str, Any] = self.params["loss_params"].copy() module = loss_params.pop("module", "torch.nn") - criterion: Callable[..., Any] = utils.func_by_str( - module, self.params["loss_func"] - ) + criterion: Callable[..., Any] = utils.func_by_str(module, loss_params["name"]) if not utils.check_dict_key(loss_params, "params"): loss_params["params"] = {} - if self.params.get("balance", False) and self.model_type == "segmentation": - weights_dict = utils.class_weighting(self.class_dist, normalise=False) - - weights = [] - if self.params.get("elim", False): - for i in range(len(weights_dict)): - weights.append(weights_dict[i]) - else: - for i in range(self.params["n_classes"]): - weights.append(weights_dict.get(i, 0.0)) - - loss_params["params"]["weight"] = Tensor(weights) - - return criterion(**loss_params["params"]) - - else: - return criterion(**loss_params["params"]) + return criterion(**loss_params["params"]) def make_optimiser(self) -> None: """Creates a :mod:`torch` optimiser based on config parameters and sets optimiser.""" @@ -552,21 +520,27 @@ def make_optimiser(self) -> None: def fit(self) -> None: """Fits the model by running ``max_epochs`` number of training and validation epochs.""" - fit_params = deepcopy(self.params["tasks"]["fit"]) + fit_params = deepcopy( + { + key: self.params["tasks"][key] + for key in self.params["tasks"].keys() + if utils.check_substrings_in_string(key, "fit") + } + ) tasks: Dict[str, MinervaTask] = {} - for mode in ("train", "val"): + for mode in fit_params.keys(): tasks[mode] = get_task( fit_params[mode].pop("type"), + mode, self.model, - self.batch_size, self.device, self.exp_fn, self.gpu, self.rank, self.world_size, self.writer, - fit_params[mode], + **self.params, ) for epoch in range(self.max_epochs): @@ -575,45 +549,50 @@ def fit(self) -> None: ) # Conduct training or validation epoch. - for mode in ("train", "val"): + for mode in tasks.keys(): # Only run a validation epoch at set frequency of epochs. Goes to next epoch if not. - if mode == "val" and (epoch + 1) % self.val_freq != 0: + if ( + utils.check_substrings_in_string(mode, "val") + and (epoch + 1) % self.val_freq != 0 + ): break - if mode == "train": + if tasks[mode].train: self.model.train() else: self.model.eval() results: Optional[Dict[str, Any]] - results = tasks[mode](mode) - - # Add epoch number to metrics. - self.metric_logger.log_epoch_number(mode, epoch) + results = tasks[mode](epoch) # Print epoch results. if self.gpu == 0: - if mode == "val": - epoch_no = epoch // self.val_freq - else: - epoch_no = epoch - self.metric_logger.print_epoch_results(mode, epoch_no) + # if utils.check_substrings_in_string(mode, "val"): + # epoch_no = epoch // self.val_freq + # else: + # epoch_no = epoch + tasks[mode].print_epoch_results(epoch) # Sends validation loss to the stopper and updates early stop bool. - if mode == "val" and self.stopper is not None: - if mode == "val": - epoch_no = epoch // self.val_freq - else: - epoch_no = epoch + if ( + utils.check_substrings_in_string(mode, "val") + and self.stopper is not None + ): + # if utils.check_substrings_in_string(mode, "val"): + # epoch_no = epoch // self.val_freq + # else: + # epoch_no = epoch - val_loss = self.metric_logger.get_metrics["val_loss"]["y"][epoch_no] + val_loss = tasks[mode].get_metrics[f"{mode}_loss"]["y"][epoch] self.stopper(val_loss, self.model) self.early_stop = self.stopper.early_stop # Special case for final train/ val epoch to plot results if configured so. if epoch == (self.max_epochs - 1) or self.early_stop: - if self.early_stop and mode == "val": # pragma: no cover + if self.early_stop and utils.check_substrings_in_string( + mode, "val" + ): # pragma: no cover self.print("\nEarly stopping triggered") # Ensures that plots likely to cause memory issues are not attempted. @@ -621,18 +600,26 @@ def fit(self) -> None: plots["CM"] = False plots["ROC"] = False - if not self.params.get("plot_last_epoch", False): + if not utils.fallback_params( + "plot_last_epoch", tasks[mode].params, self.params, False + ): # If not plotting results, ensure that only history plotting will remain # if originally set to do so. plots["Mask"] = False plots["Pred"] = False - # Create a subset of metrics which drops the testing results for plotting model history. - sub_metrics = self.metric_logger.get_sub_metrics() + # Create a subset of metrics for plotting model history. + sub_metrics = {} + for mode in tasks.keys(): + sub_metrics | tasks[mode].get_metrics + + sub_metrics = { + k.replace("fit-", ""): v for k, v in sub_metrics.items() + } # Ensures masks are not plotted for model types that do not yield such outputs. if utils.check_substrings_in_string( - self.model_type, "scene classifier", "mlp", "MLP" + tasks[mode].model_type, "scene classifier", "mlp", "MLP" ): plots["Mask"] = False @@ -645,9 +632,14 @@ def fit(self) -> None: # Plots the results of this epoch. visutils.plot_results( plots, + task_name=mode, metrics=sub_metrics, - class_names=self.params.get("classes"), - colours=self.params.get("colours"), + class_names=utils.fallback_params( + "classes", tasks[mode].params, self.params + ), + colours=utils.fallback_params( + "colours", tasks[mode].params, self.params + ), save=True, show=False, model_name=self.params["model_name"], diff --git a/tests/test_trainer.py b/tests/test_trainer.py index 43525dfd4..b6c8aad55 100644 --- a/tests/test_trainer.py +++ b/tests/test_trainer.py @@ -23,8 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -r"""Tests for :mod:`minerva.trainer`. -""" +r"""Tests for :mod:`minerva.trainer`.""" # ===================================================================================================================== # METADATA # ===================================================================================================================== From f4b8d5592460a5d7ea58bb8a0939ea453829f364 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 9 Oct 2023 23:33:25 +0100 Subject: [PATCH 075/136] Moved plotting to `MinervaTask` --- minerva/inbuilt_cfgs/example_config.yml | 52 +++++----- minerva/tasks/core.py | 60 ++++++++++- minerva/trainer.py | 130 +++++++----------------- 3 files changed, 117 insertions(+), 125 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 3688b2971..7df34fa23 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -154,39 +154,39 @@ tasks: params: res: 1.0 - tests: + test-test: type: StandardEpoch + record_float: true # ---+ Minerva Inbuilt Logging Functions +------------------------- - logger: STGLogger - metrics: SPMetrics - model_io: sup_tg + # logger: STGLogger + # metrics: SPMetrics + # model_io: sup_tg # ---+ Dataset Parameters +---------------------------------------- dataset_params: - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 - image: - transforms: false - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 + image: + transforms: false + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 - mask: - transforms: false - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + mask: + transforms: false + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 97c8bf337..0d51f55f4 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -57,7 +57,7 @@ from minerva.logging.tasklog import MinervaTaskLogger, SupervisedTaskLogger from minerva.modelio import sup_tg from minerva.models import MinervaDataParallel, MinervaModel -from minerva.utils import utils +from minerva.utils import utils, visutils from minerva.utils.utils import fallback_params, func_by_str @@ -178,12 +178,11 @@ def __init__( self.global_params = global_params self.params = new_params - print(new_params["classes"]) - self.exp_fn = exp_fn self.train = train - del self.params["train"] + if "train" in self.params: + del self.params["train"] self.gpu = gpu @@ -350,6 +349,59 @@ def get_metrics(self) -> Dict[str, Any]: def print_epoch_results(self, epoch_no: int) -> None: self.logger.print_epoch_results(epoch_no) + def plot( + self, + results: Dict[str, Any], + metrics: Optional[Dict[str, Any]] = None, + ) -> None: + # Gets the dict from params that defines which plots to make from the results. + plots = utils.fallback_params( + "plots", self.params, self.global_params, {} + ).copy() + + if not utils.fallback_params( + "plot_last_epoch", self.params, self.global_params, False + ): + # If not plotting results, ensure that only history plotting will remain + # if originally set to do so. + plots["Mask"] = False + plots["Pred"] = False + + # Ensures masks are not plotted for model types that do not yield such outputs. + if utils.check_substrings_in_string( + self.model_type, "scene classifier", "mlp", "MLP" + ): + plots["Mask"] = False + + print(metrics) + if metrics is None: + plots["History"] = False + + elif len(list(metrics.values())[0]["x"]) <= 1: + plots["History"] = False + + else: + print(list(metrics.values())[0]) + + # Amends the results' directory to add a new level for train or validation. + self.results_dir = self.exp_fn.parent / self.name + + visutils.plot_results( + plots, + task_name=self.name, + metrics=metrics, + class_names=utils.fallback_params( + "classes", self.params, self.global_params + ), + colours=utils.fallback_params("colours", self.params, self.global_params), + save=True, + show=False, + model_name=self.params["model_name"], + timestamp=self.params["timestamp"], + results_dir=self.results_dir, + **results, + ) + def __repr__(self) -> str: return f"{self.__class__.__name__}-{self.name}" diff --git a/minerva/trainer.py b/minerva/trainer.py index 6dc9c7d55..5c3d6ce27 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -595,58 +595,20 @@ def fit(self) -> None: ): # pragma: no cover self.print("\nEarly stopping triggered") - # Ensures that plots likely to cause memory issues are not attempted. - plots: Dict[str, bool] = self.params.get("plots", {}).copy() - plots["CM"] = False - plots["ROC"] = False - - if not utils.fallback_params( - "plot_last_epoch", tasks[mode].params, self.params, False - ): - # If not plotting results, ensure that only history plotting will remain - # if originally set to do so. - plots["Mask"] = False - plots["Pred"] = False - # Create a subset of metrics for plotting model history. - sub_metrics = {} + fit_metrics = {} for mode in tasks.keys(): - sub_metrics | tasks[mode].get_metrics + fit_metrics = {**fit_metrics, **tasks[mode].get_metrics} - sub_metrics = { - k.replace("fit-", ""): v for k, v in sub_metrics.items() + fit_metrics = { + k.replace("fit-", ""): v for k, v in fit_metrics.items() } - # Ensures masks are not plotted for model types that do not yield such outputs. - if utils.check_substrings_in_string( - tasks[mode].model_type, "scene classifier", "mlp", "MLP" - ): - plots["Mask"] = False - - # Amends the results' directory to add a new level for train or validation. - results_dir = self.exp_fn.parent / mode - assert results is not None if self.gpu == 0: # Plots the results of this epoch. - visutils.plot_results( - plots, - task_name=mode, - metrics=sub_metrics, - class_names=utils.fallback_params( - "classes", tasks[mode].params, self.params - ), - colours=utils.fallback_params( - "colours", tasks[mode].params, self.params - ), - save=True, - show=False, - model_name=self.params["model_name"], - timestamp=self.params["timestamp"], - results_dir=results_dir, - **results, - ) + tasks[mode].plot(results, fit_metrics) # If early stopping has been triggered, loads the last model save to replace current model, # ready for testing. @@ -669,66 +631,44 @@ def test(self, save: bool = True, show: bool = False) -> None: """ self.print("\r\nTESTING") - test_params = deepcopy(self.params["tasks"]["tests"]) + test_params = deepcopy( + { + key: self.params["tasks"][key] + for key in self.params["tasks"].keys() + if utils.check_substrings_in_string(key, "test") + } + ) - for _task in test_params: + for task_name in test_params.keys(): task = get_task( - test_params[_task].pop("type"), + test_params[task_name].pop("type"), + task_name, self.model, - self.batch_size, self.device, self.exp_fn, self.gpu, self.rank, self.world_size, self.writer, - test_params[_task], + **self.params, ) # Runs test epoch on model, returning the predicted labels, ground truth labels supplied # and the IDs of the samples supplied. - results = task("test") + results = task(1) assert results is not None - # Prints test loss and accuracy to stdout. - self.metric_logger.print_epoch_results("test", 0) - - # Add epoch number to testing results. - self.metric_logger.log_epoch_number("test", 0) - if self.gpu == 0: + # Print epoch results. + task.print_epoch_results(1) + if "z" in results and "y" in results: self.print("\nMAKING CLASSIFICATION REPORT") - self.compute_classification_report(results["z"], results["y"]) - - # Gets the dict from params that defines which plots to make from the results. - plots = self.params.get("plots", {}).copy() - - # Ensure history is not plotted again. - plots["History"] = False - - if utils.check_substrings_in_string( - self.model_type, "scene classifier", "mlp", "MLP" - ): - plots["Mask"] = False - - # Amends the results' directory to add a new level for test results. - results_dir = self.exp_fn.parent / "test" + # self.compute_classification_report(results["z"], results["y"]) # Plots the results. - visutils.plot_results( - plots, - mode="test", - class_names=self.params["classes"], - colours=self.params["colours"], - save=save, - show=show, - model_name=self.params["model_name"], - timestamp=self.params["timestamp"], - results_dir=results_dir, - **results, - ) + task.plot(results) # Now experiment is complete, saves model parameters and config file to disk in case error is # encountered in plotting of results. @@ -819,19 +759,19 @@ def close(self) -> None: yaml.dump(self.params, outfile) # Writes the recorded training and validation metrics of the experiment to file. - self.print("\nSAVING METRICS TO FILE") - try: - sub_metrics = self.metric_logger.get_sub_metrics() - metrics_df = pd.DataFrame( - {key: sub_metrics[key]["y"] for key in sub_metrics.keys()} - ) - metrics_df["Epoch"] = sub_metrics["train_loss"]["x"] - metrics_df.set_index("Epoch", inplace=True, drop=True) - metrics_df.to_csv(f"{self.exp_fn}_metrics.csv") - - except (ValueError, KeyError) as err: # pragma: no cover - self.print(err) - self.print("\n*ERROR* in saving metrics to file.") + # self.print("\nSAVING METRICS TO FILE") + # try: + # sub_metrics = self.metric_logger.get_sub_metrics() + # metrics_df = pd.DataFrame( + # {key: sub_metrics[key]["y"] for key in sub_metrics.keys()} + # ) + # metrics_df["Epoch"] = sub_metrics["train_loss"]["x"] + # metrics_df.set_index("Epoch", inplace=True, drop=True) + # metrics_df.to_csv(f"{self.exp_fn}_metrics.csv") + + # except (ValueError, KeyError) as err: # pragma: no cover + # self.print(err) + # self.print("\n*ERROR* in saving metrics to file.") # Checks whether to save the model parameters to file. if self.params.get("save_model", False) in ( From 34620d7cf2ee40f67546a436d488a36b355eba63 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 02:06:33 +0100 Subject: [PATCH 076/136] `compute_classification_report` --> `MinervaTask` --- minerva/tasks/core.py | 34 ++++++++++++++++++++++++++-------- minerva/trainer.py | 31 +++++-------------------------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 0d51f55f4..d595a0a9b 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -41,7 +41,7 @@ import abc from abc import ABC from pathlib import Path -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Sequence, Union if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter @@ -50,6 +50,7 @@ import torch import torch.distributed as dist +from nptyping import Int, NDArray from torch import Tensor from wandb.sdk.wandb_run import Run @@ -178,7 +179,9 @@ def __init__( self.global_params = global_params self.params = new_params - self.exp_fn = exp_fn + # Modify `exp_fn` with a sub-directory for this task. + self.task_dir = exp_fn / self.name + self.task_fn = self.task_dir / exp_fn.name self.train = train if "train" in self.params: @@ -373,7 +376,6 @@ def plot( ): plots["Mask"] = False - print(metrics) if metrics is None: plots["History"] = False @@ -381,10 +383,7 @@ def plot( plots["History"] = False else: - print(list(metrics.values())[0]) - - # Amends the results' directory to add a new level for train or validation. - self.results_dir = self.exp_fn.parent / self.name + pass visutils.plot_results( plots, @@ -398,10 +397,29 @@ def plot( show=False, model_name=self.params["model_name"], timestamp=self.params["timestamp"], - results_dir=self.results_dir, + results_dir=self.task_dir, **results, ) + def compute_classification_report( + self, predictions: Sequence[int], labels: Sequence[int] + ) -> None: + """Creates and saves to file a classification report table of precision, recall, f-1 score and support. + + Args: + predictions (~typing.Sequence[int]): List of predicted labels. + labels (~typing.Sequence[int]): List of corresponding ground truth label masks. + """ + # Ensures predictions and labels are flattened. + preds: NDArray[Any, Int] = utils.batch_flatten(predictions) + targets: NDArray[Any, Int] = utils.batch_flatten(labels) + + # Uses utils to create a classification report in a DataFrame. + cr_df = utils.make_classification_report(preds, targets, self.params["classes"]) + + # Saves classification report DataFrame to a .csv file at fn. + cr_df.to_csv(f"{self.task_fn}_classification-report.csv") + def __repr__(self) -> str: return f"{self.__class__.__name__}-{self.name}" diff --git a/minerva/trainer.py b/minerva/trainer.py index 5c3d6ce27..3f0cc64de 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -665,7 +665,7 @@ def test(self, save: bool = True, show: bool = False) -> None: if "z" in results and "y" in results: self.print("\nMAKING CLASSIFICATION REPORT") - # self.compute_classification_report(results["z"], results["y"]) + task.compute_classification_report(results["z"], results["y"]) # Plots the results. task.plot(results) @@ -717,16 +717,14 @@ def test(self, save: bool = True, show: bool = False) -> None: "providing the path to this experiment's results directory and unique experiment ID" ) - def tsne_cluster(self, mode: str = "test") -> None: + def tsne_cluster(self) -> None: """Perform TSNE clustering on the embeddings from the model and visualise. Passes a batch from the test dataset through the model in eval mode to get the embeddings. Passes these embeddings to :mod:`visutils` to train a TSNE algorithm and then visual the cluster. - - Args: - mode (str): The mode of model fitting that the embeddings come from. """ task = TSNEVis( + "TSNEVis", self.model, self.batch_size, self.device, @@ -737,7 +735,7 @@ def tsne_cluster(self, mode: str = "test") -> None: self.writer, ) - task(mode) + task(1) def close(self) -> None: """Closes the experiment, saving experiment parameters and model to file.""" @@ -759,7 +757,7 @@ def close(self) -> None: yaml.dump(self.params, outfile) # Writes the recorded training and validation metrics of the experiment to file. - # self.print("\nSAVING METRICS TO FILE") + self.print("\nSAVING METRICS TO FILE") # try: # sub_metrics = self.metric_logger.get_sub_metrics() # metrics_df = pd.DataFrame( @@ -801,25 +799,6 @@ def close(self) -> None: # Saves model state dict to PyTorch file. self.save_model_weights() - def compute_classification_report( - self, predictions: Sequence[int], labels: Sequence[int] - ) -> None: - """Creates and saves to file a classification report table of precision, recall, f-1 score and support. - - Args: - predictions (~typing.Sequence[int]): List of predicted labels. - labels (~typing.Sequence[int]): List of corresponding ground truth label masks. - """ - # Ensures predictions and labels are flattened. - preds: NDArray[Any, Int] = utils.batch_flatten(predictions) - targets: NDArray[Any, Int] = utils.batch_flatten(labels) - - # Uses utils to create a classification report in a DataFrame. - cr_df = utils.make_classification_report(preds, targets, self.params["classes"]) - - # Saves classification report DataFrame to a .csv file at fn. - cr_df.to_csv(f"{self.exp_fn}_classification-report.csv") - def extract_model_from_distributed(self) -> MinervaModel: """Extracts the actual model from any distributed wrapping if this is a distributed run. From 3a58741d9efe05c8945321e5b63d9383154dd7ec Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 10:34:27 +0100 Subject: [PATCH 077/136] Updated `TSNEVis` to new `MinervaTask` format --- minerva/tasks/tsne.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 97fe73a53..9b9d1d225 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -63,8 +63,8 @@ class TSNEVis(MinervaTask): def __init__( self, + name: str, model: Union[MinervaModel, MinervaDataParallel], - batch_size: int, device: torch.device, exp_fn: Path, gpu: int = 0, @@ -76,8 +76,8 @@ def __init__( **params, ) -> None: super().__init__( + name, model, - batch_size, device, exp_fn, gpu, @@ -91,7 +91,7 @@ def __init__( if self.params.get("data", None): self.loaders["test"] = self.params["data"] - def step(self, mode: str) -> None: + def step(self) -> None: """Perform TSNE clustering on the embeddings from the model and visualise. Passes a batch from the test dataset through the model in eval mode to get the embeddings. @@ -101,7 +101,7 @@ def step(self, mode: str) -> None: mode (str): The mode of model fitting that the embeddings come from. """ # Get a batch of data. - data = next(iter(self.loaders[mode])) + data = next(iter(self.loaders)) # Make sure the model is in evaluation mode. self.model.eval() @@ -112,13 +112,10 @@ def step(self, mode: str) -> None: # Flatten embeddings. embeddings = embeddings.flatten(start_dim=1) - # Get the results directory. - results_dir = self.exp_fn.parent / mode - plot_embedding( embeddings.detach().cpu(), data["bbox"], - mode, + self.name, show=True, - filename=str(results_dir / "tsne_cluster_vis.png"), + filename=str(self.task_fn / "tsne_cluster_vis.png"), ) From 4c15321e2dae36b8e814666a1a3f6b7f6de0aef9 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 18:04:24 +0100 Subject: [PATCH 078/136] Updated `WeightedKNN` signature --- minerva/tasks/knn.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index fe23ea58d..3d18c47f4 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -152,8 +152,7 @@ class WeightedKNN(MinervaTask): def __init__( self, name: str, - model: MinervaModel, - batch_size: int, + model: Union[MinervaModel, MinervaDataParallel], device: torch.device, exp_fn: Path, gpu: int = 0, @@ -167,7 +166,6 @@ def __init__( super().__init__( name, model, - batch_size, device, exp_fn, gpu, From 393125b87f1c842b47fc46d2ca9a806ea6117b8b Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 18:04:59 +0100 Subject: [PATCH 079/136] Added `save_metrics` to `MinervaTask` --- minerva/tasks/core.py | 18 ++++++++++++++++++ minerva/trainer.py | 31 +++++++------------------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index d595a0a9b..aa1540cc5 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -48,6 +48,7 @@ else: # pragma: no cover SummaryWriter = None +import pandas as pd import torch import torch.distributed as dist from nptyping import Int, NDArray @@ -420,6 +421,23 @@ def compute_classification_report( # Saves classification report DataFrame to a .csv file at fn. cr_df.to_csv(f"{self.task_fn}_classification-report.csv") + def save_metrics(self) -> None: + print("\nSAVING METRICS TO FILE") + try: + metrics = self.get_metrics() + metrics_df = pd.DataFrame( + {key: metrics[key]["y"] for key in metrics.keys()} + ) + + # Assumes that the length of each metric is the same. + metrics_df["Epoch"] = list(metrics.values())[0]["x"] + metrics_df.set_index("Epoch", inplace=True, drop=True) + metrics_df.to_csv(f"{self.exp_fn}_metrics.csv") + + except (ValueError, KeyError) as err: # pragma: no cover + print(err) + print("\n*ERROR* in saving metrics to file.") + def __repr__(self) -> str: return f"{self.__class__.__name__}-{self.name}" diff --git a/minerva/trainer.py b/minerva/trainer.py index 3f0cc64de..1c1c97830 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -568,10 +568,6 @@ def fit(self) -> None: # Print epoch results. if self.gpu == 0: - # if utils.check_substrings_in_string(mode, "val"): - # epoch_no = epoch // self.val_freq - # else: - # epoch_no = epoch tasks[mode].print_epoch_results(epoch) # Sends validation loss to the stopper and updates early stop bool. @@ -579,11 +575,6 @@ def fit(self) -> None: utils.check_substrings_in_string(mode, "val") and self.stopper is not None ): - # if utils.check_substrings_in_string(mode, "val"): - # epoch_no = epoch // self.val_freq - # else: - # epoch_no = epoch - val_loss = tasks[mode].get_metrics[f"{mode}_loss"]["y"][epoch] self.stopper(val_loss, self.model) self.early_stop = self.stopper.early_stop @@ -610,6 +601,9 @@ def fit(self) -> None: # Plots the results of this epoch. tasks[mode].plot(results, fit_metrics) + # Writes the recorded metrics of the task to file. + tasks[mode].save_metrics() + # If early stopping has been triggered, loads the last model save to replace current model, # ready for testing. if self.early_stop: # pragma: no cover @@ -663,6 +657,7 @@ def test(self, save: bool = True, show: bool = False) -> None: # Print epoch results. task.print_epoch_results(1) + # Creates a classification report from the results of the task. if "z" in results and "y" in results: self.print("\nMAKING CLASSIFICATION REPORT") task.compute_classification_report(results["z"], results["y"]) @@ -670,6 +665,9 @@ def test(self, save: bool = True, show: bool = False) -> None: # Plots the results. task.plot(results) + # Writes the recorded metrics of the task to file. + task.save_metrics() + # Now experiment is complete, saves model parameters and config file to disk in case error is # encountered in plotting of results. self.close() @@ -756,21 +754,6 @@ def close(self) -> None: with open(f"{self.exp_fn}.yml", "w") as outfile: yaml.dump(self.params, outfile) - # Writes the recorded training and validation metrics of the experiment to file. - self.print("\nSAVING METRICS TO FILE") - # try: - # sub_metrics = self.metric_logger.get_sub_metrics() - # metrics_df = pd.DataFrame( - # {key: sub_metrics[key]["y"] for key in sub_metrics.keys()} - # ) - # metrics_df["Epoch"] = sub_metrics["train_loss"]["x"] - # metrics_df.set_index("Epoch", inplace=True, drop=True) - # metrics_df.to_csv(f"{self.exp_fn}_metrics.csv") - - # except (ValueError, KeyError) as err: # pragma: no cover - # self.print(err) - # self.print("\n*ERROR* in saving metrics to file.") - # Checks whether to save the model parameters to file. if self.params.get("save_model", False) in ( "opt", From e354bb84dabb906dfc8ebb096d63095db906e8cf Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 18:15:14 +0100 Subject: [PATCH 080/136] Fixed bugs in `test_visutils` --- minerva/utils/visutils.py | 8 +++++--- tests/conftest.py | 4 +++- tests/test_utils/test_visutils.py | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/minerva/utils/visutils.py b/minerva/utils/visutils.py index 4439d36e7..6d82f8997 100644 --- a/minerva/utils/visutils.py +++ b/minerva/utils/visutils.py @@ -1104,7 +1104,7 @@ def make_roc_curves( def plot_embedding( embeddings: Any, bounds: Union[Sequence[BoundingBox], NDArray[Any, Any]], - mode: str, + task_name: str, title: Optional[str] = None, show: bool = False, save: bool = True, @@ -1117,7 +1117,7 @@ def plot_embedding( bounds (~typing.Sequence[~torchgeo.datasets.utils.BoundingBox] | ~numpy.ndarray[~torchgeo.datasets.utils.BoundingBox]): # noqa: E501 Array of objects describing a geospatial bounding box. Must contain ``minx``, ``maxx``, ``miny`` and ``maxy`` parameters. - mode (str): Mode samples are from. Must be ``'train'``, ``'val'`` or ``'test'``. + task_name (str): Name of the task that the samples are from. title (str): Optional; Title of plot. show (bool): Optional; Whether to show plot. save (bool): Optional; Whether to save plot to file. @@ -1134,7 +1134,9 @@ def plot_embedding( from minerva.datasets import make_dataset print("\nRE-CONSTRUCTING DATASET") - dataset, _ = make_dataset(CONFIG["dir"]["data"], CONFIG["dataset_params"][mode]) + dataset, _ = make_dataset( + CONFIG["dir"]["data"], CONFIG["tasks"][task_name]["dataset_params"] + ) images = [] targets = [] diff --git a/tests/conftest.py b/tests/conftest.py index a92b1ac9e..cd41f0f66 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -356,7 +356,9 @@ def exp_dataset_params() -> Dict[str, Any]: @pytest.fixture def default_dataset() -> IntersectionDataset: - dataset, _ = make_dataset(CONFIG["dir"]["data"], CONFIG["dataset_params"]["test"]) + dataset, _ = make_dataset( + CONFIG["dir"]["data"], CONFIG["tasks"]["test-test"]["dataset_params"] + ) assert isinstance(dataset, IntersectionDataset) return dataset diff --git a/tests/test_utils/test_visutils.py b/tests/test_utils/test_visutils.py index 49426779e..e9a36b793 100644 --- a/tests/test_utils/test_visutils.py +++ b/tests/test_utils/test_visutils.py @@ -243,7 +243,7 @@ def test_seg_plot(results_root, default_dataset: GeoDataset, monkeypatch) -> Non y=z, ids=ids, # type: ignore[arg-type] bounds=bboxes, - mode="test", + task_name="test-test", classes=utils.CLASSES, colours=utils.CMAP_DICT, fn_prefix=fn_prefix, @@ -369,7 +369,7 @@ def test_plot_results(default_dataset: GeoDataset) -> None: probs=probs, bounds=bounds, embeddings=embeddings, - mode="test", + task_name="test-test", class_names=utils.CLASSES, colours=utils.CMAP_DICT, save=False, @@ -385,7 +385,7 @@ def test_plot_embeddings(results_root: Path, default_dataset: GeoDataset) -> Non visutils.plot_embedding( embeddings, bounds, - "test", + "test-test", show=True, filename=results_root / "tsne_cluster_vis.png", title="test_plot", From fe6d6e8e29b3abaf0bfb9c0c77ecbe2942085230 Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 18:19:22 +0100 Subject: [PATCH 081/136] Fixed incorrect task names in `test_factory` --- tests/test_datasets/test_factory.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/test_datasets/test_factory.py b/tests/test_datasets/test_factory.py index ffb39454e..9840de3a7 100644 --- a/tests/test_datasets/test_factory.py +++ b/tests/test_datasets/test_factory.py @@ -192,7 +192,7 @@ def test_make_loaders() -> None: # old_params["transform_params"] = transform_params loader, n_batches, class_dist, params = mdt.make_loaders( - **old_params, task_name="val" + **old_params, task_name="fit-val" ) assert isinstance(loader, DataLoader) @@ -213,8 +213,12 @@ def test_get_manifest() -> None: if manifest_path.exists(): manifest_path.unlink() - assert isinstance(mdt.get_manifest(manifest_path, task_name="train"), pd.DataFrame) - assert isinstance(mdt.get_manifest(manifest_path, task_name="train"), pd.DataFrame) + assert isinstance( + mdt.get_manifest(manifest_path, task_name="fit-train"), pd.DataFrame + ) + assert isinstance( + mdt.get_manifest(manifest_path, task_name="fit-train"), pd.DataFrame + ) new_path = Path("tests", "tmp", "empty", "Chesapeake7_Manifest.csv") if new_path.exists(): @@ -223,7 +227,7 @@ def test_get_manifest() -> None: if new_path.parent.exists(): new_path.parent.rmdir() - assert isinstance(mdt.get_manifest(new_path, task_name="train"), pd.DataFrame) + assert isinstance(mdt.get_manifest(new_path, task_name="fit-train"), pd.DataFrame) if new_path.exists(): new_path.unlink() From 7cd73027130e3a50c265fc6c980ffbe727adef3d Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 18:23:58 +0100 Subject: [PATCH 082/136] Fixed task name in `test_epoch` --- tests/test_tasks/test_epoch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_tasks/test_epoch.py b/tests/test_tasks/test_epoch.py index 482452ebb..cd3952685 100644 --- a/tests/test_tasks/test_epoch.py +++ b/tests/test_tasks/test_epoch.py @@ -59,7 +59,7 @@ def test_standard_epoch(default_device, exp_fcn: MinervaModel): params = CONFIG.copy() task = StandardEpoch( - name="train", + name="fit-train", model=exp_fcn, device=default_device, exp_fn=exp_fn, @@ -72,4 +72,4 @@ def test_standard_epoch(default_device, exp_fcn: MinervaModel): assert isinstance(task.get_logs, dict) - assert repr(task) == "StandardEpoch-train" + assert repr(task) == "StandardEpoch-fit-train" From 5342101dd4ce51966932fa353aa59f906971cdea Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 11 Oct 2023 20:13:52 +0100 Subject: [PATCH 083/136] Updated example configs to new `tasks` structure --- minerva/inbuilt_cfgs/example_3rd_party.yml | 204 +++++++++-------- minerva/inbuilt_cfgs/example_CNN_config.yml | 210 +++++++++-------- .../inbuilt_cfgs/example_GeoCLR_config.yml | 204 ++++++++++------- .../inbuilt_cfgs/example_GeoSimConvNet.yml | 215 ++++++++++-------- minerva/inbuilt_cfgs/example_UNetR_config.yml | 192 +++++++++------- .../example_autoencoder_config.yml | 198 ++++++++-------- 6 files changed, 670 insertions(+), 553 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_3rd_party.yml b/minerva/inbuilt_cfgs/example_3rd_party.yml index 5171f1dee..6bd1b218c 100644 --- a/minerva/inbuilt_cfgs/example_3rd_party.yml +++ b/minerva/inbuilt_cfgs/example_3rd_party.yml @@ -38,9 +38,9 @@ elim: false # Eliminates empty classes from schema. balance: false # Balances dataset classes. # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: CrossEntropyLoss # Name of the loss function to use. -lr: 1.0E-2 # Learning rate of optimiser. -optim_func: SGD # Name of the optimiser function. +loss_func: &loss_func CrossEntropyLoss # Name of the loss function to use. +lr: 1.0E-2 # Learning rate of optimiser. +optim_func: SGD # Name of the optimiser function. # ---+ Model Parameters +------------------------------------------------------ model_params: @@ -57,6 +57,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func params: # ---+ Dataloader Parameters +------------------------------------------------- @@ -71,9 +72,9 @@ project: pytest # Define the project name for wandb. wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: STGLogger -metrics: SPMetrics -model_io: sup_tg +# task_logger: SupervisedTaskLogger +# step_logger: SupervisedGeoStepLogger +# model_io: sup_tg record_int: true # Store integer results in memory. record_float: true # Store floating point results too. Beware memory overload! @@ -83,106 +84,121 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 120 - - image: - transforms: - ToRGB: - module: minerva.transforms - - images_1: +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 120 + + image: + transforms: + ToRGB: + module: minerva.transforms + + images_1: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + image2: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: + SingleLabel: + module: minerva.transforms + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + fit-val: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: + ToRGB: + module: minerva.transforms module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - image2: + mask: + transforms: + SingleLabel: + module: minerva.transforms + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: + ToRGB: + module: minerva.transforms module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - mask: - transforms: - SingleLabel: - module: minerva.transforms - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: - ToRGB: - module: minerva.transforms - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: - SingleLabel: - module: minerva.transforms - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: - ToRGB: - module: minerva.transforms - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: - SingleLabel: - module: minerva.transforms - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + mask: + transforms: + SingleLabel: + module: minerva.transforms + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/inbuilt_cfgs/example_CNN_config.yml b/minerva/inbuilt_cfgs/example_CNN_config.yml index 87b3eebe2..ead040f07 100644 --- a/minerva/inbuilt_cfgs/example_CNN_config.yml +++ b/minerva/inbuilt_cfgs/example_CNN_config.yml @@ -38,9 +38,9 @@ pre_train: false # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: CrossEntropyLoss # Name of the loss function to use. -lr: 1.0E-3 # Learning rate of optimiser. -optim_func: SGD # Name of the optimiser function. +loss_func: &loss_func CrossEntropyLoss # Name of the loss function to use. +lr: 1.0E-3 # Learning rate of optimiser. +optim_func: SGD # Name of the optimiser function. # ---+ Model Parameters +------------------------------------------------------ model_params: @@ -55,6 +55,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func params: # ---+ Dataloader Parameters +------------------------------------------------- @@ -69,8 +70,7 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: STGLogger -metrics: SPMetrics +task_logger: SupervisedTaskLogger model_io: sup_tg record_int: true # Store integer results in memory. @@ -81,102 +81,110 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 320 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - mask: - transforms: - SingleLabel: - module: minerva.transforms - mode: modal - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 80 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: - SingleLabel: - module: minerva.transforms - mode: modal - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 160 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - transforms: - SingleLabel: - module: minerva.transforms - mode: modal - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 320 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + mask: + transforms: + SingleLabel: + module: minerva.transforms + mode: modal + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + fit-val: + type: StandardEpoch + train: false + record_float: true + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 80 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: + SingleLabel: + module: minerva.transforms + mode: modal + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + record_float: true + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 160 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + transforms: + SingleLabel: + module: minerva.transforms + mode: modal + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml index e0c77f327..90c66b882 100644 --- a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml +++ b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml @@ -37,7 +37,7 @@ pre_train: true # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: NTXentLoss # Name of the loss function to use. +loss_func: &loss_func NTXentLoss # Name of the loss function to use. lr: 1.0E-2 # Learning rate of optimiser. optim_func: SGD # Name of the optimiser function. @@ -60,6 +60,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func module: lightly.loss params: temperature: 0.5 @@ -76,8 +77,8 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: SSLLogger -metrics: SSLMetrics +task_logger: SSLTaskLogger +step_logger: SSLStepLogger model_io: ssl_pair_tg record_int: true # Store integer results in memory. @@ -88,103 +89,130 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: minerva.samplers - name: RandomPairGeoSampler - roi: false - params: - size: *patch_size - length: 120 - max_r: *max_r - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - RandomApply: - p: 0.25 - RandomResizedCrop: +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + sample_pairs: true + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SSLTaskLogger + step_logger: SSLStepLogger + model_io: ssl_pair_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: minerva.samplers + name: RandomPairGeoSampler + roi: false + params: + size: *patch_size + length: 120 + max_r: *max_r + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + RandomApply: + p: 0.25 + RandomResizedCrop: + module: torchvision.transforms + size: *patch_size + DetachedColorJitter: + module: minerva.transforms + brightness: 0.8 + contrast: 0.8 + saturation: 0.8 + hue: 0.2 + RandomHorizontalFlip: + module: torchvision.transforms + RandomVerticalFlip: module: torchvision.transforms - size: *patch_size - DetachedColorJitter: - module: minerva.transforms - brightness: 0.8 - contrast: 0.8 - saturation: 0.8 - hue: 0.2 - RandomHorizontalFlip: - module: torchvision.transforms - RandomVerticalFlip: - module: torchvision.transforms - GaussianBlur: - module: torchvision.transforms - kernel_size: 25 - - image1: + GaussianBlur: + module: torchvision.transforms + kernel_size: 25 + + image1: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + image2: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + fit-val: + type: WeightedKNN + train: false + sample_pairs: false + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SSLTaskLogger + step_logger: KNNStepLogger + model_io: ssl_pair_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - image2: + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + train: false + record_float: true + sample_pairs: false + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml index ee7bccf03..0cd2e27d9 100644 --- a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml +++ b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml @@ -39,9 +39,9 @@ pre_train: true # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: SegBarlowTwinsLoss # Name of the loss function to use. -lr: 1.0E-3 # Learning rate of optimiser. -optim_func: SGD # Name of the optimiser function. +loss_func: &loss_func SegBarlowTwinsLoss # Name of the loss function to use. +lr: 1.0E-3 # Learning rate of optimiser. +optim_func: SGD # Name of the optimiser function. # ---+ SSL/ Siamese Options +-------------------------------------------------- sample_pairs: true # Activates Siamese paired sampling. @@ -61,6 +61,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func module: minerva.loss params: @@ -76,9 +77,9 @@ wandb_dir: *wandb_dir # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: SSLLogger -metrics: SSLMetrics -model_io: ssl_pair_tg +# task_logger: SSLLogger +# metrics: SSLMetrics +# model_io: ssl_pair_tg record_int: true # Store integer results in memory. record_float: false # Store floating point results too. Beware memory overload! @@ -88,103 +89,135 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: minerva.samplers - name: RandomPairGeoSampler - roi: false - params: - size: *patch_size - length: 120 - max_r: *max_r - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - RandomApply: - p: 0.25 - RandomResizedCrop: +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + sample_pairs: true + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SSLTaskLogger + model_io: ssl_pair_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: minerva.samplers + name: RandomPairGeoSampler + roi: false + params: + size: *patch_size + length: 120 + max_r: *max_r + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + RandomApply: + p: 0.25 + RandomResizedCrop: + module: torchvision.transforms + size: *patch_size + DetachedColorJitter: + module: minerva.transforms + brightness: 0.8 + contrast: 0.8 + saturation: 0.8 + hue: 0.2 + RandomHorizontalFlip: + module: torchvision.transforms + RandomVerticalFlip: module: torchvision.transforms - size: *patch_size - DetachedColorJitter: - module: minerva.transforms - brightness: 0.8 - contrast: 0.8 - saturation: 0.8 - hue: 0.2 - RandomHorizontalFlip: - module: torchvision.transforms - RandomVerticalFlip: - module: torchvision.transforms - GaussianBlur: - module: torchvision.transforms - kernel_size: 25 - - image1: + GaussianBlur: + module: torchvision.transforms + kernel_size: 25 + + image1: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + image2: + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + fit-val: + type: WeightedKNN + train: false + record_float: true + sample_pairs: false + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SSLTaskLogger + step_logger: + name: KNNStepLogger + model_io: ssl_pair_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - image2: + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + train: false + record_float: true + sample_pairs: false + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SSLTaskLogger + model_io: ssl_pair_tg + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: module: minerva.datasets.__testing name: TstImgDataset root: NAIP params: res: 1.0 - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/inbuilt_cfgs/example_UNetR_config.yml b/minerva/inbuilt_cfgs/example_UNetR_config.yml index a9b1aecd2..b692e093f 100644 --- a/minerva/inbuilt_cfgs/example_UNetR_config.yml +++ b/minerva/inbuilt_cfgs/example_UNetR_config.yml @@ -31,16 +31,16 @@ input_size: &input_size [4, 224, 224] # patch_size plus leading channel dim. n_classes: &n_classes 8 # Number of classes in dataset. # ---+ Experiment Execution +-------------------------------------------------- -max_epochs: 5 # Maximum number of training epochs. +max_epochs: 5 # Maximum number of training epochs. elim: true # Eliminates empty classes from schema. balance: true # Balances dataset classes. pre_train: false # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: CrossEntropyLoss # Name of the loss function to use. -lr: 1.0E-3 # Learning rate of optimiser. -optim_func: SGD # Name of the optimiser function. +loss_func: &loss_func CrossEntropyLoss # Name of the loss function to use. +lr: 1.0E-3 # Learning rate of optimiser. +optim_func: SGD # Name of the optimiser function. # ---+ Model Parameters +------------------------------------------------------ model_params: @@ -57,6 +57,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func params: # ---+ Dataloader Parameters +------------------------------------------------- @@ -71,9 +72,9 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: STGLogger -metrics: SPMetrics -model_io: sup_tg +# task_logger: SupervisedTaskLogger +# step_logger: SupervisedGeoStepLogger +# model_io: sup_tg record_int: true # Store integer results in memory. record_float: false # Store floating point results too. Beware memory overload! @@ -83,87 +84,102 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 320 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 80 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 160 - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 320 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + fit-val: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 80 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +---------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 160 + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: diff --git a/minerva/inbuilt_cfgs/example_autoencoder_config.yml b/minerva/inbuilt_cfgs/example_autoencoder_config.yml index a56b4f426..2c4ed8237 100644 --- a/minerva/inbuilt_cfgs/example_autoencoder_config.yml +++ b/minerva/inbuilt_cfgs/example_autoencoder_config.yml @@ -39,9 +39,9 @@ fine_tune: false # Activate fine-tuning mode. autoencoder_data_key: mask # ---+ Loss and Optimisers +--------------------------------------------------- -loss_func: CrossEntropyLoss # Name of the loss function to use. -lr: 1.0E-3 # Learning rate of optimiser. -optim_func: SGD # Name of the optimiser function. +loss_func: &loss_func CrossEntropyLoss # Name of the loss function to use. +lr: 1.0E-3 # Learning rate of optimiser. +optim_func: SGD # Name of the optimiser function. # ---+ Model Parameters +------------------------------------------------------ model_params: @@ -58,6 +58,7 @@ optim_params: # ---+ Loss Function Parameters +---------------------------------------------- loss_params: + name: *loss_func params: # ---+ Dataloader Parameters +------------------------------------------------- @@ -72,9 +73,9 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- -logger: STGLogger -metrics: SPMetrics -model_io: autoencoder_io +task_logger: SupervisedTaskLogger +step_logger: SupervisedGeoStepLogger +model_io: sup_tg record_int: true # Store integer results in memory. record_float: false # Store floating point results too. Beware memory overload! @@ -84,91 +85,106 @@ collator: module: torchgeo.datasets name: stack_samples -# === DATASET PARAMETERS ====================================================== -dataset_params: - # Training Dataset - train: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Validation Dataset - val: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 16 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 - - # Test Dataset - test: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 16 - - image: - transforms: - Normalise: - module: minerva.transforms - norm_value: 255 - module: minerva.datasets.__testing - name: TstImgDataset - root: NAIP - params: - res: 1.0 - - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - root: Chesapeake7 - params: - res: 1.0 +# === TASKS =================================================================== +tasks: + fit-train: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + fit-val: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 16 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 + + test-test: + type: StandardEpoch + train: true + record_float: true + + # ---+ Dataset Parameters +-------------------------------------------- + dataset_params: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 16 + + image: + transforms: + Normalise: + module: minerva.transforms + norm_value: 255 + module: minerva.datasets.__testing + name: TstImgDataset + root: NAIP + params: + res: 1.0 + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + root: Chesapeake7 + params: + res: 1.0 # === PLOTTING OPTIONS ======================================================== plots: From 87cd7abfc163b793c072662c17c65226c0a9e0f0 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 11:18:52 +0100 Subject: [PATCH 084/136] Bump `torchgeo` --> `0.5.0` --- requirements/requirements.txt | 2 +- requirements/requirements_dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 1878027fa..cf746ae6e 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -30,7 +30,7 @@ starlette==0.27.0 # not directly required, pinned by Dependabot to avoid a vulne tabulate==0.9.0 tensorflow==2.13.0 timm==0.9.2 -torchgeo@git+https://github.com/microsoft/torchgeo +torchgeo==0.5.0 torchinfo==1.8.0 tornado>=6.3.3 tqdm==4.66.1 diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index 9077cfb69..1244d4552 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -42,7 +42,7 @@ starlette>=0.25.0 # not directly required, pinned by Dependabot to avoid a vulne tabulate==0.9.0 tensorflow==2.13.0 timm==0.9.2 -torchgeo@git+https://github.com/microsoft/torchgeo +torchgeo==0.5.0 torchinfo==1.8.0 tornado>=6.3.3 tox==4.8.0 From 8c44347b4c9fd2b851afbfacd7dcc16ed61122aa Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 11:55:09 +0100 Subject: [PATCH 085/136] Renamed `root` --> `paths` --- minerva/datasets/factory.py | 18 +++++++++--------- minerva/inbuilt_cfgs/example_3rd_party.yml | 14 +++++++------- minerva/inbuilt_cfgs/example_CNN_config.yml | 12 ++++++------ minerva/inbuilt_cfgs/example_GeoCLR_config.yml | 12 ++++++------ minerva/inbuilt_cfgs/example_GeoSimConvNet.yml | 12 ++++++------ minerva/inbuilt_cfgs/example_UNetR_config.yml | 12 ++++++------ .../example_autoencoder_config.yml | 12 ++++++------ minerva/inbuilt_cfgs/example_config.yml | 14 +++++++------- minerva/inbuilt_cfgs/exp_mf_config.yml | 4 ++-- tests/conftest.py | 2 +- tests/test_datasets/test_dataset_utils.py | 4 ++-- tests/test_datasets/test_factory.py | 2 +- tests/test_datasets/test_paired.py | 6 +++--- tests/test_samplers.py | 4 ++-- 14 files changed, 64 insertions(+), 64 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 76e29ad42..4cefa60d7 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -120,17 +120,17 @@ def get_subdataset( module_path=sub_dataset_params["module"], func=sub_dataset_params["name"] ) - # Construct the root to the sub-dataset's files. - sub_dataset_root: Path = ( - universal_path(data_directory) / sub_dataset_params["root"] + # Construct the paths to the sub-dataset's files. + sub_dataset_path: Path = ( + universal_path(data_directory) / sub_dataset_params["paths"] ) - sub_dataset_root = sub_dataset_root.absolute() + sub_dataset_path = sub_dataset_path.absolute() - return _sub_dataset, str(sub_dataset_root) + return _sub_dataset, str(sub_dataset_path) def create_subdataset( dataset_class: Callable[..., GeoDataset], - root: str, + paths: str, subdataset_params: Dict[Literal["params"], Dict[str, Any]], _transformations: Optional[Any], ) -> GeoDataset: @@ -142,13 +142,13 @@ def create_subdataset( if sample_pairs: return PairedDataset( dataset_class, - root, + paths, transforms=_transformations, **copy_params["params"], ) else: return dataset_class( - root, + paths, transforms=_transformations, **copy_params["params"], ) @@ -171,7 +171,7 @@ def create_subdataset( master_transforms: Optional[Any] = None for area_key in type_dataset_params.keys(): # If any of these keys are present, this must be a parameter set for a singular dataset at this level. - if area_key in ("module", "name", "params", "root"): + if area_key in ("module", "name", "params", "paths"): multi_datasets_exist = False continue diff --git a/minerva/inbuilt_cfgs/example_3rd_party.yml b/minerva/inbuilt_cfgs/example_3rd_party.yml index 6bd1b218c..565508cdd 100644 --- a/minerva/inbuilt_cfgs/example_3rd_party.yml +++ b/minerva/inbuilt_cfgs/example_3rd_party.yml @@ -109,14 +109,14 @@ tasks: images_1: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 image2: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -126,7 +126,7 @@ tasks: module: minerva.transforms module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -151,7 +151,7 @@ tasks: module: minerva.transforms module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -161,7 +161,7 @@ tasks: module: minerva.transforms module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -186,7 +186,7 @@ tasks: module: minerva.transforms module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -196,7 +196,7 @@ tasks: module: minerva.transforms module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_CNN_config.yml b/minerva/inbuilt_cfgs/example_CNN_config.yml index ead040f07..539fbee16 100644 --- a/minerva/inbuilt_cfgs/example_CNN_config.yml +++ b/minerva/inbuilt_cfgs/example_CNN_config.yml @@ -103,7 +103,7 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: @@ -113,7 +113,7 @@ tasks: mode: modal module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -137,7 +137,7 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -148,7 +148,7 @@ tasks: mode: modal module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -171,7 +171,7 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -182,7 +182,7 @@ tasks: mode: modal module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml index 90c66b882..9fc66d98a 100644 --- a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml +++ b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml @@ -140,13 +140,13 @@ tasks: image1: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 image2: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -173,14 +173,14 @@ tasks: image: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -203,14 +203,14 @@ tasks: image: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml index 0cd2e27d9..699df9aeb 100644 --- a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml +++ b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml @@ -139,13 +139,13 @@ tasks: image1: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 image2: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -174,14 +174,14 @@ tasks: image: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -208,14 +208,14 @@ tasks: image: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_UNetR_config.yml b/minerva/inbuilt_cfgs/example_UNetR_config.yml index b692e093f..26757019f 100644 --- a/minerva/inbuilt_cfgs/example_UNetR_config.yml +++ b/minerva/inbuilt_cfgs/example_UNetR_config.yml @@ -108,13 +108,13 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -140,13 +140,13 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -171,13 +171,13 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_autoencoder_config.yml b/minerva/inbuilt_cfgs/example_autoencoder_config.yml index 2c4ed8237..4c78de953 100644 --- a/minerva/inbuilt_cfgs/example_autoencoder_config.yml +++ b/minerva/inbuilt_cfgs/example_autoencoder_config.yml @@ -109,14 +109,14 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -142,14 +142,14 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -175,14 +175,14 @@ tasks: norm_value: 255 module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/example_config.yml b/minerva/inbuilt_cfgs/example_config.yml index 7df34fa23..ccbb45c29 100644 --- a/minerva/inbuilt_cfgs/example_config.yml +++ b/minerva/inbuilt_cfgs/example_config.yml @@ -100,14 +100,14 @@ tasks: images_1: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 image2: module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -115,7 +115,7 @@ tasks: transforms: false module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -142,7 +142,7 @@ tasks: transforms: false module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -150,7 +150,7 @@ tasks: transforms: false module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 @@ -176,7 +176,7 @@ tasks: transforms: false module: minerva.datasets.__testing name: TstImgDataset - root: NAIP + paths: NAIP params: res: 1.0 @@ -184,7 +184,7 @@ tasks: transforms: false module: minerva.datasets.__testing name: TstMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 diff --git a/minerva/inbuilt_cfgs/exp_mf_config.yml b/minerva/inbuilt_cfgs/exp_mf_config.yml index 5e572def6..b31556360 100644 --- a/minerva/inbuilt_cfgs/exp_mf_config.yml +++ b/minerva/inbuilt_cfgs/exp_mf_config.yml @@ -21,13 +21,13 @@ tasks: image: module: minerva.datasets.__testing name: TestImgDataset - root: NAIP + paths: NAIP params: res: 1.0 mask: module: minerva.datasets.__testing name: TestMaskDataset - root: Chesapeake7 + paths: Chesapeake7 params: res: 1.0 # Collator diff --git a/tests/conftest.py b/tests/conftest.py index cd41f0f66..31619ac7f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -348,7 +348,7 @@ def exp_dataset_params() -> Dict[str, Any]: "transforms": {"AutoNorm": {"length": 12}}, "module": "minerva.datasets.__testing", "name": "TstImgDataset", - "root": "NAIP", + "paths": "NAIP", "params": {"res": 1.0, "crs": 26918}, } } diff --git a/tests/test_datasets/test_dataset_utils.py b/tests/test_datasets/test_dataset_utils.py index 02b7a8db1..2be7515db 100644 --- a/tests/test_datasets/test_dataset_utils.py +++ b/tests/test_datasets/test_dataset_utils.py @@ -65,7 +65,7 @@ def test_make_bounding_box() -> None: def test_intersect_datasets(img_root: Path, lc_root: Path) -> None: - imagery = PairedDataset(TstImgDataset, img_root) - labels = PairedDataset(TstMaskDataset, lc_root) + imagery = PairedDataset(TstImgDataset, str(img_root)) + labels = PairedDataset(TstMaskDataset, str(lc_root)) assert isinstance(mdt.intersect_datasets([imagery, labels]), IntersectionDataset) diff --git a/tests/test_datasets/test_factory.py b/tests/test_datasets/test_factory.py index 9840de3a7..84167f2da 100644 --- a/tests/test_datasets/test_factory.py +++ b/tests/test_datasets/test_factory.py @@ -71,7 +71,7 @@ def test_make_dataset(exp_dataset_params: Dict[str, Any], data_root: Path) -> No exp_dataset_params["mask"] = { "module": "minerva.datasets.__testing", "name": "TstMaskDataset", - "root": "Chesapeake7", + "paths": "Chesapeake7", "params": {"res": 1.0}, } diff --git a/tests/test_datasets/test_paired.py b/tests/test_datasets/test_paired.py index aa5db82fb..991e55ef4 100644 --- a/tests/test_datasets/test_paired.py +++ b/tests/test_datasets/test_paired.py @@ -52,7 +52,7 @@ # TESTS # ===================================================================================================================== def test_paired_datasets(img_root: Path) -> None: - dataset1 = PairedDataset(TstImgDataset, img_root) + dataset1 = PairedDataset(TstImgDataset, str(img_root)) dataset2 = TstImgDataset(str(img_root)) with pytest.raises( @@ -108,8 +108,8 @@ def dataset_test(_dataset) -> None: dataset1 = TstImgDataset(str(img_root)) dataset2 = TstImgDataset(str(img_root)) - dataset3 = PairedDataset(TstImgDataset, img_root) - dataset4 = PairedDataset(TstImgDataset, img_root) + dataset3 = PairedDataset(TstImgDataset, str(img_root)) + dataset4 = PairedDataset(TstImgDataset, str(img_root)) union_dataset1 = PairedDataset(dataset1 | dataset2) union_dataset2 = dataset3 | dataset4 diff --git a/tests/test_samplers.py b/tests/test_samplers.py index ddc8abaad..89dc64a3a 100644 --- a/tests/test_samplers.py +++ b/tests/test_samplers.py @@ -57,7 +57,7 @@ # TESTS # ===================================================================================================================== def test_randompairgeosampler(img_root: Path) -> None: - dataset = PairedDataset(TstImgDataset, img_root, res=1.0) + dataset = PairedDataset(TstImgDataset, str(img_root), res=1.0) sampler = RandomPairGeoSampler(dataset, size=32, length=32, max_r=52) loader: DataLoader[Dict[str, Any]] = DataLoader( @@ -73,7 +73,7 @@ def test_randompairgeosampler(img_root: Path) -> None: def test_randompairbatchgeosampler(img_root: Path) -> None: - dataset = PairedDataset(TstImgDataset, img_root, res=1.0) + dataset = PairedDataset(TstImgDataset, str(img_root), res=1.0) sampler = RandomPairBatchGeoSampler( dataset, size=32, length=32, batch_size=8, max_r=52, tiles_per_batch=1 From 7c1d31a7db523d0df88a357ce0ce7bfbffb27eb0 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 12:46:09 +0100 Subject: [PATCH 086/136] Ensured kwargs are optional --- minerva/tasks/knn.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 3d18c47f4..bc25516f7 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -177,8 +177,8 @@ def __init__( **params, ) - self.temp = self.params["temp"] - self.k = self.params["k"] + self.temp = self.params.get("temp") + self.k = self.params.get("k") def generate_feature_bank(self) -> Tuple[Tensor, Tensor]: feature_list = [] From 793c11036fa0a1dd9534cfd4708acc9969bc30d7 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 12:50:31 +0100 Subject: [PATCH 087/136] Fixed `get_io_func` bug --- minerva/tasks/core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index aa1540cc5..0623a2a8f 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -150,7 +150,7 @@ class MinervaTask(ABC): """ logger_cls: MinervaTaskLogger = SupervisedTaskLogger - modelio: Callable[..., Any] = sup_tg + model_io_name: str = "sup_tg" def __init__( self, @@ -310,10 +310,11 @@ def get_io_func(self) -> Callable[..., Any]: Returns: ~typing.Callable[..., ~typing.Any]: Model IO function requested from parameters. """ - io_func: Callable[..., Any] = ( - func_by_str("minerva.modelio", self.params["model_io"]) - if "modelio" in self.params - else self.modelio + io_func: Callable[..., Any] = func_by_str( + "minerva.modelio", + utils.fallback_params( + "model_io", self.params, self.global_params, self.model_io_name + ), ) return io_func From 2afdda8d387f728fd531af101037aab7543feae1 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:14:11 +0100 Subject: [PATCH 088/136] Fixed bug with `step_logger_params` --- minerva/logging/tasklog.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index b1b5b371d..523389143 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -109,6 +109,7 @@ def __init__( self.n_batches = n_batches self.batch_size = batch_size self.n_samples = self.n_batches * self.batch_size + self.output_size = output_size self.task_name = task_name @@ -430,11 +431,10 @@ def __init__( sample_pairs: bool = False, **params, ) -> None: - if sample_pairs: - if not step_logger_params: - step_logger_params = {} - if "params" not in step_logger_params: - step_logger_params["params"] = {} + if not step_logger_params: + step_logger_params = {} + if "params" not in step_logger_params: + step_logger_params["params"] = {} step_logger_params["params"]["sample_pairs"] = sample_pairs step_logger_params["params"]["collapse_level"] = sample_pairs @@ -471,9 +471,6 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: * self.output_size[0] * self.output_size[1] ) - print(f"{self.n_batches=}") - print(f"{self.batch_size=}") - print(f"{self.output_size=}") self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] From 4cc0022613b93770f3aee14914815dbf9302e965 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:16:28 +0100 Subject: [PATCH 089/136] Use `fallback_params` for `make_logger` --- minerva/tasks/core.py | 22 +++++++++++++++------- minerva/tasks/epoch.py | 2 +- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 0623a2a8f..2fbf0eb08 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -149,7 +149,7 @@ class MinervaTask(ABC): .. versionadded:: 0.27 """ - logger_cls: MinervaTaskLogger = SupervisedTaskLogger + logger_cls: str = "SupervisedTaskLogger" model_io_name: str = "sup_tg" def __init__( @@ -175,6 +175,11 @@ def __init__( loaders, n_batches, class_dist, new_params = make_loaders( rank, world_size, task_name=name, **global_params ) + + # If there are multiple modes and therefore number of batches, just take the value of the first one. + if isinstance(n_batches, dict): + n_batches = n_batches.values()[0] + global_params["tasks"][name] = new_params self.global_params = global_params @@ -281,19 +286,22 @@ def make_logger(self) -> MinervaTaskLogger: """ # Gets constructor of the metric logger from name in the config. - self.logger_cls = ( - func_by_str("minerva.logging.tasklog", self.params["logger"]) - if "logger" in self.params - else self.logger_cls + _logger_cls = func_by_str( + "minerva.logging.tasklog", + utils.fallback_params( + "task_logger", self.params, self.global_params, self.logger_cls + ), ) # Initialises the metric logger with arguments. - logger: MinervaTaskLogger = self.logger_cls( + logger: MinervaTaskLogger = _logger_cls( self.name, self.n_batches, self.batch_size, self.output_size, - step_logger_params=self.params.get("step_logger"), + step_logger_params=utils.fallback_params( + "step_logger", self.params, self.global_params, {} + ), record_int=self.record_int, record_float=self.record_float, writer=self.writer, diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index bbaaa7f4c..935e72ec9 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -60,7 +60,7 @@ class StandardEpoch(MinervaTask): .. versionadded:: 0.27 """ - logger_cls = SupervisedTaskLogger + logger_cls = "SupervisedTaskLogger" def step(self) -> None: # Initialises a progress bar for the epoch. From 3f9ef0b56d235f71baf1b65fb6e8f6cfd60b71c4 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:17:52 +0100 Subject: [PATCH 090/136] Use `features` and `test` for KNN modes --- .../inbuilt_cfgs/example_GeoCLR_config.yml | 68 +++++++++++++------ .../inbuilt_cfgs/example_GeoSimConvNet.yml | 62 +++++++++++------ minerva/tasks/knn.py | 11 ++- 3 files changed, 94 insertions(+), 47 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml index 9fc66d98a..79d94b6aa 100644 --- a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml +++ b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml @@ -99,7 +99,8 @@ tasks: # ---+ Minerva Inbuilt Logging Functions +------------------------- task_logger: SSLTaskLogger - step_logger: SSLStepLogger + step_logger: + name: SSLStepLogger model_io: ssl_pair_tg # ---+ Dataset Parameters +---------------------------------------- @@ -157,32 +158,57 @@ tasks: # ---+ Minerva Inbuilt Logging Functions +------------------------- task_logger: SSLTaskLogger - step_logger: KNNStepLogger + step_logger: + name: KNNStepLogger model_io: ssl_pair_tg # ---+ Dataset Parameters +---------------------------------------- dataset_params: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 + features: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 - image: - module: minerva.datasets.__testing - name: TstImgDataset - paths: NAIP - params: - res: 1.0 + image: + module: minerva.datasets.__testing + name: TstImgDataset + paths: NAIP + params: + res: 1.0 - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - paths: Chesapeake7 - params: - res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + paths: Chesapeake7 + params: + res: 1.0 + + test: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + module: minerva.datasets.__testing + name: TstImgDataset + paths: NAIP + params: + res: 1.0 + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + paths: Chesapeake7 + params: + res: 1.0 test-test: type: StandardEpoch diff --git a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml index 699df9aeb..9373ba982 100644 --- a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml +++ b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml @@ -163,27 +163,51 @@ tasks: # ---+ Dataset Parameters +---------------------------------------- dataset_params: - sampler: - module: torchgeo.samplers - name: RandomGeoSampler - roi: false - params: - size: *patch_size - length: 32 + features: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 - image: - module: minerva.datasets.__testing - name: TstImgDataset - paths: NAIP - params: - res: 1.0 + image: + module: minerva.datasets.__testing + name: TstImgDataset + paths: NAIP + params: + res: 1.0 - mask: - module: minerva.datasets.__testing - name: TstMaskDataset - paths: Chesapeake7 - params: - res: 1.0 + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + paths: Chesapeake7 + params: + res: 1.0 + + test: + sampler: + module: torchgeo.samplers + name: RandomGeoSampler + roi: false + params: + size: *patch_size + length: 32 + + image: + module: minerva.datasets.__testing + name: TstImgDataset + paths: NAIP + params: + res: 1.0 + + mask: + module: minerva.datasets.__testing + name: TstMaskDataset + paths: Chesapeake7 + params: + res: 1.0 test-test: type: StandardEpoch diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index bc25516f7..e8902a0c4 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -57,7 +57,7 @@ from minerva.logging import SSLTaskLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese -from minerva.utils import AUX_CONFIGS, utils +from minerva.utils import utils from .core import MinervaTask @@ -184,7 +184,7 @@ def generate_feature_bank(self) -> Tuple[Tensor, Tensor]: feature_list = [] target_list = [] - feat_bar = alive_it(self.loaders["val"]) + feat_bar = alive_it(self.loaders["features"]) for batch in feat_bar: val_data: Tensor = batch["image"].to(self.device, non_blocking=True) val_target: Tensor = batch["mask"].to(self.device, non_blocking=True) @@ -230,9 +230,6 @@ def step(self) -> None: # Puts the model in evaluation mode so no back passes are made. self.model.eval() - # Get the number of classes from the data config. - n_classes = len(AUX_CONFIGS["data_config"]["classes"]) - total_num = 0 with torch.no_grad(): @@ -285,7 +282,7 @@ def step(self) -> None: # Counts for each class one_hot_label = torch.zeros( - test_data.size(0) * self.k, n_classes, device=sim_labels.device + test_data.size(0) * self.k, self.n_classes, device=sim_labels.device ) # [B*K, C] @@ -295,7 +292,7 @@ def step(self) -> None: # Weighted score ---> [B, C] pred_scores = torch.sum( - one_hot_label.view(test_data.size(0), -1, n_classes) + one_hot_label.view(test_data.size(0), -1, self.n_classes) * sim_weight.unsqueeze(dim=-1), dim=1, ) From 5ee0f632e5e0dac7f78482ffe83c56200fa41593 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:32:32 +0100 Subject: [PATCH 091/136] Added missing call to `calc_metrics` --- minerva/tasks/core.py | 2 +- minerva/tasks/epoch.py | 1 - minerva/tasks/knn.py | 30 ++++++++++-------------------- 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 2fbf0eb08..581f59753 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -178,7 +178,7 @@ def __init__( # If there are multiple modes and therefore number of batches, just take the value of the first one. if isinstance(n_batches, dict): - n_batches = n_batches.values()[0] + n_batches = next(iter(n_batches.values())) global_params["tasks"][name] = new_params diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index 935e72ec9..db0ccaba9 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -45,7 +45,6 @@ import torch.distributed as dist from alive_progress import alive_bar -from minerva.logging import SupervisedTaskLogger from minerva.utils import utils from .core import MinervaTask diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index e8902a0c4..640608420 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -86,8 +86,6 @@ class WeightedKNN(MinervaTask): modes (tuple[str, ...]): The different *modes* of fitting in this experiment specified by the config. writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wandb_run.Run | None): The *writer* to perform logging for this experiment. For use with either :mod:`tensorboard` or :mod:`wandb`. - stopper (~pytorchtools.EarlyStopping | None): Early stopping function. - early_stop (bool): Whether early stopping has been triggered. Will end model training if ``True``. n_samples (dict[str, int]): Number of samples in each mode of model fitting. metric_logger (~logger.MinervaLogger): Object to calculate and log metrics to track the performance of the model. @@ -102,6 +100,9 @@ class WeightedKNN(MinervaTask): writer (~wandb.sdk.wandb_run.Run | RunDisabled): Optional; Run object for Weights and Biases. params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be constructed, trained and evaluated. These should be defined via config ``YAML`` files. + record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. + record_float (bool): Store the floating point results of each epoch in memory + such as the raw predicted probabilities. Keyword Args: batch_size (int): Number of samples in each batch. @@ -115,12 +116,6 @@ class WeightedKNN(MinervaTask): Contains the ``module`` key to define the import path and the ``name`` key for name of the collation function. sample_pairs (bool): Activates paired sampling for Siamese models. Only used for ``train`` datasets. - stopping (dict[str, ~typing.Any]): Dictionary to hold the parameters defining the early stopping functionality. - If no dictionary is given, it is assumed that there will be no early stopping. - pre_train_name (str): Name of the pre-trained model to use. - reload (bool): Reloads the weights in the cache matching ``pre_train_name`` to continue model fitting. - loss_func (str): Name of the loss function to use. - optim_func (str): Name of the optimiser function to use. lr (float): Learning rate of optimiser. optim_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the optimiser, other than the already handled learning rate -- ``lr``. Place them in the ``params`` key. @@ -131,18 +126,8 @@ class WeightedKNN(MinervaTask): balance (bool): Activates class balancing. For ``model_type="scene classifer"`` or ``model_type="mlp"``, over and under sampling will be used. For ``model_type="segmentation"``, class weighting will be used on the loss function. - patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. - input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. - Should align with the values given for ``patch_size``. - metrics (str): Specify the metric logger to use. Must be the name of a :class:`~metrics.MinervaMetric` class - within :mod:`metrics`. - logger (str): Specify the logger to use. Must be the name of a :class:`~logger.MinervaLogger` class - within :mod:`logger`. modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name of a function within :mod:`modelio`. - record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. - record_float (bool): Store the floating point results of each epoch in memory - such as the raw predicted probabilities. .. versionadded:: 0.27 """ @@ -161,6 +146,8 @@ def __init__( writer: Optional[Union[SummaryWriter, Run]] = None, record_int: bool = True, record_float: bool = False, + k: int = 5, + temp: float = 0.5, **params, ) -> None: super().__init__( @@ -177,8 +164,8 @@ def __init__( **params, ) - self.temp = self.params.get("temp") - self.k = self.params.get("k") + self.temp = temp + self.k = k def generate_feature_bank(self) -> Tuple[Tensor, Tensor]: feature_list = [] @@ -318,3 +305,6 @@ def step(self) -> None: # Update global step number for this mode of model fitting. self.step_num += 1 + + # Updates metrics with epoch results. + self.logger.calc_metrics() From 48c4385f971670540c0388abeeb3d68b29c9d597 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:52:01 +0100 Subject: [PATCH 092/136] Fixed `step_logger_params` use --- .../example_autoencoder_config.yml | 3 ++- minerva/logging/tasklog.py | 24 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_autoencoder_config.yml b/minerva/inbuilt_cfgs/example_autoencoder_config.yml index 4c78de953..9e978c369 100644 --- a/minerva/inbuilt_cfgs/example_autoencoder_config.yml +++ b/minerva/inbuilt_cfgs/example_autoencoder_config.yml @@ -74,7 +74,8 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== # ---+ Minerva Inbuilt Logging Functions +------------------------------------- task_logger: SupervisedTaskLogger -step_logger: SupervisedGeoStepLogger +step_logger: + name: SupervisedGeoStepLogger model_io: sup_tg record_int: true # Store integer results in memory. diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index 523389143..bd72713d7 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -42,7 +42,7 @@ # ===================================================================================================================== import abc from abc import ABC -from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter @@ -55,12 +55,7 @@ from minerva.utils.utils import check_substrings_in_string -from .steplog import ( - MinervaStepLogger, - SSLStepLogger, - SupervisedGeoStepLogger, - get_logger, -) +from .steplog import get_logger # ===================================================================================================================== @@ -90,7 +85,7 @@ class MinervaTaskLogger(ABC): metric_types: List[str] = [] special_metric_types: List[str] = [] - logger_cls: Callable[..., MinervaStepLogger] + logger_cls: str def __init__( self, @@ -122,9 +117,12 @@ def __init__( self.writer = writer - if step_logger_params: - if step_logger_params.get("name") is not None: - self.logger_cls = get_logger(step_logger_params["name"]) + if isinstance(step_logger_params, dict): + self.logger_cls = get_logger( + step_logger_params.get("name", self.logger_cls) + ) + if "params" not in step_logger_params: + step_logger_params["params"] = {} else: step_logger_params = {"params": {}} @@ -304,7 +302,7 @@ class SupervisedTaskLogger(MinervaTaskLogger): """ metric_types: List[str] = ["loss", "acc", "miou"] - logger_cls = SupervisedGeoStepLogger + logger_cls = "SupervisedGeoStepLogger" def __init__( self, @@ -415,7 +413,7 @@ class SSLTaskLogger(MinervaTaskLogger): metric_types = ["loss", "acc", "top5_acc"] special_metric_types = ["collapse_level", "euc_dist"] - logger_cls = SSLStepLogger + logger_cls = "SSLStepLogger" def __init__( self, From a80a58d51852deb32441114d490102b79f9f0aa5 Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 12 Oct 2023 15:54:17 +0100 Subject: [PATCH 093/136] Removed debug print statement --- minerva/logging/tasklog.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/minerva/logging/tasklog.py b/minerva/logging/tasklog.py index bd72713d7..f646d35b8 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logging/tasklog.py @@ -463,13 +463,6 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: ) if check_substrings_in_string(self.model_type, "segmentation"): - print( - self.n_batches - * self.batch_size - * self.output_size[0] - * self.output_size[1] - ) - self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] / ( From 6ee299918698414862ef0feba9e7870a07ebf029 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 13 Oct 2023 17:02:36 +0100 Subject: [PATCH 094/136] Fixed path issues --- minerva/tasks/core.py | 5 ++++- minerva/trainer.py | 8 +++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 581f59753..52bfad1b5 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -427,13 +427,16 @@ def compute_classification_report( # Uses utils to create a classification report in a DataFrame. cr_df = utils.make_classification_report(preds, targets, self.params["classes"]) + # Ensure the parent directories for the classification report exist. + self.task_fn.parent.mkdir(parents=True, exist_ok=True) + # Saves classification report DataFrame to a .csv file at fn. cr_df.to_csv(f"{self.task_fn}_classification-report.csv") def save_metrics(self) -> None: print("\nSAVING METRICS TO FILE") try: - metrics = self.get_metrics() + metrics = self.get_metrics metrics_df = pd.DataFrame( {key: metrics[key]["y"] for key in metrics.keys()} ) diff --git a/minerva/trainer.py b/minerva/trainer.py index 1c1c97830..41b173f33 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -275,16 +275,14 @@ def __init__( self.params["model_name"], self.params["timestamp"] ) + # Path to experiment directory and experiment name. self.params["dir"]["results"] = universal_path(self.params["dir"]["results"]) - results_dir = self.params["dir"]["results"] / self.params["exp_name"] + self.exp_fn: Path = self.params["dir"]["results"] / self.params["exp_name"] if self.gpu == 0: # Makes a directory for this experiment. utils.mkexpdir(self.params["exp_name"]) - # Path to experiment directory and experiment name. - self.exp_fn: Path = results_dir / self.params["exp_name"] - self.writer: Optional[Union[SummaryWriter, Run]] = None if self.params.get("wandb_log", False): # Sets the `wandb` run object (or None). @@ -294,7 +292,7 @@ def __init__( assert TENSORBOARD_WRITER # Initialise TensorBoard logger. - self.writer = TENSORBOARD_WRITER(results_dir) + self.writer = TENSORBOARD_WRITER(self.exp_fn) else: # pragma: no cover self.writer = None From 1f199e59b16d2c6fbcfb0c0453b2f58a637791a8 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 13 Oct 2023 18:00:36 +0100 Subject: [PATCH 095/136] Fixed the length size of samplers --- minerva/inbuilt_cfgs/example_autoencoder_config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_autoencoder_config.yml b/minerva/inbuilt_cfgs/example_autoencoder_config.yml index 9e978c369..ad03d0074 100644 --- a/minerva/inbuilt_cfgs/example_autoencoder_config.yml +++ b/minerva/inbuilt_cfgs/example_autoencoder_config.yml @@ -76,7 +76,7 @@ wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. task_logger: SupervisedTaskLogger step_logger: name: SupervisedGeoStepLogger -model_io: sup_tg +model_io: autoencoder_io record_int: true # Store integer results in memory. record_float: false # Store floating point results too. Beware memory overload! @@ -101,7 +101,7 @@ tasks: roi: false params: size: *patch_size - length: 32 + length: 36 image: transforms: @@ -134,7 +134,7 @@ tasks: roi: false params: size: *patch_size - length: 16 + length: 18 image: transforms: @@ -167,7 +167,7 @@ tasks: roi: false params: size: *patch_size - length: 16 + length: 18 image: transforms: From e11d80a11acd65bf23441c25f08a43c6fb92b24a Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 13 Oct 2023 19:10:26 +0100 Subject: [PATCH 096/136] Fixed tests for TSNE Visualisation --- minerva/inbuilt_cfgs/example_GeoCLR_config.yml | 11 ++++++----- minerva/tasks/tsne.py | 2 -- minerva/trainer.py | 6 +++--- tests/test_trainer.py | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml index 79d94b6aa..879889571 100644 --- a/minerva/inbuilt_cfgs/example_GeoCLR_config.yml +++ b/minerva/inbuilt_cfgs/example_GeoCLR_config.yml @@ -76,11 +76,6 @@ project: pytest # Define the project name for wandb. wandb_dir: /test/tmp/wandb # Directory to store wandb logs locally. # === MODEL IO & LOGGING ====================================================== -# ---+ Minerva Inbuilt Logging Functions +------------------------------------- -task_logger: SSLTaskLogger -step_logger: SSLStepLogger -model_io: ssl_pair_tg - record_int: true # Store integer results in memory. record_float: true # Store floating point results too. Beware memory overload! @@ -155,6 +150,7 @@ tasks: type: WeightedKNN train: false sample_pairs: false + n_classes: 8 # ---+ Minerva Inbuilt Logging Functions +------------------------- task_logger: SSLTaskLogger @@ -215,6 +211,11 @@ tasks: train: false record_float: true sample_pairs: false + n_classes: 8 + + # ---+ Minerva Inbuilt Logging Functions +------------------------- + task_logger: SupervisedTaskLogger + model_io: sup_tg # ---+ Dataset Parameters +---------------------------------------- dataset_params: diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 9b9d1d225..6f1fb7975 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -88,8 +88,6 @@ def __init__( record_float, **params, ) - if self.params.get("data", None): - self.loaders["test"] = self.params["data"] def step(self) -> None: """Perform TSNE clustering on the embeddings from the model and visualise. diff --git a/minerva/trainer.py b/minerva/trainer.py index 41b173f33..910c1fc37 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -713,22 +713,22 @@ def test(self, save: bool = True, show: bool = False) -> None: "providing the path to this experiment's results directory and unique experiment ID" ) - def tsne_cluster(self) -> None: + def tsne_cluster(self, task_name: str = "TSNEVis") -> None: """Perform TSNE clustering on the embeddings from the model and visualise. Passes a batch from the test dataset through the model in eval mode to get the embeddings. Passes these embeddings to :mod:`visutils` to train a TSNE algorithm and then visual the cluster. """ task = TSNEVis( - "TSNEVis", + task_name, self.model, - self.batch_size, self.device, self.exp_fn, self.gpu, self.rank, self.world_size, self.writer, + **self.params, ) task(1) diff --git a/tests/test_trainer.py b/tests/test_trainer.py index b6c8aad55..be9ebe2fe 100644 --- a/tests/test_trainer.py +++ b/tests/test_trainer.py @@ -183,7 +183,7 @@ def test_trainer_4( if kwargs.get("tsne_cluster"): trainer.model = trainer.model.get_backbone() # type: ignore[assignment, operator] - trainer.tsne_cluster() + trainer.tsne_cluster("test-test") if kwargs.get("test"): trainer.test() From fca87fd48a1a7a9cbeadc7ff9cea512c16005a8a Mon Sep 17 00:00:00 2001 From: Harry Date: Sat, 14 Oct 2023 22:31:49 +0100 Subject: [PATCH 097/136] Bypass class balancing and elimination --- minerva/inbuilt_cfgs/example_CNN_config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_CNN_config.yml b/minerva/inbuilt_cfgs/example_CNN_config.yml index 539fbee16..af408a4a1 100644 --- a/minerva/inbuilt_cfgs/example_CNN_config.yml +++ b/minerva/inbuilt_cfgs/example_CNN_config.yml @@ -32,8 +32,8 @@ n_classes: &n_classes 8 # Number of classes in dataset. # ---+ Experiment Execution +-------------------------------------------------- max_epochs: 3 # Maximum number of training epochs. -elim: true # Eliminates empty classes from schema. -balance: true # Balances dataset classes. +elim: false # Eliminates empty classes from schema. +balance: false # Balances dataset classes. pre_train: false # Activate pre-training mode. fine_tune: false # Activate fine-tuning mode. From 8b07c00426fc51941ff06d6b28128ce4c81f305f Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 01:14:19 +0100 Subject: [PATCH 098/136] Renamed `logging` --> `logger` to avoid inbuilt conflict --- minerva/{logging => logger}/__init__.py | 2 +- minerva/{logging => logger}/steplog.py | 2 +- minerva/{logging => logger}/tasklog.py | 8 +++----- minerva/tasks/core.py | 5 ++--- minerva/tasks/knn.py | 4 ++-- tests/test_logging.py | 18 +++++++++--------- 6 files changed, 18 insertions(+), 21 deletions(-) rename minerva/{logging => logger}/__init__.py (95%) rename minerva/{logging => logger}/steplog.py (99%) rename minerva/{logging => logger}/tasklog.py (98%) diff --git a/minerva/logging/__init__.py b/minerva/logger/__init__.py similarity index 95% rename from minerva/logging/__init__.py rename to minerva/logger/__init__.py index 2b9e0d23d..77ad10852 100644 --- a/minerva/logging/__init__.py +++ b/minerva/logger/__init__.py @@ -23,7 +23,7 @@ # # @org: University of Southampton # Created under a project funded by the Ordnance Survey Ltd. -""":mod:`logging` contains functionality for logging and analysing results within :mod:`minerva`""" +""":mod:`minerva.logger` contains functionality for logging and analysing results within :mod:`minerva`""" # ===================================================================================================================== # METADATA # ===================================================================================================================== diff --git a/minerva/logging/steplog.py b/minerva/logger/steplog.py similarity index 99% rename from minerva/logging/steplog.py rename to minerva/logger/steplog.py index 588e18e22..b5ebab98a 100644 --- a/minerva/logging/steplog.py +++ b/minerva/logger/steplog.py @@ -130,7 +130,7 @@ def __init__( task_name: str, n_batches: int, batch_size: int, - output_size: int, + output_size: Tuple[int, int], record_int: bool = True, record_float: bool = False, writer: Optional[Union[SummaryWriter, Run]] = None, diff --git a/minerva/logging/tasklog.py b/minerva/logger/tasklog.py similarity index 98% rename from minerva/logging/tasklog.py rename to minerva/logger/tasklog.py index f646d35b8..62a0cc323 100644 --- a/minerva/logging/tasklog.py +++ b/minerva/logger/tasklog.py @@ -55,7 +55,7 @@ from minerva.utils.utils import check_substrings_in_string -from .steplog import get_logger +from .steplog import MinervaStepLogger, get_logger # ===================================================================================================================== @@ -118,9 +118,7 @@ def __init__( self.writer = writer if isinstance(step_logger_params, dict): - self.logger_cls = get_logger( - step_logger_params.get("name", self.logger_cls) - ) + self._logger = get_logger(step_logger_params.get("name", self.logger_cls)) if "params" not in step_logger_params: step_logger_params["params"] = {} @@ -147,7 +145,7 @@ def _make_logger(self) -> None: .. note:: Will overwrite ``self.logger`` with new logger. """ - self.step_logger = self.logger_cls( + self.step_logger: MinervaStepLogger = self._logger( task_name=self.task_name, n_batches=self.n_batches, batch_size=self.batch_size, diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 52bfad1b5..9f6d10956 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -56,8 +56,7 @@ from wandb.sdk.wandb_run import Run from minerva.datasets import make_loaders -from minerva.logging.tasklog import MinervaTaskLogger, SupervisedTaskLogger -from minerva.modelio import sup_tg +from minerva.logger.tasklog import MinervaTaskLogger from minerva.models import MinervaDataParallel, MinervaModel from minerva.utils import utils, visutils from minerva.utils.utils import fallback_params, func_by_str @@ -444,7 +443,7 @@ def save_metrics(self) -> None: # Assumes that the length of each metric is the same. metrics_df["Epoch"] = list(metrics.values())[0]["x"] metrics_df.set_index("Epoch", inplace=True, drop=True) - metrics_df.to_csv(f"{self.exp_fn}_metrics.csv") + metrics_df.to_csv(f"{self.task_fn}_metrics.csv") except (ValueError, KeyError) as err: # pragma: no cover print(err) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 640608420..01450c44b 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -55,7 +55,7 @@ else: # pragma: no cover SummaryWriter = None -from minerva.logging import SSLTaskLogger +from minerva.logger import SSLTaskLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese from minerva.utils import utils @@ -132,7 +132,7 @@ class WeightedKNN(MinervaTask): .. versionadded:: 0.27 """ - logger_cls = SSLTaskLogger + logger_cls = "SSLTaskLogger" def __init__( self, diff --git a/tests/test_logging.py b/tests/test_logging.py index 71d0dc99e..e08f6024f 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -59,7 +59,7 @@ from torch.nn.modules import Module from torchgeo.datasets.utils import BoundingBox -from minerva.logging.tasklog import SSLTaskLogger, SupervisedTaskLogger +from minerva.logger.tasklog import SSLTaskLogger, SupervisedTaskLogger from minerva.loss import SegBarlowTwinsLoss from minerva.modelio import ssl_pair_tg, sup_tg from minerva.models import FCN16ResNet18, MinervaSiamese, SimCLR18, SimConv @@ -122,9 +122,9 @@ def test_SupervisedGeoStepLogger( step_logger_params={"params": {"n_classes": std_n_classes}}, ) - correct_loss = {"x": [], "y": []} - correct_acc = {"x": [], "y": []} - correct_miou = {"x": [], "y": []} + correct_loss: Dict[str, List[float]] = {"x": [], "y": []} + correct_acc: Dict[str, List[float]] = {"x": [], "y": []} + correct_miou: Dict[str, List[float]] = {"x": [], "y": []} for epoch_no in range(n_epochs): print(f"{epoch_no=}") @@ -271,11 +271,11 @@ def test_SSLStepLogger( sample_pairs=True, ) - correct_loss = {"x": [], "y": []} - correct_acc = {"x": [], "y": []} - correct_top5 = {"x": [], "y": []} - correct_collapse_level = {"x": [], "y": []} - correct_euc_dist = {"x": [], "y": []} + correct_loss: Dict[str, List[float]] = {"x": [], "y": []} + correct_acc: Dict[str, List[float]] = {"x": [], "y": []} + correct_top5: Dict[str, List[float]] = {"x": [], "y": []} + correct_collapse_level: Dict[str, List[float]] = {"x": [], "y": []} + correct_euc_dist: Dict[str, List[float]] = {"x": [], "y": []} for epoch_no in range(n_epochs): for i in range(std_n_batches): From de6dfd4e9053b6d5abddc17b1957ccc97ba1f754 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 01:58:33 +0100 Subject: [PATCH 099/136] mypy fixes --- minerva/datasets/factory.py | 8 ++++---- minerva/logger/steplog.py | 2 +- minerva/logger/tasklog.py | 3 ++- minerva/models/__depreciated.py | 2 +- minerva/tasks/core.py | 2 +- minerva/tasks/knn.py | 1 - minerva/trainer.py | 9 +++------ tests/test_logging.py | 24 ++++++++---------------- tests/test_models/test_core.py | 2 ++ tests/test_models/test_depreciated.py | 2 ++ tests/test_models/test_resnets.py | 1 + 11 files changed, 25 insertions(+), 31 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index 4cefa60d7..66ab372cb 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -507,17 +507,17 @@ def make_loaders( "ClassTransform" ] = class_transform["ClassTransform"] - sampler_params: Dict[str, Any] = dataset_params[mode]["sampler"] + mode_sampler_params: Dict[str, Any] = dataset_params[mode]["sampler"] # Calculates number of batches. - n_batches[mode] = int(sampler_params["params"]["length"] / batch_size) + n_batches[mode] = int(mode_sampler_params["params"]["length"] / batch_size) - # --+ MAKE DATASETS +=========================================================================================+ + # --+ MAKE DATASETS +=====================================================================================+ print(f"CREATING {mode} DATASET") loaders[mode] = construct_dataloader( params["dir"]["data"], dataset_params[mode], - sampler_params, + mode_sampler_params, dataloader_params, batch_size, collator_params=utils.fallback_params("collator", task_params, params), diff --git a/minerva/logger/steplog.py b/minerva/logger/steplog.py index b5ebab98a..c329d8cf8 100644 --- a/minerva/logger/steplog.py +++ b/minerva/logger/steplog.py @@ -741,5 +741,5 @@ def get_logger(name) -> Callable[..., Any]: .. versionadded:: 0.27 """ - logger: Callable[..., Any] = func_by_str("minerva.logging.steplog", name) + logger: Callable[..., Any] = func_by_str("minerva.logger.steplog", name) return logger diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index 62a0cc323..9ef2b41c1 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -76,7 +76,8 @@ class MinervaTaskLogger(ABC): n_batches (dict[str, int]): Dictionary of the number of batches in each mode of fitting. batch_size (int): Batch size. data_size (tuple[int, int, int]): Shape of the input data in ``C x H x W``. - logger_params (dict[str, ~typing.Any]): Optional; Parameters for a logger other than the default for these metrics. + logger_params (dict[str, ~typing.Any]): Optional; Parameters for a logger + other than the default for these metrics. .. versionadded:: 0.27 """ diff --git a/minerva/models/__depreciated.py b/minerva/models/__depreciated.py index 60dd66259..00cc3194e 100644 --- a/minerva/models/__depreciated.py +++ b/minerva/models/__depreciated.py @@ -37,7 +37,7 @@ # IMPORTS # ===================================================================================================================== from collections import OrderedDict -from typing import Any, Iterable, List, Optional, Sequence, Tuple, Union +from typing import Any, List, Optional, Sequence, Tuple, Union import numpy as np import torch.nn.modules as nn diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 9f6d10956..21f0458ca 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -286,7 +286,7 @@ def make_logger(self) -> MinervaTaskLogger: # Gets constructor of the metric logger from name in the config. _logger_cls = func_by_str( - "minerva.logging.tasklog", + "minerva.logger.tasklog", utils.fallback_params( "task_logger", self.params, self.global_params, self.logger_cls ), diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 01450c44b..942a7846b 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -55,7 +55,6 @@ else: # pragma: no cover SummaryWriter = None -from minerva.logger import SSLTaskLogger from minerva.models import MinervaDataParallel, MinervaModel, MinervaSiamese from minerva.utils import utils diff --git a/minerva/trainer.py b/minerva/trainer.py index 910c1fc37..a93741507 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -41,14 +41,11 @@ import os from copy import deepcopy from pathlib import Path -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Sequence, Tuple, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Union -import pandas as pd import torch import yaml from inputimeout import TimeoutOccurred, inputimeout -from nptyping import Int, NDArray -from torch import Tensor from torch.nn.modules import Module from torch.nn.parallel import DistributedDataParallel as DDP @@ -68,7 +65,7 @@ ) from minerva.pytorchtools import EarlyStopping from minerva.tasks import MinervaTask, TSNEVis, get_task -from minerva.utils import universal_path, utils, visutils +from minerva.utils import universal_path, utils # ===================================================================================================================== # GLOBALS @@ -585,7 +582,7 @@ def fit(self) -> None: self.print("\nEarly stopping triggered") # Create a subset of metrics for plotting model history. - fit_metrics = {} + fit_metrics: Dict[str, Any] = {} for mode in tasks.keys(): fit_metrics = {**fit_metrics, **tasks[mode].get_metrics} diff --git a/tests/test_logging.py b/tests/test_logging.py index e08f6024f..4c955d2f0 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -202,11 +202,11 @@ def test_SupervisedGeoStepLogger( metrics = logger.get_metrics - assert metrics[f"pytest_loss"] == pytest.approx(correct_loss) - assert metrics[f"pytest_acc"] == pytest.approx(correct_acc) + assert metrics["pytest_loss"] == pytest.approx(correct_loss) + assert metrics["pytest_acc"] == pytest.approx(correct_acc) if model_type == "segmentation": - assert metrics[f"pytest_miou"] == pytest.approx(correct_miou) + assert metrics["pytest_miou"] == pytest.approx(correct_miou) logger._make_logger() @@ -341,23 +341,15 @@ def test_SSLStepLogger( metrics = logger.get_metrics - print(metrics) - print(correct_loss) - print(correct_acc) - print(correct_top5) - - assert metrics[f"pytest_loss"] == pytest.approx(correct_loss) - assert metrics[f"pytest_acc"] == pytest.approx(correct_acc) - assert metrics[f"pytest_top5_acc"] == pytest.approx(correct_top5) + assert metrics["pytest_loss"] == pytest.approx(correct_loss) + assert metrics["pytest_acc"] == pytest.approx(correct_acc) + assert metrics["pytest_top5_acc"] == pytest.approx(correct_top5) if extra_metrics: - print(correct_collapse_level) - print(correct_euc_dist) - - assert metrics[f"pytest_collapse_level"] == pytest.approx( + assert metrics["pytest_collapse_level"] == pytest.approx( correct_collapse_level ) - assert metrics[f"pytest_euc_dist"] == pytest.approx(correct_euc_dist) + assert metrics["pytest_euc_dist"] == pytest.approx(correct_euc_dist) logger._make_logger() diff --git a/tests/test_models/test_core.py b/tests/test_models/test_core.py index 097667d63..9568d440a 100644 --- a/tests/test_models/test_core.py +++ b/tests/test_models/test_core.py @@ -92,6 +92,7 @@ def test_minerva_model(x_entropy_loss, std_n_classes: int, std_n_batches: int) - model.set_optimiser(optimiser) model.determine_output_dim() + assert isinstance(model.output_shape, tuple) assert model.output_shape[0] is model.n_classes for train in (True, False): @@ -133,6 +134,7 @@ def test_minerva_wrapper( model.set_optimiser(optimiser) model.determine_output_dim() + assert isinstance(model.output_shape, tuple) assert model.output_shape[0] is model.n_classes x = torch.rand(std_n_batches, *input_size) diff --git a/tests/test_models/test_depreciated.py b/tests/test_models/test_depreciated.py index c8e28d31e..33abe6b06 100644 --- a/tests/test_models/test_depreciated.py +++ b/tests/test_models/test_depreciated.py @@ -54,6 +54,7 @@ def test_mlp(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() + assert isinstance(model.output_shape, tuple) assert model.output_shape[0] is model.n_classes x = torch.rand(16, (288)) @@ -73,6 +74,7 @@ def test_cnn(x_entropy_loss) -> None: model.set_optimiser(optimiser) model.determine_output_dim() + assert isinstance(model.output_shape, tuple) assert model.output_shape[0] is model.n_classes x = torch.rand(6, *input_size) diff --git a/tests/test_models/test_resnets.py b/tests/test_models/test_resnets.py index ab98162e3..1e790d143 100644 --- a/tests/test_models/test_resnets.py +++ b/tests/test_models/test_resnets.py @@ -65,6 +65,7 @@ def resnet_test( model.set_optimiser(optimiser) model.determine_output_dim() + assert isinstance(model.output_shape, tuple) assert model.output_shape[0] is model.n_classes loss, z = model.step(x, y, True) From aefc969013a7dc17528bf42672d30c4d72864f5d Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 17:06:57 +0100 Subject: [PATCH 100/136] Use `staticmethod` wrapper rather than decorator --- minerva/modelio.py | 3 --- minerva/tasks/core.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/minerva/modelio.py b/minerva/modelio.py index d09d8a571..3158005da 100644 --- a/minerva/modelio.py +++ b/minerva/modelio.py @@ -53,7 +53,6 @@ # ===================================================================================================================== # METHODS # ===================================================================================================================== -@staticmethod def sup_tg( batch: Dict[Any, Any], model: MinervaModel, @@ -103,7 +102,6 @@ def sup_tg( return loss, z, y, bbox -@staticmethod def autoencoder_io( batch: Dict[Any, Any], model: MinervaModel, @@ -185,7 +183,6 @@ def autoencoder_io( return loss, z, y, bbox -@staticmethod def ssl_pair_tg( batch: Tuple[Dict[str, Any], Dict[str, Any]], model: MinervaModel, diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 21f0458ca..87d092ce4 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -221,7 +221,7 @@ def __init__( "record_float", self.params, self.global_params, record_float ) - self.modelio = self.get_io_func() + self.modelio = staticmethod(self.get_io_func()) self.loaders = loaders self.device = device From 6b74f2dfe7309cce3d180250ed29b7f178fa60b3 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 17:11:57 +0100 Subject: [PATCH 101/136] `mode` --> `train` --- tests/test_modelio.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/test_modelio.py b/tests/test_modelio.py index c7e82019a..648e4edd1 100644 --- a/tests/test_modelio.py +++ b/tests/test_modelio.py @@ -74,7 +74,7 @@ def test_sup_tg( optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) model.set_optimiser(optimiser) - for mode in ("train", "val", "test"): + for train in (True, False): bboxes = [simple_bbox] * std_batch_size batch: Dict[str, Union[Tensor, List[Any]]] = { "image": random_rgbi_batch, @@ -82,7 +82,7 @@ def test_sup_tg( "bbox": bboxes, } - results = sup_tg(batch, model, default_device, mode) + results = sup_tg(batch, model, default_device, train) assert isinstance(results[0], Tensor) assert isinstance(results[1], Tensor) @@ -106,7 +106,7 @@ def test_ssl_pair_tg( optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) model.set_optimiser(optimiser) - for mode in ("train", "val"): + for train in (True, False): images_1 = torch.rand(size=(std_batch_size, *rgbi_input_size)) bboxes_1 = [simple_bbox] * std_batch_size @@ -123,7 +123,7 @@ def test_ssl_pair_tg( "bbox": bboxes_2, } - results = ssl_pair_tg((batch_1, batch_2), model, default_device, mode) + results = ssl_pair_tg((batch_1, batch_2), model, default_device, train) assert isinstance(results[0], Tensor) assert isinstance(results[1], Tensor) @@ -148,7 +148,7 @@ def test_mask_autoencoder_io( optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) model.set_optimiser(optimiser) - for mode in ("train", "val", "test"): + for train in (True, False): images = torch.rand(size=(std_batch_size, *rgbi_input_size)) masks = torch.randint(0, 8, (std_batch_size, *rgbi_input_size[1:])) # type: ignore[attr-defined] bboxes = [simple_bbox] * std_batch_size @@ -163,11 +163,11 @@ def test_mask_autoencoder_io( match="The value of key='wrong' is not understood. Must be either 'mask' or 'image'", ): autoencoder_io( - batch, model, default_device, mode, autoencoder_data_key="wrong" + batch, model, default_device, train, autoencoder_data_key="wrong" ) results = autoencoder_io( - batch, model, default_device, mode, autoencoder_data_key="mask" + batch, model, default_device, train, autoencoder_data_key="mask" ) assert isinstance(results[0], Tensor) @@ -196,7 +196,7 @@ def test_image_autoencoder_io( optimiser = torch.optim.SGD(model.parameters(), lr=1.0e-3) model.set_optimiser(optimiser) - for mode in ("train", "val", "test"): + for train in (True, False): bboxes = [simple_bbox] * std_batch_size batch: Dict[str, Union[Tensor, List[Any]]] = { "image": random_rgbi_batch, @@ -205,7 +205,7 @@ def test_image_autoencoder_io( } results = autoencoder_io( - batch, model, default_device, mode, autoencoder_data_key="image" + batch, model, default_device, train, autoencoder_data_key="image" ) assert isinstance(results[0], Tensor) From a7d724f677bb602b2c5c3f9f0592edd2d3f78f3d Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 17:18:56 +0100 Subject: [PATCH 102/136] Use `np.prod` to get product of `self.output_size` --- minerva/logger/tasklog.py | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index 9ef2b41c1..c686509eb 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -49,6 +49,7 @@ else: # pragma: no cover SummaryWriter = None +import numpy as np from torch import Tensor from torchgeo.datasets.utils import BoundingBox from wandb.sdk.wandb_run import Run @@ -93,7 +94,7 @@ def __init__( task_name: str, n_batches: int, batch_size: int, - output_size: Tuple[int, int], + output_size: Tuple[int, ...], step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, @@ -308,7 +309,7 @@ def __init__( task_name: str, n_batches: int, batch_size: int, - output_size: Tuple[int, int], + output_size: Tuple[int, ...], step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, @@ -342,12 +343,7 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: if self.model_type == "segmentation": self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] - / ( - self.n_batches - * self.batch_size - * self.output_size[0] - * self.output_size[1] - ) + / (self.n_batches * self.batch_size * np.prod(self.output_size)) ) if logs.get("total_miou") is not None: self.metrics[f"{self.task_name}_miou"]["y"].append( @@ -419,7 +415,7 @@ def __init__( task_name: str, n_batches: int, batch_size: int, - output_size: Tuple[int, int], + output_size: Tuple[int, ...], step_logger_params: Optional[Dict[str, Any]] = None, record_int: bool = True, record_float: bool = False, @@ -464,21 +460,11 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: if check_substrings_in_string(self.model_type, "segmentation"): self.metrics[f"{self.task_name}_acc"]["y"].append( logs["total_correct"] - / ( - self.n_batches - * self.batch_size - * self.output_size[0] - * self.output_size[1] - ) + / (self.n_batches * self.batch_size * np.prod(self.output_size)) ) self.metrics[f"{self.task_name}_top5_acc"]["y"].append( logs["total_top5"] - / ( - self.n_batches - * self.batch_size - * self.output_size[0] - * self.output_size[1] - ) + / (self.n_batches * self.batch_size * np.prod(self.output_size)) ) else: From e668b251459fefcb5c8541d162b8d75039365b10 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 17:30:21 +0100 Subject: [PATCH 103/136] Ensure logged logged float values are floats --- tests/test_logging.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/test_logging.py b/tests/test_logging.py index 4c955d2f0..3d8c193d6 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -127,7 +127,6 @@ def test_SupervisedGeoStepLogger( correct_miou: Dict[str, List[float]] = {"x": [], "y": []} for epoch_no in range(n_epochs): - print(f"{epoch_no=}") data: List[Dict[str, Union[Tensor, List[Any]]]] = [] for i in range(std_n_batches): images = torch.rand(size=(std_batch_size, 4, *small_patch_size)) @@ -183,7 +182,7 @@ def test_SupervisedGeoStepLogger( if utils.check_substrings_in_string(model_type, "segmentation"): correct_acc["y"].append( logs["total_correct"] - / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + / float(std_n_batches * std_batch_size * np.prod(small_patch_size)) ) else: correct_acc["y"].append( @@ -308,17 +307,13 @@ def test_SSLStepLogger( correct_loss["y"].append(logs["total_loss"] / std_n_batches) if utils.check_substrings_in_string(model_type, "segmentation"): - print(std_n_batches * std_batch_size * np.prod(output_shape)) - print(f"{std_n_batches=}") - print(f"{std_batch_size=}") - print(f"{small_patch_size=}") correct_acc["y"].append( logs["total_correct"] - / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + / float(std_n_batches * std_batch_size * np.prod(small_patch_size)) ) correct_top5["y"].append( logs["total_top5"] - / (std_n_batches * std_batch_size * np.prod(small_patch_size)) + / float(std_n_batches * std_batch_size * np.prod(small_patch_size)) ) else: From f1ee454a7b0277627f5e8061c48d39c06e98c773 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 18:03:54 +0100 Subject: [PATCH 104/136] Fixed/ ignored `mypy` issues --- tests/test_logging.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_logging.py b/tests/test_logging.py index 3d8c193d6..a9c9532e9 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -141,7 +141,7 @@ def test_SupervisedGeoStepLogger( } data.append(batch) - logger.step(i, *sup_tg(batch, model, device=default_device, train=train)) + logger.step(i, *sup_tg(batch, model, device=default_device, train=train)) # type: ignore[arg-type] logs = logger.get_logs assert logs["batch_num"] == std_n_batches @@ -284,7 +284,7 @@ def test_SSLStepLogger( logger.step( i, - *ssl_pair_tg((batch, batch), model, device=default_device, train=train), + *ssl_pair_tg((batch, batch), model, device=default_device, train=train), # type: ignore[arg-type] ) logs = logger.get_logs From f3a97967c3b801d8f50ace4a239b30ffb30d3320 Mon Sep 17 00:00:00 2001 From: Harry Date: Sun, 15 Oct 2023 19:18:29 +0100 Subject: [PATCH 105/136] Fixed `staticmethod not callable` error --- minerva/tasks/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 87d092ce4..cf605e60d 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -221,7 +221,7 @@ def __init__( "record_float", self.params, self.global_params, record_float ) - self.modelio = staticmethod(self.get_io_func()) + self.modelio = staticmethod(self.get_io_func()).__func__ self.loaders = loaders self.device = device From 69cb5716ccf1f691a87f59feb6b6fe27796fb729 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:07:41 +0100 Subject: [PATCH 106/136] Added `check_substrings_in_string` and `fallback_params` to `__all__` --- minerva/utils/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index dca9b3478..825532cb6 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -69,6 +69,7 @@ "exist_delete_check", "mkexpdir", "check_dict_key", + "check_substrings_in_string", "datetime_reformat", "get_dataset_name", "transform_coordinates", @@ -105,6 +106,7 @@ "print_config", "tsne_cluster", "calc_norm_euc_dist", + "fallback_params", ] # ===================================================================================================================== @@ -548,7 +550,7 @@ def exist_delete_check(fn: Union[str, Path]) -> None: """Checks if given file exists then deletes if true. Args: - fn (str): Path to file to have existence checked then deleted. + fn (str | ~pathlib.Path): Path to file to have existence checked then deleted. Returns: None From 085f3a77379cf20cb13bf4fd86e6a40b951381be Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:08:33 +0100 Subject: [PATCH 107/136] Reincorporated `save` and `show` arg use --- minerva/tasks/core.py | 6 ++++-- minerva/trainer.py | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index cf605e60d..66d332f54 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -365,6 +365,8 @@ def plot( self, results: Dict[str, Any], metrics: Optional[Dict[str, Any]] = None, + save: bool = True, + show: bool = False, ) -> None: # Gets the dict from params that defines which plots to make from the results. plots = utils.fallback_params( @@ -402,8 +404,8 @@ def plot( "classes", self.params, self.global_params ), colours=utils.fallback_params("colours", self.params, self.global_params), - save=True, - show=False, + save=save, + show=show, model_name=self.params["model_name"], timestamp=self.params["timestamp"], results_dir=self.task_dir, diff --git a/minerva/trainer.py b/minerva/trainer.py index a93741507..5b4a4694a 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -583,8 +583,8 @@ def fit(self) -> None: # Create a subset of metrics for plotting model history. fit_metrics: Dict[str, Any] = {} - for mode in tasks.keys(): - fit_metrics = {**fit_metrics, **tasks[mode].get_metrics} + for _mode in tasks.keys(): + fit_metrics = {**fit_metrics, **tasks[_mode].get_metrics} fit_metrics = { k.replace("fit-", ""): v for k, v in fit_metrics.items() @@ -658,7 +658,7 @@ def test(self, save: bool = True, show: bool = False) -> None: task.compute_classification_report(results["z"], results["y"]) # Plots the results. - task.plot(results) + task.plot(results, save=save, show=show) # Writes the recorded metrics of the task to file. task.save_metrics() From 2abc10b3479bd512ef685e7338ec6e63483e7261 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:08:57 +0100 Subject: [PATCH 108/136] Added `get_logger` to `__all__` --- minerva/logger/steplog.py | 1 + 1 file changed, 1 insertion(+) diff --git a/minerva/logger/steplog.py b/minerva/logger/steplog.py index c329d8cf8..11a41cbbf 100644 --- a/minerva/logger/steplog.py +++ b/minerva/logger/steplog.py @@ -38,6 +38,7 @@ "SupervisedGeoStepLogger", "SSLStepLogger", "KNNStepLogger", + "get_logger", ] # ===================================================================================================================== From 3db7895c55f1825e34b7f4fedcf9f0babf4ff74a Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:09:22 +0100 Subject: [PATCH 109/136] `qodana` fixes --- minerva/logger/tasklog.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index c686509eb..cc100ee76 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -175,7 +175,6 @@ def step( """Abstract method to log a step, using the logger. Must be overwritten. Args: - mode (str): Mode of model fitting. step_num (int): The global step number of for the mode of model fitting. loss (~torch.Tensor): Loss from this step of model fitting. z (~torch.Tensor): Optional; Output tensor from the model. @@ -347,12 +346,12 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: ) if logs.get("total_miou") is not None: self.metrics[f"{self.task_name}_miou"]["y"].append( - logs["total_miou"] / (self.n_samples) + logs["total_miou"] / self.n_samples ) else: self.metrics[f"{self.task_name}_acc"]["y"].append( - logs["total_correct"] / (self.n_samples) + logs["total_correct"] / self.n_samples ) def log_epoch_number(self, epoch_no: int) -> None: @@ -469,10 +468,10 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: else: self.metrics[f"{self.task_name}_acc"]["y"].append( - logs["total_correct"] / (self.n_samples) + logs["total_correct"] / self.n_samples ) self.metrics[f"{self.task_name}_top5_acc"]["y"].append( - logs["total_top5"] / (self.n_samples) + logs["total_top5"] / self.n_samples ) if self.sample_pairs: From 07fa25bcf2b36291aefb56a041e3f3b2ea9e8851 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:09:53 +0100 Subject: [PATCH 110/136] Use `step` not `__call__` --- minerva/tasks/tsne.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 6f1fb7975..679f3be03 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -94,9 +94,6 @@ def step(self) -> None: Passes a batch from the test dataset through the model in eval mode to get the embeddings. Passes these embeddings to :mod:`visutils` to train a TSNE algorithm and then visual the cluster. - - Args: - mode (str): The mode of model fitting that the embeddings come from. """ # Get a batch of data. data = next(iter(self.loaders)) @@ -105,7 +102,7 @@ def step(self) -> None: self.model.eval() # Pass the batch of data through the model to get the embeddings. - embeddings: Tensor = self.model(data["image"].to(self.device))[0] + embeddings: Tensor = self.model.step(data["image"].to(self.device))[0] # Flatten embeddings. embeddings = embeddings.flatten(start_dim=1) From 7a23092940ae572c0dd637d13478238d83406d13 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:13:47 +0100 Subject: [PATCH 111/136] Added missing `task_name` param to docstrings --- minerva/datasets/factory.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index f622d74a7..a480adb17 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -582,6 +582,7 @@ def get_manifest( Args: manifest_path (str | ~pathlib.Path): Path (including filename and extension) to the manifest saved as a ``csv``. + task_name (str): Optional; Name of the task to which the dataset to create a manifest of belongs to. Returns: ~pandas.DataFrame: Manifest either loaded from ``manifest_path`` or created from parameters in :data:`CONFIG`. @@ -616,6 +617,7 @@ def make_manifest( Args: mf_config (dict[~typing.Any, ~typing.Any]): Config to use to construct the manifest with. + task_name (str): Optional; Name of the task to which the dataset to create a manifest of belongs to. Returns: ~pandas.DataFrame: The completed manifest as a :class:`~pandas.DataFrame`. From e9b732dbb59f8ec131f04dc55a0ebedd96479da9 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 00:16:06 +0100 Subject: [PATCH 112/136] Updated `Qodana` baseline --- qodana.sarif.json | 5472 ++++++++++++++++++++++----------------------- 1 file changed, 2676 insertions(+), 2796 deletions(-) diff --git a/qodana.sarif.json b/qodana.sarif.json index bbb604631..364e7fe66 100644 --- a/qodana.sarif.json +++ b/qodana.sarif.json @@ -10,14 +10,14 @@ "version": "232.9876.134", "rules": [], "taxa": [ - { - "id": "Python", - "name": "Python" - }, { "id": "EditorConfig", "name": "EditorConfig" }, + { + "id": "Python", + "name": "Python" + }, { "id": "JavaScript and TypeScript", "name": "JavaScript and TypeScript" @@ -83,8 +83,8 @@ "name": "MongoJS" }, { - "id": "JavaScript and TypeScript/Code style issues", - "name": "Code style issues", + "id": "JavaScript and TypeScript/General", + "name": "General", "relationships": [ { "target": { @@ -101,8 +101,8 @@ ] }, { - "id": "JavaScript and TypeScript/General", - "name": "General", + "id": "JavaScript and TypeScript/Code style issues", + "name": "Code style issues", "relationships": [ { "target": { @@ -644,10 +644,6 @@ "id": "Proofreading", "name": "Proofreading" }, - { - "id": "Jupyter", - "name": "Jupyter" - }, { "id": "CSS/Code quality tools", "name": "Code quality tools", @@ -666,6 +662,10 @@ } ] }, + { + "id": "Jupyter", + "name": "Jupyter" + }, { "id": "PostgreSQL", "name": "PostgreSQL" @@ -704,23 +704,23 @@ }, "extensions": [ { - "name": "Pythonid", + "name": "org.editorconfig.editorconfigjetbrains", "version": "232.9876", "rules": [ { - "id": "PyPandasSeriesToListInspection", + "id": "EditorConfigCharClassRedundancy", "shortDescription": { - "text": "Method Series.to_list() is recommended" + "text": "Unnecessary character class" }, "fullDescription": { - "text": "Reports redundant 'list' in 'list(Series.values)' statement for pandas and polars libraries. Such 'Series' values extraction can be replaced with the 'to_list()' function call. Example: list(df['column'].values)\n When the quick-fix is applied, the code changes to: df['column'].to_list()", - "markdown": "Reports redundant `list` in `list(Series.values)` statement for pandas and polars libraries.\nSuch `Series` values extraction can be replaced with the `to_list()` function call.\n\n**Example:**\n\n```\nlist(df['column'].values)\n```\n\nWhen the quick-fix is applied, the code changes to:\n\n```\ndf['column'].to_list()\n```" + "text": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example '[a]'→'a'.", + "markdown": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example `[a]`→`a`." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyPackages", + "suppressToolId": "EditorConfigCharClassRedundancy", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -728,7 +728,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -741,27 +741,27 @@ ] }, { - "id": "PySetFunctionToLiteralInspection", + "id": "EditorConfigRootDeclarationUniqueness", "shortDescription": { - "text": "Function call can be replaced with set literal" + "text": "Extra top-level declaration" }, "fullDescription": { - "text": "Reports calls to the 'set' function that can be replaced with the 'set' literal. Example: 'def do_mult(a, b):\n c = a * b\n return set([c, a, b])' When the quick-fix is applied, the code changes to: 'def do_mult(a, b):\n c = a * b\n return {c, a, b}'", - "markdown": "Reports calls to the `set` function that can be replaced with\nthe `set` literal.\n\n**Example:**\n\n\n def do_mult(a, b):\n c = a * b\n return set([c, a, b])\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_mult(a, b):\n c = a * b\n return {c, a, b}\n" + "text": "Reports multiple top-level declarations. There can be only one optional “root=true” top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed.", + "markdown": "Reports multiple top-level declarations. There can be only one optional \"root=true\" top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed." }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PySetFunctionToLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigRootDeclarationUniqueness", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -774,28 +774,28 @@ ] }, { - "id": "Query_index_required", + "id": "EditorConfigNumerousWildcards", "shortDescription": { - "text": "Query does not have the required index" + "text": "Too many wildcards" }, "fullDescription": { - "text": "Reports GQL queries for which an index is not defined in 'index.yaml'. Such queries will fail on the production server. The quick-fix allows you to add the necessary index definitions.", - "markdown": "Reports GQL queries for which an index is not defined in `index.yaml`.\nSuch queries will fail on the production server.\nThe quick-fix allows you to add the necessary index definitions." + "text": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues.", + "markdown": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "Query_index_required", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigNumerousWildcards", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Google App Engine (Python)", - "index": 4, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -807,27 +807,27 @@ ] }, { - "id": "PyInitNewSignatureInspection", + "id": "EditorConfigPartialOverride", "shortDescription": { - "text": "Incompatible signatures of __new__ and __init__" + "text": "Overlapping sections" }, "fullDescription": { - "text": "Reports incompatible signatures of the '__new__' and '__init__' methods. Example: 'class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass' If the '__new__' and '__init__' have different arguments, then the 'MyClass' cannot be instantiated. As a fix, the IDE offers to apply the Change Signature refactoring.", - "markdown": "Reports incompatible signatures of the `__new__` and `__init__` methods.\n\n**Example:**\n\n\n class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass\n\nIf the `__new__` and `__init__` have different arguments, then the `MyClass`\ncannot be instantiated.\n\nAs a fix, the IDE offers to apply the Change Signature refactoring." + "text": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: '[{foo,bar}]' and '[{foo,bas}]' both contain “foo”.", + "markdown": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: `[{foo,bar}]` and `[{foo,bas}]` both contain \"foo\"." }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "note", "parameters": { - "suppressToolId": "PyInitNewSignature", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigPartialOverride", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -840,19 +840,19 @@ ] }, { - "id": "EndBlockNamesInspection", + "id": "EditorConfigEmptySection", "shortDescription": { - "text": "Django endblock name doesn't match the block name" + "text": "Empty section" }, "fullDescription": { - "text": "Reports incorrect names of the closing blocks. Example: '{% block my_block %}\n {% endblock not_correct %}'", - "markdown": "Reports incorrect names of the closing blocks.\n\n**Example:**\n\n\n {% block my_block %}\n {% endblock not_correct %}\n" + "text": "Reports sections that do not contain any EditorConfig properties.", + "markdown": "Reports sections that do not contain any EditorConfig properties." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "EndBlockNamesInspection", + "suppressToolId": "EditorConfigEmptySection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -860,8 +860,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -873,19 +873,19 @@ ] }, { - "id": "PyMissingConstructorInspection", + "id": "EditorConfigShadowingOption", "shortDescription": { - "text": "Missed call to '__init__' of the super class" + "text": "Overriding property" }, "fullDescription": { - "text": "Reports cases when a call to the 'super' constructor in a class is missed. Example: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n pass' The 'Pear' class should have a 'super' call in the '__init__' method. When the quick-fix is applied, the code changes to: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n super().__init__()'", - "markdown": "Reports cases when a call to the `super` constructor in a class is missed.\n\n**Example:**\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n pass\n\nThe `Pear` class should have a `super` call in the `__init__`\nmethod.\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n super().__init__()\n" + "text": "Reports properties that override the same properties defined earlier in the file. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes the same files as '[*.java]' but also sets indent_size to value 2. Thus the first declaration 'indent_size=4'will be ignored.", + "markdown": "Reports properties that override the same properties defined earlier in the file.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes the same files as `[*.java]` but also sets indent_size to value 2. Thus the first declaration `indent_size=4`will be ignored." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyMissingConstructor", + "suppressToolId": "EditorConfigShadowingOption", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -893,7 +893,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -906,27 +906,27 @@ ] }, { - "id": "PySimplifyBooleanCheckInspection", + "id": "EditorConfigListAcceptability", "shortDescription": { - "text": "Redundant boolean variable check" + "text": "Unexpected value list" }, "fullDescription": { - "text": "Reports equality comparison with a boolean literal. Example: 'def func(s):\n if s.isdigit() == True:\n return int(s)' With the quick-fix applied, the code fragment will be simplified to: 'def func(s):\n if s.isdigit():\n return int(s)'", - "markdown": "Reports equality comparison with a boolean literal.\n\n**Example:**\n\n\n def func(s):\n if s.isdigit() == True:\n return int(s)\n\nWith the quick-fix applied, the code fragment will be simplified to:\n\n\n def func(s):\n if s.isdigit():\n return int(s)\n" + "text": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified.", + "markdown": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PySimplifyBooleanCheck", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigListAcceptability", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -939,19 +939,19 @@ ] }, { - "id": "PyCallingNonCallableInspection", + "id": "EditorConfigKeyCorrectness", "shortDescription": { - "text": "Attempt to call a non-callable object" + "text": "Unknown property" }, "fullDescription": { - "text": "Reports a problem when you are trying to call objects that are not callable, like, for example, properties: Example: 'class Record:\n @property\n def as_json(self):\n\njson = Record().as_json()'", - "markdown": "Reports a problem when you are trying\nto call objects that are not callable, like, for example, properties:\n\n**Example:**\n\n\n class Record:\n @property\n def as_json(self):\n\n json = Record().as_json()\n" + "text": "Reports properties that are not supported by the IDE. Note: some “ij” domain properties may require specific language plugins.", + "markdown": "Reports properties that are not supported by the IDE. Note: some \"ij\" domain properties may require specific language plugins." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyCallingNonCallable", + "suppressToolId": "EditorConfigKeyCorrectness", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -959,7 +959,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -972,27 +972,27 @@ ] }, { - "id": "PyUnreachableCodeInspection", + "id": "EditorConfigPatternEnumerationRedundancy", "shortDescription": { - "text": "Unreachable code" + "text": "Unnecessary braces" }, "fullDescription": { - "text": "Reports code fragments that cannot be normally reached. Example: 'if True:\n print('Yes')\nelse:\n print('No')' As a fix, you might want to check and modify the algorithm to ensure it implements the expected logic.", - "markdown": "Reports code fragments that cannot be normally reached.\n\n**Example:**\n\n\n if True:\n print('Yes')\n else:\n print('No')\n\nAs a fix, you might want to check and modify the algorithm to ensure it implements\nthe expected logic." + "text": "Reports pattern lists that are either empty '{}' or contain just one pattern, for example '{foo}' in contrast to a list containing multiple patterns, for example '{foo,bar}'. In this case braces are handled as a part of the name. For example, the pattern '*.{a}' will match the file 'my.{a}' but not 'my.a'.", + "markdown": "Reports pattern lists that are either empty `{}` or contain just one pattern, for example `{foo}` in contrast to a list containing multiple patterns, for example `{foo,bar}`. In this case braces are handled as a part of the name. For example, the pattern `*.{a}` will match the file `my.{a}` but not `my.a`." }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PyUnreachableCode", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigPatternEnumerationRedundancy", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1005,27 +1005,27 @@ ] }, { - "id": "PyChainedComparisonsInspection", + "id": "EditorConfigEncoding", "shortDescription": { - "text": "Too complex chained comparisons" + "text": "File encoding doesn't match EditorConfig charset" }, "fullDescription": { - "text": "Reports chained comparisons that can be simplified. Example: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass' The IDE offers to simplify 'if x >= xmin and x <= xmax'. When the quick-fix is applied, the code changes to: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass'", - "markdown": "Reports chained comparisons that can be simplified.\n\n**Example:**\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass\n\nThe IDE offers to simplify `if x >= xmin and x <= xmax`.\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass\n" + "text": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file.", + "markdown": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyChainedComparisons", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigEncoding", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1038,28 +1038,28 @@ ] }, { - "id": "DjangoBrokenLineCommentInspection", + "id": "EditorConfigRootDeclarationCorrectness", "shortDescription": { - "text": "Broken line comment" + "text": "Unexpected top-level declaration" }, "fullDescription": { - "text": "Reports '#}' line comment ends in Django templates that do not have a matching line comment start. Example: 'comment #}' The IDE highlights '#}' as it requires the corresponding '{#' token.", - "markdown": "Reports `#}` line comment ends in Django templates that do not have a\nmatching line comment start.\n\n**Example:**\n\n\n comment #}\n\nThe IDE highlights `#}` as it requires the corresponding `{#` token." + "text": "Reports unexpected top-level declarations. Top-level declarations other than “root=true” are not allowed in the EditorConfig file.", + "markdown": "Reports unexpected top-level declarations. Top-level declarations other than \"root=true\" are not allowed in the EditorConfig file." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "error", "parameters": { - "suppressToolId": "DjangoBrokenLineCommentInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigRootDeclarationCorrectness", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1071,27 +1071,27 @@ ] }, { - "id": "PyCompatibilityInspection", + "id": "EditorConfigReferenceCorrectness", "shortDescription": { - "text": "Code is incompatible with specific Python versions" + "text": "Invalid reference" }, "fullDescription": { - "text": "Reports incompatibility with the specified versions of Python. Enable this inspection if you need your code to be compatible with a range of Python versions, for example, if you are building a library. To define the range of the inspected Python versions, select the corresponding checkboxes in the Options section. For more information about the Python versions supported by the IDE, see the web help.", - "markdown": "Reports incompatibility with the specified versions of Python.\nEnable this inspection if you need your code to be compatible with a range of Python versions, for example,\nif you are building a library.\n\nTo define the range of the inspected Python versions, select the corresponding checkboxes in the **Options**\nsection.\n\nFor more information about the Python versions supported by the IDE, see the\n[web help](https://www.jetbrains.com/help/pycharm/python.html#support)." + "text": "Reports identifiers that are either unknown or have a wrong type.", + "markdown": "Reports identifiers that are either unknown or have a wrong type." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "error", "parameters": { - "suppressToolId": "PyCompatibility", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigReferenceCorrectness", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1104,27 +1104,27 @@ ] }, { - "id": "PyGlobalUndefinedInspection", + "id": "EditorConfigPairAcceptability", "shortDescription": { - "text": "Global variable is not defined at the module level" + "text": "Unexpected key-value pair" }, "fullDescription": { - "text": "Reports problems when a variable defined through the 'global' statement is not defined in the module scope. Example: 'def foo():\n global bar\n print(bar)\n\nfoo()' As a fix, you can move the global variable declaration: 'global bar\n\n\ndef foo():\n print(bar)'", - "markdown": "Reports problems when a variable defined through the `global`\nstatement is not defined in the module scope.\n\n**Example:**\n\n\n def foo():\n global bar\n print(bar)\n\n foo()\n\nAs a fix, you can move the global variable declaration:\n\n\n global bar\n\n\n def foo():\n print(bar)\n" + "text": "Reports key-value pairs that are not allowed in the current context.", + "markdown": "Reports key-value pairs that are not allowed in the current context." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PyGlobalUndefined", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } + "suppressToolId": "EditorConfigPairAcceptability", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" + } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1137,19 +1137,19 @@ ] }, { - "id": "PyProtocolInspection", + "id": "EditorConfigPatternRedundancy", "shortDescription": { - "text": "Invalid protocol definitions and usages" + "text": "Duplicate or redundant pattern" }, "fullDescription": { - "text": "Reports invalid definitions and usages of protocols introduced in PEP-544. Example: 'from typing import Protocol\n\n\nclass MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\nclass MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\nclass MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass'", - "markdown": "Reports invalid definitions and usages of protocols introduced in\n[PEP-544](https://www.python.org/dev/peps/pep-0544/).\n\n**Example:**\n\n\n from typing import Protocol\n\n\n class MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\n class MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\n class MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass\n\n" + "text": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in '[{*.java,*}]' the first '*.java' pattern defines a narrower scope compared to '*'. That is why it is redundant and can be removed.", + "markdown": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in `[{*.java,*}]` the first `*.java` pattern defines a narrower scope compared to `*`. That is why it is redundant and can be removed." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyProtocol", + "suppressToolId": "EditorConfigPatternRedundancy", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1157,7 +1157,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1170,19 +1170,19 @@ ] }, { - "id": "PyTypeHintsInspection", + "id": "EditorConfigNoMatchingFiles", "shortDescription": { - "text": "Invalid type hints definitions and usages" + "text": "No matching files" }, "fullDescription": { - "text": "Reports invalid usages of type hints. Example: 'from typing import TypeVar\n\nT0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\ndef b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\ndef c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass' Available quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown.", - "markdown": "Reports invalid usages of type hints.\n\n**Example:**\n\n\n from typing import TypeVar\n\n T0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\n def b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\n def c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass\n\nAvailable quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown." + "text": "Reports sections with wildcard patterns that do not match any files under the directory in which the '.editorconfig' file is located.", + "markdown": "Reports sections with wildcard patterns that do not match any files under the directory in which the `.editorconfig` file is located." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyTypeHints", + "suppressToolId": "EditorConfigNoMatchingFiles", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1190,7 +1190,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1203,27 +1203,27 @@ ] }, { - "id": "PyMethodMayBeStaticInspection", + "id": "EditorConfigDeprecatedDescriptor", "shortDescription": { - "text": "Method is not declared static" + "text": "Deprecated property" }, "fullDescription": { - "text": "Reports any methods that do not require a class instance creation and can be made static. Example: 'class MyClass(object):\n def my_method(self, x):\n print(x)' If a Make function from method quick-fix is applied, the code changes to: 'def my_method(x):\n print(x)\n\n\nclass MyClass(object):\n pass' If you select the Make method static quick-fix, the '@staticmethod' decorator is added: 'class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)'", - "markdown": "Reports any methods that do not require a class instance creation and can be\nmade static.\n\n**Example:**\n\n\n class MyClass(object):\n def my_method(self, x):\n print(x)\n\nIf a **Make function from method** quick-fix is applied, the code changes to:\n\n\n def my_method(x):\n print(x)\n\n\n class MyClass(object):\n pass\n\nIf you select the **Make method static** quick-fix, the `@staticmethod` decorator is added:\n\n\n class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)\n" + "text": "Reports EditorConfig properties that are no longer supported.", + "markdown": "Reports EditorConfig properties that are no longer supported." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyMethodMayBeStatic", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigDeprecatedDescriptor", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1236,19 +1236,19 @@ ] }, { - "id": "CythonUsageBeforeDeclarationInspection", + "id": "EditorConfigWildcardRedundancy", "shortDescription": { - "text": "Cython variable is used before its declaration" + "text": "Redundant wildcard" }, "fullDescription": { - "text": "Reports Cython variables being referenced before declaration. Example: 'cdef int c_x\n\nprint(c_x, c_y) # Variable 'c_y' is used before its declaration\n\ncdef int c_y = 0'", - "markdown": "Reports Cython variables being referenced before declaration.\n\n**Example:**\n\n\n cdef int c_x\n\n print(c_x, c_y) # Variable 'c_y' is used before its declaration\n\n cdef int c_y = 0\n" + "text": "Reports wildcards that become redundant when the “**” wildcard is used in the same section. The “**” wildcard defines a broader set of files than any other wildcard. That is why, any other wildcard used in the same section has no affect and can be removed.", + "markdown": "Reports wildcards that become redundant when the \"\\*\\*\" wildcard is used in the same section.\n\n\nThe \"\\*\\*\" wildcard defines a broader set of files than any other wildcard.\nThat is why, any other wildcard used in the same section has no affect and can be removed." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "CythonUsageBeforeDeclaration", + "suppressToolId": "EditorConfigWildcardRedundancy", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1256,7 +1256,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1269,27 +1269,27 @@ ] }, { - "id": "PyDictCreationInspection", + "id": "EditorConfigHeaderUniqueness", "shortDescription": { - "text": "Dictionary creation can be rewritten by dictionary literal" + "text": "EditorConfig section is not unique" }, "fullDescription": { - "text": "Reports situations when you can rewrite dictionary creation by using a dictionary literal. This approach brings performance improvements. Example: 'dic = {}\ndic['var'] = 1' When the quick-fix is applied, the code changes to: 'dic = {'var': 1}'", - "markdown": "Reports situations when you can rewrite dictionary creation\nby using a dictionary literal.\n\nThis approach brings performance improvements.\n\n**Example:**\n\n\n dic = {}\n dic['var'] = 1\n\nWhen the quick-fix is applied, the code changes to:\n\n\n dic = {'var': 1}\n" + "text": "Reports sections that define the same file pattern as other sections.", + "markdown": "Reports sections that define the same file pattern as other sections." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyDictCreation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigHeaderUniqueness", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1302,19 +1302,19 @@ ] }, { - "id": "PyStringFormatInspection", + "id": "EditorConfigShadowedOption", "shortDescription": { - "text": "Errors in string formatting operations" + "text": "Overridden property" }, "fullDescription": { - "text": "Reports errors in string formatting operations. Example 1: '\"Hello {1}\".format(\"people\")' Example 2: 'def bar():\n return 1\n\n\n\"%s %s\" % bar()' As a fix, you need to rewrite string formatting fragments to adhere to the formatting syntax.", - "markdown": "Reports errors in string formatting operations.\n\n**Example 1:**\n\n\n \"Hello {1}\".format(\"people\")\n\n**Example 2:**\n\n\n def bar():\n return 1\n\n\n \"%s %s\" % bar()\n\nAs a fix, you need to rewrite string formatting fragments to\nadhere to the [formatting syntax](https://docs.python.org/3/library/string.html#format-string-syntax)." + "text": "Reports properties that are already defined in other sections. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes all '*.java' files too but it also redefines indent_size. As a result the value 2 will be used for files matching '*.java'.", + "markdown": "Reports properties that are already defined in other sections.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes all `*.java` files too but it also redefines indent_size. As a result the value 2 will be used for files matching `*.java`." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyStringFormat", + "suppressToolId": "EditorConfigShadowedOption", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1322,7 +1322,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1335,27 +1335,27 @@ ] }, { - "id": "PyExceptionInheritInspection", + "id": "EditorConfigEmptyHeader", "shortDescription": { - "text": "Exceptions do not inherit from standard 'Exception' class" + "text": "Empty header" }, "fullDescription": { - "text": "Reports cases when a custom exception class is raised but does not inherit from the builtin Exception class. Example: 'class A:\n pass\n\n\ndef me_exception():\n raise A()' The proposed quick-fix changes the code to: 'class A(Exception):\n pass\n\n\ndef me_exception():\n raise A()'", - "markdown": "Reports cases when a custom exception class is\nraised but does not inherit from the\n[builtin Exception class](https://docs.python.org/3/library/exceptions.html).\n\n**Example:**\n\n\n class A:\n pass\n\n\n def me_exception():\n raise A()\n\nThe proposed quick-fix changes the code to:\n\n\n class A(Exception):\n pass\n\n\n def me_exception():\n raise A()\n" + "text": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by 'gitignore'.", + "markdown": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by `gitignore`." }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PyExceptionInherit", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigEmptyHeader", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1368,27 +1368,27 @@ ] }, { - "id": "PyAssignmentToLoopOrWithParameterInspection", + "id": "EditorConfigValueCorrectness", "shortDescription": { - "text": "Assignments to 'for' loop or 'with' statement parameter" + "text": "Invalid property value" }, "fullDescription": { - "text": "Reports the cases when you rewrite a loop variable with an inner loop. Example: 'for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)' It also warns you if a variable declared in the 'with' statement is redeclared inside the statement body: 'with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:'", - "markdown": "Reports the cases when you rewrite a loop variable with an inner loop.\n\n**Example:**\n\n\n for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)\n \nIt also warns you if a variable declared in the `with` statement is redeclared inside the statement body:\n\n\n with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:\n \n" + "text": "Reports property values that do not meet value restrictions. For example, some properties may be only “true” or “false”, others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them.", + "markdown": "Reports property values that do not meet value restrictions. For example, some properties may be only \"true\" or \"false\", others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PyAssignmentToLoopOrWithParameter", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigValueCorrectness", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1401,28 +1401,28 @@ ] }, { - "id": "DjangoUnresolvedFilterInspection", + "id": "EditorConfigVerifyByCore", "shortDescription": { - "text": "Unresolved filter" + "text": "Invalid .editorconfig file" }, "fullDescription": { - "text": "Reports unresolved filters in Django templates. Example: '{{ my_value|cool_filter:\"arg\" }}'", - "markdown": "Reports unresolved filters in Django templates.\n\n**Example:**\n\n\n {{ my_value|cool_filter:\"arg\" }}\n" + "text": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied.", + "markdown": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "error", "parameters": { - "suppressToolId": "DjangoUnresolvedFilterInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigVerifyByCore", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1434,28 +1434,28 @@ ] }, { - "id": "AppEngineThreadsafeCGIHandlerInspection", + "id": "EditorConfigValueUniqueness", "shortDescription": { - "text": "Threadsafe cannot be enabled with the CGI handler" + "text": "Non-unique list value" }, "fullDescription": { - "text": "Reports cases when threadsafe is not enabled with the CGI handler.", - "markdown": "Reports cases when threadsafe is not enabled with the CGI handler." + "text": "Reports duplicates in lists of values.", + "markdown": "Reports duplicates in lists of values." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "error", "parameters": { - "suppressToolId": "AppEngineThreadsafeCGIHandler", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigValueUniqueness", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Google App Engine (Python)", - "index": 4, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1467,28 +1467,28 @@ ] }, { - "id": "DjangoUnresolvedTagInspection", + "id": "EditorConfigMissingRequiredDeclaration", "shortDescription": { - "text": "Unresolved tag" + "text": "Required declarations are missing" }, "fullDescription": { - "text": "Reports unresolved tags in Django templates. Example: '

{{ question.question_text }}

\n' The IDE highlights ''. You can either remove the tag or apply the quick-fix to add '' to custom HTML tags.", - "markdown": "Reports unresolved tags in Django templates.\n\n**Example:**\n\n\n

{{ question.question_text }}

\n \n\nThe IDE highlights ``. You can either remove the tag or apply the quick-fix to\nadd `` to custom HTML tags." + "text": "Reports properties that miss the required declarations. Refer to the documentation for more information.", + "markdown": "Reports properties that miss the required declarations. Refer to the documentation for more information." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "error", "parameters": { - "suppressToolId": "DjangoUnresolvedTagInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigMissingRequiredDeclaration", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1500,19 +1500,19 @@ ] }, { - "id": "PySuperArgumentsInspection", + "id": "EditorConfigCharClassLetterRedundancy", "shortDescription": { - "text": "Wrong arguments to call super" + "text": "Duplicate character class letter" }, "fullDescription": { - "text": "Reports cases when any call to 'super(A, B)' does not meet the following requirements: 'B' is an instance of 'A' 'B' a subclass of 'A' Example: 'class Figure:\n def color(self):\n pass\n\n\nclass Rectangle(Figure):\n def color(self):\n pass\n\n\nclass Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle' As a fix, you can make the 'Square' an instance of the 'Rectangle' class.", - "markdown": "Reports cases when any call to `super(A, B)` does not meet the\nfollowing requirements:\n\n* `B` is an instance of `A`\n* `B` a subclass of `A`\n\n**Example:**\n\n\n class Figure:\n def color(self):\n pass\n\n\n class Rectangle(Figure):\n def color(self):\n pass\n\n\n class Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle\n\nAs a fix, you can make the `Square` an instance of the `Rectangle` class." + "text": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example '[aa]'.", + "markdown": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example `[aa]`." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PySuperArguments", + "suppressToolId": "EditorConfigCharClassLetterRedundancy", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1520,7 +1520,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1533,28 +1533,28 @@ ] }, { - "id": "DjangoOrmInspection", + "id": "EditorConfigSpaceInHeader", "shortDescription": { - "text": "Django ORM error" + "text": "Space in file pattern" }, "fullDescription": { - "text": "Reports several methods that may not be called due to some ORM reasons. Example: 'class Choice:\n question = ForeignKey(Question, null=False)\n\n\nchoice_set = Question.objects.get(id=1).choice_set.remove()' The 'remove' function can not be called if the foreign key has 'null=False'.", - "markdown": "Reports several methods that may not be called due to some ORM reasons.\n\n**Example:**\n\n\n class Choice:\n question = ForeignKey(Question, null=False)\n\n\n choice_set = Question.objects.get(id=1).choice_set.remove()\n\nThe `remove` function can not be called if the foreign key has `null=False`." + "text": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed.", + "markdown": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "DjangoOrm", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "EditorConfigSpaceInHeader", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1566,19 +1566,19 @@ ] }, { - "id": "DjangoUnresolvedTemplateReferenceInspection", + "id": "EditorConfigOptionRedundancy", "shortDescription": { - "text": "Unresolved template reference" + "text": "Redundant property" }, "fullDescription": { - "text": "Reports unresolved file references in string literals of 'extends'> and 'include'> Django tags. Example: '{% extends \"../DjangoApp/templatetags/base.html\"%}' In this example, the 'base.html' tag is highlighted, because it is not available in the specified location.", - "markdown": "Reports unresolved file references in string literals of\n`extends`\\> and `include`\\> Django tags.\n\n**Example:**\n\n\n {% extends \"../DjangoApp/templatetags/base.html\"%}\n\nIn this example, the `base.html` tag is highlighted, because it is not available in the\nspecified location." + "text": "Reports properties that are redundant when another applicable section already contains the same property and value. For example: '[*]\nindent_size=4\n[*.java]\nindent_size=4' are both applicable to '*.java' files and define the same 'indent_size' value.", + "markdown": "Reports properties that are redundant when another applicable section already contains the same property and value.\n\n\nFor example:\n\n\n [*]\n indent_size=4\n [*.java]\n indent_size=4\n\nare both applicable to `*.java` files and define the same `indent_size` value." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "DjangoUnresolvedTemplateReferenceInspection", + "suppressToolId": "EditorConfigOptionRedundancy", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1586,8 +1586,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "EditorConfig", + "index": 0, "toolComponent": { "name": "QDPY" } @@ -1599,19 +1599,19 @@ ] }, { - "id": "PyNonAsciiCharInspection", + "id": "EditorConfigUnusedDeclaration", "shortDescription": { - "text": "File contains non-ASCII character" + "text": "Unused declaration" }, "fullDescription": { - "text": "Reports cases in Python 2 when a file contains non-ASCII characters and does not have an encoding declaration at the top. Example: 'class A(object):\n# №5\n def __init__(self):\n pass' In this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding declaration. Apply the proposed quick-fix to add a missing encoding declaration: '# coding=utf-8\nclass A(object)\n# №5\n def __init__(self):\n pass'", - "markdown": "Reports cases in Python 2 when a file contains non-ASCII characters and does not\nhave an encoding declaration at the top.\n\n**Example:**\n\n\n class A(object):\n # №5\n def __init__(self):\n pass\n\nIn this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding\ndeclaration. Apply the proposed quick-fix to add a missing encoding declaration:\n\n\n # coding=utf-8\n class A(object)\n # №5\n def __init__(self):\n pass\n" + "text": "Reports unused declarations. Such declarations can be removed.", + "markdown": "Reports unused declarations. Such declarations can be removed." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyNonAsciiChar", + "suppressToolId": "EditorConfigUnusedDeclaration", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1619,7 +1619,7 @@ "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1632,27 +1632,27 @@ ] }, { - "id": "PyAbstractClassInspection", + "id": "EditorConfigUnexpectedComma", "shortDescription": { - "text": "Class must implement all abstract methods" + "text": "Unexpected comma" }, "fullDescription": { - "text": "Reports cases when not all abstract properties or methods are defined in a subclass. Example: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_triangle(self):\n pass' When the quick-fix is applied, the IDE implements an abstract method for the 'Triangle' class: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass'", - "markdown": "Reports cases when not all abstract properties or methods are defined in\na subclass.\n\n**Example:**\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_triangle(self):\n pass\n\nWhen the quick-fix is applied, the IDE implements an abstract method for the `Triangle` class:\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass\n" + "text": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists.", + "markdown": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "error", "parameters": { - "suppressToolId": "PyAbstractClass", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "EditorConfigUnexpectedComma", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "Python", + "id": "EditorConfig", "index": 0, "toolComponent": { "name": "QDPY" @@ -1663,21 +1663,33 @@ ] } ] - }, + } + ], + "language": "en-US", + "contents": [ + "localizedData", + "nonLocalizedData" + ], + "isComprehensive": false + }, + { + "name": "Pythonid", + "version": "232.9876", + "rules": [ { - "id": "PyOldStyleClassesInspection", + "id": "PyPandasSeriesToListInspection", "shortDescription": { - "text": "Old-style class contains new-style class features" + "text": "Method Series.to_list() is recommended" }, "fullDescription": { - "text": "Reports occurrences of new-style class features in old-style classes. The inspection highlights '__slots__', '__getattribute__', and 'super()' inside old-style classes.", - "markdown": "Reports occurrences of\n[new-style class features](https://www.python.org/doc/newstyle/)\nin old-style classes. The inspection highlights\n`__slots__`, `__getattribute__`, and `super()`\ninside old-style classes." + "text": "Reports redundant 'list' in 'list(Series.values)' statement for pandas and polars libraries. Such 'Series' values extraction can be replaced with the 'to_list()' function call. Example: list(df['column'].values)\n When the quick-fix is applied, the code changes to: df['column'].to_list()", + "markdown": "Reports redundant `list` in `list(Series.values)` statement for pandas and polars libraries.\nSuch `Series` values extraction can be replaced with the `to_list()` function call.\n\n**Example:**\n\n```\nlist(df['column'].values)\n```\n\nWhen the quick-fix is applied, the code changes to:\n\n```\ndf['column'].to_list()\n```" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyOldStyleClasses", + "suppressToolId": "PyPackages", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1686,7 +1698,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1698,19 +1710,19 @@ ] }, { - "id": "DjangoIncompatibleInspection", + "id": "PySetFunctionToLiteralInspection", "shortDescription": { - "text": "Incompatible code in Django templates" + "text": "Function call can be replaced with set literal" }, "fullDescription": { - "text": "Reports features that are not available in the current Django version. Example: '{% if my_var is True %}\n{% endif %}' Available since 1.10. The IDE shows warning when discovered in the earlier versions.", - "markdown": "Reports features that are not available in the current Django version.\n\n**Example:**\n\n\n {% if my_var is True %}\n {% endif %}\n\nAvailable since 1.10. The IDE shows warning when discovered in the earlier versions." + "text": "Reports calls to the 'set' function that can be replaced with the 'set' literal. Example: 'def do_mult(a, b):\n c = a * b\n return set([c, a, b])' When the quick-fix is applied, the code changes to: 'def do_mult(a, b):\n c = a * b\n return {c, a, b}'", + "markdown": "Reports calls to the `set` function that can be replaced with\nthe `set` literal.\n\n**Example:**\n\n\n def do_mult(a, b):\n c = a * b\n return set([c, a, b])\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_mult(a, b):\n c = a * b\n return {c, a, b}\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "DjangoIncompatibleInspection", + "suppressToolId": "PySetFunctionToLiteral", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1718,8 +1730,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1731,19 +1743,19 @@ ] }, { - "id": "Query_bound_parameters", + "id": "Query_index_required", "shortDescription": { - "text": "Query does not have required bound parameters" + "text": "Query does not have the required index" }, "fullDescription": { - "text": "Reports GQL queries with bound parameters that don't have the necessary parameters passed to the query method call.", - "markdown": "Reports GQL queries with bound parameters that don't have the necessary\nparameters passed to the query method call." + "text": "Reports GQL queries for which an index is not defined in 'index.yaml'. Such queries will fail on the production server. The quick-fix allows you to add the necessary index definitions.", + "markdown": "Reports GQL queries for which an index is not defined in `index.yaml`.\nSuch queries will fail on the production server.\nThe quick-fix allows you to add the necessary index definitions." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "Query_bound_parameters", + "suppressToolId": "Query_index_required", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1764,28 +1776,28 @@ ] }, { - "id": "PyBroadExceptionInspection", + "id": "PyInitNewSignatureInspection", "shortDescription": { - "text": "Unclear exception clauses" + "text": "Incompatible signatures of __new__ and __init__" }, "fullDescription": { - "text": "Reports exception clauses that do not provide specific information about the problem. Example: Clauses that do not specify an exception class Clauses that are specified as 'Exception'", - "markdown": "Reports exception clauses that do not provide specific information\nabout the problem.\n\n**Example:**\n\n* Clauses that do not specify an exception class\n* Clauses that are specified as `Exception`" + "text": "Reports incompatible signatures of the '__new__' and '__init__' methods. Example: 'class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass' If the '__new__' and '__init__' have different arguments, then the 'MyClass' cannot be instantiated. As a fix, the IDE offers to apply the Change Signature refactoring.", + "markdown": "Reports incompatible signatures of the `__new__` and `__init__` methods.\n\n**Example:**\n\n\n class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass\n\nIf the `__new__` and `__init__` have different arguments, then the `MyClass`\ncannot be instantiated.\n\nAs a fix, the IDE offers to apply the Change Signature refactoring." }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyBroadException", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyInitNewSignature", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1797,19 +1809,19 @@ ] }, { - "id": "PyTypeCheckerInspection", + "id": "EndBlockNamesInspection", "shortDescription": { - "text": "Incorrect type" + "text": "Django endblock name doesn't match the block name" }, "fullDescription": { - "text": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases. Types of function parameters can be specified in docstrings or in Python 3 function annotations. Example: 'def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\na: str\na = foo() # Expected str, got int' With the quick-fix, you can modify the problematic types: 'def foo() -> str:\n return \"abc\"\n\n\na: str\na = foo()'", - "markdown": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases.\n\nTypes of function parameters can be specified in\ndocstrings or in Python 3 function annotations.\n\n**Example:**\n\n\n def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\n a: str\n a = foo() # Expected str, got int\n\nWith the quick-fix, you can modify the problematic types:\n\n\n def foo() -> str:\n return \"abc\"\n\n\n a: str\n a = foo()\n" + "text": "Reports incorrect names of the closing blocks. Example: '{% block my_block %}\n {% endblock not_correct %}'", + "markdown": "Reports incorrect names of the closing blocks.\n\n**Example:**\n\n\n {% block my_block %}\n {% endblock not_correct %}\n" }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyTypeChecker", + "suppressToolId": "EndBlockNamesInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1817,8 +1829,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -1830,19 +1842,19 @@ ] }, { - "id": "PyByteLiteralInspection", + "id": "PyMissingConstructorInspection", "shortDescription": { - "text": "A byte literal contains a non-ASCII character" + "text": "Missed call to '__init__' of the super class" }, "fullDescription": { - "text": "Reports characters in byte literals that are outside ASCII range. Example: 's = b'№5''", - "markdown": "Reports characters in byte literals that are outside ASCII range.\n\n**Example:**\n\n\n s = b'№5'\n" + "text": "Reports cases when a call to the 'super' constructor in a class is missed. Example: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n pass' The 'Pear' class should have a 'super' call in the '__init__' method. When the quick-fix is applied, the code changes to: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n super().__init__()'", + "markdown": "Reports cases when a call to the `super` constructor in a class is missed.\n\n**Example:**\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n pass\n\nThe `Pear` class should have a `super` call in the `__init__`\nmethod.\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n super().__init__()\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyByteLiteral", + "suppressToolId": "PyMissingConstructor", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1851,7 +1863,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1863,19 +1875,19 @@ ] }, { - "id": "PyAugmentAssignmentInspection", + "id": "PySimplifyBooleanCheckInspection", "shortDescription": { - "text": "Assignment can be replaced with augmented assignment" + "text": "Redundant boolean variable check" }, "fullDescription": { - "text": "Reports assignments that can be replaced with augmented assignments. Example: 'a = 23\nb = 3\na = a + b' After the quick-fix is applied, the code changes to: 'a = 23\nb = 3\na += b'", - "markdown": "Reports assignments that can be replaced with augmented assignments.\n\n**Example:**\n\n\n a = 23\n b = 3\n a = a + b\n\nAfter the quick-fix is applied, the code changes to:\n\n\n a = 23\n b = 3\n a += b\n" + "text": "Reports equality comparison with a boolean literal. Example: 'def func(s):\n if s.isdigit() == True:\n return int(s)' With the quick-fix applied, the code fragment will be simplified to: 'def func(s):\n if s.isdigit():\n return int(s)'", + "markdown": "Reports equality comparison with a boolean literal.\n\n**Example:**\n\n\n def func(s):\n if s.isdigit() == True:\n return int(s)\n\nWith the quick-fix applied, the code fragment will be simplified to:\n\n\n def func(s):\n if s.isdigit():\n return int(s)\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyAugmentAssignment", + "suppressToolId": "PySimplifyBooleanCheck", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -1884,7 +1896,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1896,19 +1908,19 @@ ] }, { - "id": "PyDeprecationInspection", + "id": "PyCallingNonCallableInspection", "shortDescription": { - "text": "Deprecated function, class, or module" + "text": "Attempt to call a non-callable object" }, "fullDescription": { - "text": "Reports usages of Python functions, or methods that are marked as deprecated and raise the 'DeprecationWarning' or 'PendingDeprecationWarning' warning. Also, this inspection highlights usages of 'abc.abstractstaticmethod', 'abc.abstractproperty', and 'abc.abstractclassmethod' decorators. Example: 'class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\nfoo = Foo()\nprint(foo.bar)'", - "markdown": "Reports usages of Python functions, or methods that are marked as\ndeprecated and raise the `DeprecationWarning` or `PendingDeprecationWarning` warning.\n\nAlso, this inspection highlights usages of `abc.abstractstaticmethod`, `abc.abstractproperty`, and `abc.abstractclassmethod`\ndecorators.\n\n**Example:**\n\n\n class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\n foo = Foo()\n print(foo.bar)\n" + "text": "Reports a problem when you are trying to call objects that are not callable, like, for example, properties: Example: 'class Record:\n @property\n def as_json(self):\n\njson = Record().as_json()'", + "markdown": "Reports a problem when you are trying\nto call objects that are not callable, like, for example, properties:\n\n**Example:**\n\n\n class Record:\n @property\n def as_json(self):\n\n json = Record().as_json()\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyDeprecation", + "suppressToolId": "PyCallingNonCallable", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1917,7 +1929,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1929,19 +1941,19 @@ ] }, { - "id": "PyUnnecessaryBackslashInspection", + "id": "PyUnreachableCodeInspection", "shortDescription": { - "text": "Unnecessary backslash" + "text": "Unreachable code" }, "fullDescription": { - "text": "Reports backslashes in places where line continuation is implicit inside '()', '[]', and '{}'. Example: 'a = ('first', \\\n 'second', 'third')' When the quick-fix is applied, the redundant backslash is deleted.", - "markdown": "Reports backslashes in places where line continuation is implicit inside `()`,\n`[]`, and `{}`.\n\n**Example:**\n\n\n a = ('first', \\\n 'second', 'third')\n\nWhen the quick-fix is applied, the redundant backslash is deleted." + "text": "Reports code fragments that cannot be normally reached. Example: 'if True:\n print('Yes')\nelse:\n print('No')' As a fix, you might want to check and modify the algorithm to ensure it implements the expected logic.", + "markdown": "Reports code fragments that cannot be normally reached.\n\n**Example:**\n\n\n if True:\n print('Yes')\n else:\n print('No')\n\nAs a fix, you might want to check and modify the algorithm to ensure it implements\nthe expected logic." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyUnnecessaryBackslash", + "suppressToolId": "PyUnreachableCode", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -1950,7 +1962,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1962,19 +1974,19 @@ ] }, { - "id": "PyShadowingNamesInspection", + "id": "PyChainedComparisonsInspection", "shortDescription": { - "text": "Shadowing names from outer scopes" + "text": "Too complex chained comparisons" }, "fullDescription": { - "text": "Reports shadowing names defined in outer scopes. Example: 'def outer(p):\n def inner(p):\n pass' As a quick-fix, the IDE offers to remove a parameter or rename it.", - "markdown": "Reports shadowing names defined in outer scopes.\n\n**Example:**\n\n\n def outer(p):\n def inner(p):\n pass\n\nAs a quick-fix, the IDE offers to remove a parameter or rename it." + "text": "Reports chained comparisons that can be simplified. Example: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass' The IDE offers to simplify 'if x >= xmin and x <= xmax'. When the quick-fix is applied, the code changes to: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass'", + "markdown": "Reports chained comparisons that can be simplified.\n\n**Example:**\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass\n\nThe IDE offers to simplify `if x >= xmin and x <= xmax`.\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass\n" }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyShadowingNames", + "suppressToolId": "PyChainedComparisons", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -1983,7 +1995,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -1995,19 +2007,19 @@ ] }, { - "id": "PyFinalInspection", + "id": "DjangoBrokenLineCommentInspection", "shortDescription": { - "text": "Invalid usages of final classes, methods, and variables" + "text": "Broken line comment" }, "fullDescription": { - "text": "Reports invalid usages of final classes, methods and variables. Example: 'from typing import final\n\n\n@final\nclass A:\n def a_method(self):\n pass\n\n\nclass B(A):\n def a_method(self):\n pass'", - "markdown": "Reports invalid usages of final classes,\nmethods and variables.\n\n**Example:**\n\n\n from typing import final\n\n\n @final\n class A:\n def a_method(self):\n pass\n\n\n class B(A):\n def a_method(self):\n pass\n" + "text": "Reports '#}' line comment ends in Django templates that do not have a matching line comment start. Example: 'comment #}' The IDE highlights '#}' as it requires the corresponding '{#' token.", + "markdown": "Reports `#}` line comment ends in Django templates that do not have a\nmatching line comment start.\n\n**Example:**\n\n\n comment #}\n\nThe IDE highlights `#}` as it requires the corresponding `{#` token." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyFinal", + "suppressToolId": "DjangoBrokenLineCommentInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2015,8 +2027,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -2028,19 +2040,19 @@ ] }, { - "id": "DjangoCloseTagInspection", + "id": "PyCompatibilityInspection", "shortDescription": { - "text": "Mismatched opening and closing tags" + "text": "Code is incompatible with specific Python versions" }, "fullDescription": { - "text": "Reports cases when opening tags in Django templates are not correctly matched by closing tags. Example: '{% if error_message %}

{{ error_message }}

{% endif %}' The IDE reports an error on the 'strong' tag not being closed.", - "markdown": "Reports cases when opening tags in Django templates are not correctly matched by closing tags.\n\n**Example:**\n\n\n {% if error_message %}

{{ error_message }}

{% endif %}\n\nThe IDE reports an error on the `strong` tag not being closed." + "text": "Reports incompatibility with the specified versions of Python. Enable this inspection if you need your code to be compatible with a range of Python versions, for example, if you are building a library. To define the range of the inspected Python versions, select the corresponding checkboxes in the Options section. For more information about the Python versions supported by the IDE, see the web help.", + "markdown": "Reports incompatibility with the specified versions of Python.\nEnable this inspection if you need your code to be compatible with a range of Python versions, for example,\nif you are building a library.\n\nTo define the range of the inspected Python versions, select the corresponding checkboxes in the **Options**\nsection.\n\nFor more information about the Python versions supported by the IDE, see the\n[web help](https://www.jetbrains.com/help/pycharm/python.html#support)." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "DjangoCloseTagInspection", + "suppressToolId": "PyCompatibility", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2048,8 +2060,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2061,19 +2073,19 @@ ] }, { - "id": "PySingleQuotedDocstringInspection", + "id": "PyGlobalUndefinedInspection", "shortDescription": { - "text": "Single quoted docstring" + "text": "Global variable is not defined at the module level" }, "fullDescription": { - "text": "Reports docstrings that do not adhere to the triple double-quoted string format. Example: 'def calc(self, balance=0):\n 'param: balance'\n self.balance = balance' When the quick-fix is applied, the code changes to: 'def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance'", - "markdown": "Reports docstrings that do not adhere to the triple double-quoted string format.\n\n**Example:**\n\n\n def calc(self, balance=0):\n 'param: balance'\n self.balance = balance\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance\n" + "text": "Reports problems when a variable defined through the 'global' statement is not defined in the module scope. Example: 'def foo():\n global bar\n print(bar)\n\nfoo()' As a fix, you can move the global variable declaration: 'global bar\n\n\ndef foo():\n print(bar)'", + "markdown": "Reports problems when a variable defined through the `global`\nstatement is not defined in the module scope.\n\n**Example:**\n\n\n def foo():\n global bar\n print(bar)\n\n foo()\n\nAs a fix, you can move the global variable declaration:\n\n\n global bar\n\n\n def foo():\n print(bar)\n" }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PySingleQuotedDocstring", + "suppressToolId": "PyGlobalUndefined", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -2082,7 +2094,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2094,28 +2106,28 @@ ] }, { - "id": "PyUnusedLocalInspection", + "id": "PyProtocolInspection", "shortDescription": { - "text": "Unused local symbols" + "text": "Invalid protocol definitions and usages" }, "fullDescription": { - "text": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function.", - "markdown": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function." + "text": "Reports invalid definitions and usages of protocols introduced in PEP-544. Example: 'from typing import Protocol\n\n\nclass MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\nclass MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\nclass MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass'", + "markdown": "Reports invalid definitions and usages of protocols introduced in\n[PEP-544](https://www.python.org/dev/peps/pep-0544/).\n\n**Example:**\n\n\n from typing import Protocol\n\n\n class MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\n class MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\n class MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass\n\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyUnusedLocal", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyProtocol", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2127,19 +2139,19 @@ ] }, { - "id": "PyReturnFromInitInspection", + "id": "PyTypeHintsInspection", "shortDescription": { - "text": "__init__ method that returns a value" + "text": "Invalid type hints definitions and usages" }, "fullDescription": { - "text": "Reports occurrences of 'return' statements with a return value inside '__init__' methods of classes. Example: 'class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum' A constructor should not return any value. The '__init__' method should only initialize the values of instance members for news objects. As a quick-fix, the IDE offers to remove the 'return' statement.", - "markdown": "Reports occurrences of `return` statements with a return value inside\n`__init__` methods of classes.\n\n**Example:**\n\n\n class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum\n\nA constructor should not return any value. The `__init__` method should\nonly initialize the values of instance members for news objects.\n\nAs a quick-fix, the IDE offers to remove the `return` statement." + "text": "Reports invalid usages of type hints. Example: 'from typing import TypeVar\n\nT0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\ndef b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\ndef c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass' Available quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown.", + "markdown": "Reports invalid usages of type hints.\n\n**Example:**\n\n\n from typing import TypeVar\n\n T0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\n def b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\n def c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass\n\nAvailable quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyReturnFromInit", + "suppressToolId": "PyTypeHints", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2148,7 +2160,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2160,28 +2172,28 @@ ] }, { - "id": "Query_restricted", + "id": "PyMethodMayBeStaticInspection", "shortDescription": { - "text": "Query does not comply with the query restrictions" + "text": "Method is not declared static" }, "fullDescription": { - "text": "Reports GQL queries that do not comply with the restrictions for queries allowed on the Google App Engine server. See the App Engine documentation for more information.", - "markdown": "Reports GQL queries that do not comply with the restrictions for queries allowed\non the Google App Engine server.\nSee the [App Engine documentation](http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Restrictions_on_Queries) for more information." + "text": "Reports any methods that do not require a class instance creation and can be made static. Example: 'class MyClass(object):\n def my_method(self, x):\n print(x)' If a Make function from method quick-fix is applied, the code changes to: 'def my_method(x):\n print(x)\n\n\nclass MyClass(object):\n pass' If you select the Make method static quick-fix, the '@staticmethod' decorator is added: 'class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)'", + "markdown": "Reports any methods that do not require a class instance creation and can be\nmade static.\n\n**Example:**\n\n\n class MyClass(object):\n def my_method(self, x):\n print(x)\n\nIf a **Make function from method** quick-fix is applied, the code changes to:\n\n\n def my_method(x):\n print(x)\n\n\n class MyClass(object):\n pass\n\nIf you select the **Make method static** quick-fix, the `@staticmethod` decorator is added:\n\n\n class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)\n" }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "Query_restricted", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyMethodMayBeStatic", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Google App Engine (Python)", - "index": 4, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2193,28 +2205,28 @@ ] }, { - "id": "PyMissingOrEmptyDocstringInspection", + "id": "CythonUsageBeforeDeclarationInspection", "shortDescription": { - "text": "Missing or empty docstring" + "text": "Cython variable is used before its declaration" }, "fullDescription": { - "text": "Reports missing and empty docstrings. Example of a missing docstring 'def demo(a):\n c = a ** 2' Example of an empty docstring 'def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2' When the quick-fix is applied, the code fragments change to: 'def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2' You need to provide some details about the parameter in the generated template.", - "markdown": "Reports missing and empty docstrings.\n\n**Example of a missing docstring**\n\n\n def demo(a):\n c = a ** 2\n\n**Example of an empty docstring**\n\n\n def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2\n\nWhen the quick-fix is applied, the code fragments change to:\n\n\n def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2\n\nYou need to provide some details about the parameter in the generated template." + "text": "Reports Cython variables being referenced before declaration. Example: 'cdef int c_x\n\nprint(c_x, c_y) # Variable 'c_y' is used before its declaration\n\ncdef int c_y = 0'", + "markdown": "Reports Cython variables being referenced before declaration.\n\n**Example:**\n\n\n cdef int c_x\n\n print(c_x, c_y) # Variable 'c_y' is used before its declaration\n\n cdef int c_y = 0\n" }, "defaultConfiguration": { - "enabled": false, - "level": "note", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "PyMissingOrEmptyDocstring", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "CythonUsageBeforeDeclaration", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2226,19 +2238,19 @@ ] }, { - "id": "PyPep8NamingInspection", + "id": "PyDictCreationInspection", "shortDescription": { - "text": "PEP 8 naming convention violation" + "text": "Dictionary creation can be rewritten by dictionary literal" }, "fullDescription": { - "text": "Reports violations of the PEP8 naming conventions. Example: 'class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")' In this code fragment, IDE offers to rename 'mammalia' to 'Mammalia'. When the quick-fix is applied, the code change to: 'class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")'", - "markdown": "Reports violations of the\n[PEP8](https://www.python.org/dev/peps/pep-0008/) naming conventions.\n\n**Example:**\n\n\n class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n\nIn this code fragment, IDE offers to rename `mammalia` to `Mammalia`.\nWhen the quick-fix is applied, the code change to:\n\n\n class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n" + "text": "Reports situations when you can rewrite dictionary creation by using a dictionary literal. This approach brings performance improvements. Example: 'dic = {}\ndic['var'] = 1' When the quick-fix is applied, the code changes to: 'dic = {'var': 1}'", + "markdown": "Reports situations when you can rewrite dictionary creation\nby using a dictionary literal.\n\nThis approach brings performance improvements.\n\n**Example:**\n\n\n dic = {}\n dic['var'] = 1\n\nWhen the quick-fix is applied, the code changes to:\n\n\n dic = {'var': 1}\n" }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyPep8Naming", + "suppressToolId": "PyDictCreation", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -2247,7 +2259,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2259,19 +2271,19 @@ ] }, { - "id": "DjangoUnresolvedLoadInspection", + "id": "PyStringFormatInspection", "shortDescription": { - "text": "Unresolved library inspection" + "text": "Errors in string formatting operations" }, "fullDescription": { - "text": "Reports unresolved references in Django load tags. Example: '{% load something_nonexistent %}'", - "markdown": "Reports unresolved references in Django load tags.\n\n**Example:**\n\n\n {% load something_nonexistent %}\n" + "text": "Reports errors in string formatting operations. Example 1: '\"Hello {1}\".format(\"people\")' Example 2: 'def bar():\n return 1\n\n\n\"%s %s\" % bar()' As a fix, you need to rewrite string formatting fragments to adhere to the formatting syntax.", + "markdown": "Reports errors in string formatting operations.\n\n**Example 1:**\n\n\n \"Hello {1}\".format(\"people\")\n\n**Example 2:**\n\n\n def bar():\n return 1\n\n\n \"%s %s\" % bar()\n\nAs a fix, you need to rewrite string formatting fragments to\nadhere to the [formatting syntax](https://docs.python.org/3/library/string.html#format-string-syntax)." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "DjangoUnresolvedLoadInspection", + "suppressToolId": "PyStringFormat", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2279,8 +2291,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2292,19 +2304,19 @@ ] }, { - "id": "PyDictDuplicateKeysInspection", + "id": "PyExceptionInheritInspection", "shortDescription": { - "text": "Dictionary contains duplicate keys" + "text": "Exceptions do not inherit from standard 'Exception' class" }, "fullDescription": { - "text": "Reports using the same value as the dictionary key twice. Example: 'dic = {\"a\": [1, 2], \"a\": [3, 4]}'", - "markdown": "Reports using the same value as the dictionary key twice.\n\n**Example:**\n\n\n dic = {\"a\": [1, 2], \"a\": [3, 4]}\n" + "text": "Reports cases when a custom exception class is raised but does not inherit from the builtin Exception class. Example: 'class A:\n pass\n\n\ndef me_exception():\n raise A()' The proposed quick-fix changes the code to: 'class A(Exception):\n pass\n\n\ndef me_exception():\n raise A()'", + "markdown": "Reports cases when a custom exception class is\nraised but does not inherit from the\n[builtin Exception class](https://docs.python.org/3/library/exceptions.html).\n\n**Example:**\n\n\n class A:\n pass\n\n\n def me_exception():\n raise A()\n\nThe proposed quick-fix changes the code to:\n\n\n class A(Exception):\n pass\n\n\n def me_exception():\n raise A()\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyDictDuplicateKeys", + "suppressToolId": "PyExceptionInherit", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2313,7 +2325,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2325,19 +2337,19 @@ ] }, { - "id": "PyNoneFunctionAssignmentInspection", + "id": "PyAssignmentToLoopOrWithParameterInspection", "shortDescription": { - "text": "Assigning function calls that don't return anything" + "text": "Assignments to 'for' loop or 'with' statement parameter" }, "fullDescription": { - "text": "Reports cases when an assignment is done on a function that does not return anything. This inspection is similar to pylint inspection E1111. Example: 'def just_print():\n print(\"Hello!\")\n\n\naction = just_print()' As a quick-fix, the IDE offers to remove the assignment.", - "markdown": "Reports cases when an assignment is done on a function that does not return anything.\nThis inspection is similar to [pylint inspection E1111](https://docs.pylint.org/en/1.6.0/features.html#id6).\n\n**Example:**\n\n\n def just_print():\n print(\"Hello!\")\n\n\n action = just_print()\n\nAs a quick-fix, the IDE offers to remove the assignment." + "text": "Reports the cases when you rewrite a loop variable with an inner loop. Example: 'for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)' It also warns you if a variable declared in the 'with' statement is redeclared inside the statement body: 'with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:'", + "markdown": "Reports the cases when you rewrite a loop variable with an inner loop.\n\n**Example:**\n\n\n for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)\n \nIt also warns you if a variable declared in the `with` statement is redeclared inside the statement body:\n\n\n with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:\n \n" }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyNoneFunctionAssignment", + "suppressToolId": "PyAssignmentToLoopOrWithParameter", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -2346,7 +2358,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2358,19 +2370,19 @@ ] }, { - "id": "JupyterPackageInspection", + "id": "DjangoUnresolvedFilterInspection", "shortDescription": { - "text": "The 'jupyter' package is not installed" + "text": "Unresolved filter" }, "fullDescription": { - "text": "Reports cases when the 'jupyter' package is not installed for the selected Python interpreter. Without a properly installed 'jupyter' package, you cannot execute Jupyter notebooks. Click the corresponding link on the warning banner to install the missing package. You can also install the package in the Project Settings/Preferences or in the Python Packages tool window. See Installing Python package for more details.", - "markdown": "Reports cases when the `jupyter` package is not installed for the selected\nPython interpreter. Without a properly installed `jupyter` package, you cannot\nexecute Jupyter notebooks.\n\nClick the corresponding link on the warning banner to install the missing\npackage. You can also install the package in the Project **Settings/Preferences** or in the\n**Python Packages** tool window.\n\nSee [Installing Python package](https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-upgrading-packages.html) for more details." + "text": "Reports unresolved filters in Django templates. Example: '{{ my_value|cool_filter:\"arg\" }}'", + "markdown": "Reports unresolved filters in Django templates.\n\n**Example:**\n\n\n {{ my_value|cool_filter:\"arg\" }}\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "JupyterPackage", + "suppressToolId": "DjangoUnresolvedFilterInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2378,8 +2390,8 @@ "relationships": [ { "target": { - "id": "Jupyter", - "index": 57, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -2391,19 +2403,19 @@ ] }, { - "id": "PyStatementEffectInspection", + "id": "AppEngineThreadsafeCGIHandlerInspection", "shortDescription": { - "text": "Statement has no effect" + "text": "Threadsafe cannot be enabled with the CGI handler" }, "fullDescription": { - "text": "Reports statements that have no effect. Example: 'class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n2 + 3 # has no effect' In this example, you can either add a field 'time' to the 'Car' class or introduce variables for the problematic statements.", - "markdown": "Reports statements that have no effect.\n\n**Example:**\n\n\n class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n 2 + 3 # has no effect\n\nIn this example, you can either add a field `time` to the `Car` class or\nintroduce variables for the problematic statements." + "text": "Reports cases when threadsafe is not enabled with the CGI handler.", + "markdown": "Reports cases when threadsafe is not enabled with the CGI handler." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyStatementEffect", + "suppressToolId": "AppEngineThreadsafeCGIHandler", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2411,8 +2423,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Google App Engine (Python)", + "index": 4, "toolComponent": { "name": "QDPY" } @@ -2424,19 +2436,19 @@ ] }, { - "id": "PyMandatoryEncodingInspection", + "id": "DjangoUnresolvedTagInspection", "shortDescription": { - "text": "No encoding specified for file" + "text": "Unresolved tag" }, "fullDescription": { - "text": "Reports a missing encoding comment in Python 2. Example: 'class Book(object):\n def __init__(self):\n pass' When the quick-fix is applied, the missing comment is added: '# coding=utf-8\nclass Book(object):\n def __init__(self):\n pass'", - "markdown": "Reports a missing encoding comment in Python 2.\n\n**Example:**\n\n\n class Book(object):\n def __init__(self):\n pass\n\nWhen the quick-fix is applied, the missing comment is added:\n\n\n # coding=utf-8\n class Book(object):\n def __init__(self):\n pass\n" + "text": "Reports unresolved tags in Django templates. Example: '

{{ question.question_text }}

\n' The IDE highlights ''. You can either remove the tag or apply the quick-fix to add '' to custom HTML tags.", + "markdown": "Reports unresolved tags in Django templates.\n\n**Example:**\n\n\n

{{ question.question_text }}

\n \n\nThe IDE highlights ``. You can either remove the tag or apply the quick-fix to\nadd `` to custom HTML tags." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyMandatoryEncoding", + "suppressToolId": "DjangoUnresolvedTagInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2444,8 +2456,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -2457,19 +2469,19 @@ ] }, { - "id": "PyInconsistentIndentationInspection", + "id": "PySuperArgumentsInspection", "shortDescription": { - "text": "Inconsistent indentation" + "text": "Wrong arguments to call super" }, "fullDescription": { - "text": "Reports inconsistent indentation in Python source files when, for example, you use a mixture of tabs and spaces in your code.", - "markdown": "Reports inconsistent indentation in Python source files when, for example,\nyou use a mixture of tabs and spaces in your code." + "text": "Reports cases when any call to 'super(A, B)' does not meet the following requirements: 'B' is an instance of 'A' 'B' a subclass of 'A' Example: 'class Figure:\n def color(self):\n pass\n\n\nclass Rectangle(Figure):\n def color(self):\n pass\n\n\nclass Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle' As a fix, you can make the 'Square' an instance of the 'Rectangle' class.", + "markdown": "Reports cases when any call to `super(A, B)` does not meet the\nfollowing requirements:\n\n* `B` is an instance of `A`\n* `B` a subclass of `A`\n\n**Example:**\n\n\n class Figure:\n def color(self):\n pass\n\n\n class Rectangle(Figure):\n def color(self):\n pass\n\n\n class Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle\n\nAs a fix, you can make the `Square` an instance of the `Rectangle` class." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyInconsistentIndentation", + "suppressToolId": "PySuperArguments", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2478,7 +2490,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2490,28 +2502,28 @@ ] }, { - "id": "PyAttributeOutsideInitInspection", + "id": "DjangoOrmInspection", "shortDescription": { - "text": "An instance attribute is defined outside `__init__`" + "text": "Django ORM error" }, "fullDescription": { - "text": "Reports a problem when instance attribute definition is outside '__init__' method. Example: 'class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'' When the quick-fix is applied, the code sample changes to: 'class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass'", - "markdown": "Reports a problem when instance attribute definition is outside `__init__` method.\n\n**Example:**\n\n\n class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'\n\n\nWhen the quick-fix is applied, the code sample changes to:\n\n\n class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass\n" + "text": "Reports several methods that may not be called due to some ORM reasons. Example: 'class Choice:\n question = ForeignKey(Question, null=False)\n\n\nchoice_set = Question.objects.get(id=1).choice_set.remove()' The 'remove' function can not be called if the foreign key has 'null=False'.", + "markdown": "Reports several methods that may not be called due to some ORM reasons.\n\n**Example:**\n\n\n class Choice:\n question = ForeignKey(Question, null=False)\n\n\n choice_set = Question.objects.get(id=1).choice_set.remove()\n\nThe `remove` function can not be called if the foreign key has `null=False`." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyAttributeOutsideInit", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "DjangoOrm", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -2523,19 +2535,19 @@ ] }, { - "id": "PyTypedDictInspection", + "id": "DjangoUnresolvedTemplateReferenceInspection", "shortDescription": { - "text": "Invalid TypedDict definition and usages" + "text": "Unresolved template reference" }, "fullDescription": { - "text": "Reports invalid definition and usage of TypedDict. Example: 'from typing import TypedDict\n\n\nclass Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\nm = Movie(name=\"name\", year=1000, rate=9)\nprint(m[\"director\"]) # There is no the 'director' key in 'Movie'\ndel m[\"name\"] # The 'name' key cannot be deleted\nm[\"year\"] = \"1001\" # Expected 'int', got 'str''", - "markdown": "Reports invalid definition and usage of\n[TypedDict](https://www.python.org/dev/peps/pep-0589/).\n\n**Example:**\n\n\n from typing import TypedDict\n\n\n class Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\n m = Movie(name=\"name\", year=1000, rate=9)\n print(m[\"director\"]) # There is no the 'director' key in 'Movie'\n del m[\"name\"] # The 'name' key cannot be deleted\n m[\"year\"] = \"1001\" # Expected 'int', got 'str'\n" + "text": "Reports unresolved file references in string literals of 'extends'> and 'include'> Django tags. Example: '{% extends \"../DjangoApp/templatetags/base.html\"%}' In this example, the 'base.html' tag is highlighted, because it is not available in the specified location.", + "markdown": "Reports unresolved file references in string literals of\n`extends`\\> and `include`\\> Django tags.\n\n**Example:**\n\n\n {% extends \"../DjangoApp/templatetags/base.html\"%}\n\nIn this example, the `base.html` tag is highlighted, because it is not available in the\nspecified location." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyTypedDict", + "suppressToolId": "DjangoUnresolvedTemplateReferenceInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2543,8 +2555,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -2556,28 +2568,28 @@ ] }, { - "id": "PyPep8Inspection", + "id": "PyNonAsciiCharInspection", "shortDescription": { - "text": "PEP 8 coding style violation" + "text": "File contains non-ASCII character" }, "fullDescription": { - "text": "Reports violations of the PEP 8 coding style guide by running the bundled pycodestyle.py tool.", - "markdown": "Reports violations of the [PEP 8 coding style guide](https://www.python.org/dev/peps/pep-0008/) by running the bundled [pycodestyle.py](https://github.com/PyCQA/pycodestyle) tool." + "text": "Reports cases in Python 2 when a file contains non-ASCII characters and does not have an encoding declaration at the top. Example: 'class A(object):\n# №5\n def __init__(self):\n pass' In this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding declaration. Apply the proposed quick-fix to add a missing encoding declaration: '# coding=utf-8\nclass A(object)\n# №5\n def __init__(self):\n pass'", + "markdown": "Reports cases in Python 2 when a file contains non-ASCII characters and does not\nhave an encoding declaration at the top.\n\n**Example:**\n\n\n class A(object):\n # №5\n def __init__(self):\n pass\n\nIn this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding\ndeclaration. Apply the proposed quick-fix to add a missing encoding declaration:\n\n\n # coding=utf-8\n class A(object)\n # №5\n def __init__(self):\n pass\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyPep8", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyNonAsciiChar", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2589,28 +2601,28 @@ ] }, { - "id": "PyMissingTypeHintsInspection", + "id": "PyOldStyleClassesInspection", "shortDescription": { - "text": "Missing type hinting for function definition" + "text": "Old-style class contains new-style class features" }, "fullDescription": { - "text": "Reports missing type hints for function declaration in one of the two formats: parameter annotations or a type comment. Select the Only when types are known checkbox if you want the inspection check the types collected from runtime or inferred.", - "markdown": "Reports missing type hints for function declaration in\none of the two formats: parameter annotations or a type comment.\n\nSelect the **Only when types are known** checkbox if you want the inspection check\nthe types collected from runtime or inferred." + "text": "Reports occurrences of new-style class features in old-style classes. The inspection highlights '__slots__', '__getattribute__', and 'super()' inside old-style classes.", + "markdown": "Reports occurrences of\n[new-style class features](https://www.python.org/doc/newstyle/)\nin old-style classes. The inspection highlights\n`__slots__`, `__getattribute__`, and `super()`\ninside old-style classes." }, "defaultConfiguration": { - "enabled": false, - "level": "note", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "PyMissingTypeHints", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyOldStyleClasses", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2622,28 +2634,28 @@ ] }, { - "id": "PyTupleItemAssignmentInspection", + "id": "PyAbstractClassInspection", "shortDescription": { - "text": "Tuple item assignment is prohibited" + "text": "Class must implement all abstract methods" }, "fullDescription": { - "text": "Reports assignments to a tuple item. Example: 't = ('red', 'blue', 'green', 'white')\nt[3] = 'black'' A quick-fix offers to replace the tuple with a list.", - "markdown": "Reports assignments to a tuple item.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n t[3] = 'black'\n\nA quick-fix offers to replace the tuple with a list." + "text": "Reports cases when not all abstract properties or methods are defined in a subclass. Example: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_triangle(self):\n pass' When the quick-fix is applied, the IDE implements an abstract method for the 'Triangle' class: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass'", + "markdown": "Reports cases when not all abstract properties or methods are defined in\na subclass.\n\n**Example:**\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_triangle(self):\n pass\n\nWhen the quick-fix is applied, the IDE implements an abstract method for the `Triangle` class:\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass\n" }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyTupleItemAssignment", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyAbstractClass", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2655,21 +2667,21 @@ ] }, { - "id": "DjangoUnresolvedUrlInspection", + "id": "DjangoIncompatibleInspection", "shortDescription": { - "text": "Django {% url %} tag arguments are unresolved" + "text": "Incompatible code in Django templates" }, "fullDescription": { - "text": "Reports a missing url in the 'url' tag. Example: '{% url 'url_name' %}' The IDE shows a warning if 'url_name' is not defined in the 'urls' file.", - "markdown": "Reports a missing url in the `url` tag.\n\n**Example:**\n\n\n {% url 'url_name' %}\n\nThe IDE shows a warning if `url_name` is not defined in the `urls` file." + "text": "Reports features that are not available in the current Django version. Example: '{% if my_var is True %}\n{% endif %}' Available since 1.10. The IDE shows warning when discovered in the earlier versions.", + "markdown": "Reports features that are not available in the current Django version.\n\n**Example:**\n\n\n {% if my_var is True %}\n {% endif %}\n\nAvailable since 1.10. The IDE shows warning when discovered in the earlier versions." }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "DjangoUnresolvedUrlInspection", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "DjangoIncompatibleInspection", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ @@ -2688,19 +2700,19 @@ ] }, { - "id": "DjangoUnresolvedStaticReferenceInspection", + "id": "Query_bound_parameters", "shortDescription": { - "text": "Unresolved static reference" + "text": "Query does not have required bound parameters" }, "fullDescription": { - "text": "Reports unresolved references to static resources. Example: '{% load staticfiles %}\n' In this example, 'style.css' is highlighted if there is no such a file in the 'static/poll' directory.", - "markdown": "Reports unresolved references to static resources.\n\n**Example:**\n\n\n {% load staticfiles %}\n \n\nIn this example, `style.css` is highlighted if there is no such a file in the `static/poll`\ndirectory." + "text": "Reports GQL queries with bound parameters that don't have the necessary parameters passed to the query method call.", + "markdown": "Reports GQL queries with bound parameters that don't have the necessary\nparameters passed to the query method call." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "DjangoUnresolvedStaticReferenceInspection", + "suppressToolId": "Query_bound_parameters", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2708,8 +2720,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Google App Engine (Python)", + "index": 4, "toolComponent": { "name": "QDPY" } @@ -2721,28 +2733,28 @@ ] }, { - "id": "PyDunderSlotsInspection", + "id": "PyBroadExceptionInspection", "shortDescription": { - "text": "Invalid usages of classes with '__slots__' definitions" + "text": "Unclear exception clauses" }, "fullDescription": { - "text": "Reports invalid usages of a class with '__slots__' definitions. Example: 'class Foo:\n __slots__ = ['foo', 'bar']\n\n\nfoo = Foo()\nfoo.baz = 'spam''", - "markdown": "Reports invalid usages of a class with `__slots__` definitions.\n\n**Example:**\n\n\n class Foo:\n __slots__ = ['foo', 'bar']\n\n\n foo = Foo()\n foo.baz = 'spam'\n" + "text": "Reports exception clauses that do not provide specific information about the problem. Example: Clauses that do not specify an exception class Clauses that are specified as 'Exception'", + "markdown": "Reports exception clauses that do not provide specific information\nabout the problem.\n\n**Example:**\n\n* Clauses that do not specify an exception class\n* Clauses that are specified as `Exception`" }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyDunderSlots", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyBroadException", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2754,19 +2766,19 @@ ] }, { - "id": "PyDefaultArgumentInspection", + "id": "PyTypeCheckerInspection", "shortDescription": { - "text": "The default argument is mutable" + "text": "Incorrect type" }, "fullDescription": { - "text": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for an argument. Default argument values are evaluated only once at function definition time, which means that modifying the default value of the argument will affect all subsequent calls of that function. Example: 'def func(s, cache={}):\n cache[s] = None' When the quick-fix is applied, the code changes to: 'def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None'", - "markdown": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for\nan argument. \n\nDefault argument values are evaluated only once at function definition time,\nwhich means that modifying the\ndefault value of the argument will affect all subsequent calls of that function.\n\n**Example:**\n\n\n def func(s, cache={}):\n cache[s] = None\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None\n" + "text": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases. Types of function parameters can be specified in docstrings or in Python 3 function annotations. Example: 'def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\na: str\na = foo() # Expected str, got int' With the quick-fix, you can modify the problematic types: 'def foo() -> str:\n return \"abc\"\n\n\na: str\na = foo()'", + "markdown": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases.\n\nTypes of function parameters can be specified in\ndocstrings or in Python 3 function annotations.\n\n**Example:**\n\n\n def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\n a: str\n a = foo() # Expected str, got int\n\nWith the quick-fix, you can modify the problematic types:\n\n\n def foo() -> str:\n return \"abc\"\n\n\n a: str\n a = foo()\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyDefaultArgument", + "suppressToolId": "PyTypeChecker", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2775,7 +2787,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2787,28 +2799,28 @@ ] }, { - "id": "PyShadowingBuiltinsInspection", + "id": "PyByteLiteralInspection", "shortDescription": { - "text": "Shadowing built-in names" + "text": "A byte literal contains a non-ASCII character" }, "fullDescription": { - "text": "Reports shadowing built-in names, such as 'len' or 'list'. Example: 'def len(a, b, c):\n d = a + b + c\n return d' In this code fragment, the 'len' built-in name is used. The IDE offers to apply the Rename refactoring as a fix.", - "markdown": "Reports shadowing built-in names, such as `len` or `list`.\n\n**Example:**\n\n\n def len(a, b, c):\n d = a + b + c\n return d\n\nIn this code fragment, the `len` built-in name is used. The IDE offers to\napply the Rename refactoring as a fix." + "text": "Reports characters in byte literals that are outside ASCII range. Example: 's = b'№5''", + "markdown": "Reports characters in byte literals that are outside ASCII range.\n\n**Example:**\n\n\n s = b'№5'\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyShadowingBuiltins", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyByteLiteral", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2820,28 +2832,28 @@ ] }, { - "id": "PyMethodOverridingInspection", + "id": "PyAugmentAssignmentInspection", "shortDescription": { - "text": "Method signature does not match signature of overridden method" + "text": "Assignment can be replaced with augmented assignment" }, "fullDescription": { - "text": "Reports inconsistencies in overriding method signatures. Example: 'class Book:\n def add_title(self):\n pass\n\n\nclass Novel(Book):\n def add_title(self, text):\n pass' Parameters of the 'add_title' method in the 'Novel' class do not match the method signature specified in the 'Book' class. As a fix, the IDE offers to apply the Change Signature refactoring.", - "markdown": "Reports inconsistencies in overriding method signatures.\n\n**Example:**\n\n\n class Book:\n def add_title(self):\n pass\n\n\n class Novel(Book):\n def add_title(self, text):\n pass\n\nParameters of the `add_title` method in the `Novel` class do not match the method\nsignature specified in the `Book` class. As a fix, the IDE offers to apply the Change Signature\nrefactoring." + "text": "Reports assignments that can be replaced with augmented assignments. Example: 'a = 23\nb = 3\na = a + b' After the quick-fix is applied, the code changes to: 'a = 23\nb = 3\na += b'", + "markdown": "Reports assignments that can be replaced with augmented assignments.\n\n**Example:**\n\n\n a = 23\n b = 3\n a = a + b\n\nAfter the quick-fix is applied, the code changes to:\n\n\n a = 23\n b = 3\n a += b\n" }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "note", "parameters": { - "suppressToolId": "PyMethodOverriding", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyAugmentAssignment", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2853,19 +2865,19 @@ ] }, { - "id": "PyTestParametrizedInspection", + "id": "PyDeprecationInspection", "shortDescription": { - "text": "Incorrect arguments in @pytest.mark.parametrize" + "text": "Deprecated function, class, or module" }, "fullDescription": { - "text": "Reports functions that are decorated with @pytest.mark.parametrize but do not have arguments to accept parameters of the decorator.", - "markdown": "Reports functions that are decorated with [@pytest.mark.parametrize](https://docs.pytest.org/en/stable/parametrize.html) but do not have arguments to accept\nparameters of the decorator." + "text": "Reports usages of Python functions, or methods that are marked as deprecated and raise the 'DeprecationWarning' or 'PendingDeprecationWarning' warning. Also, this inspection highlights usages of 'abc.abstractstaticmethod', 'abc.abstractproperty', and 'abc.abstractclassmethod' decorators. Example: 'class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\nfoo = Foo()\nprint(foo.bar)'", + "markdown": "Reports usages of Python functions, or methods that are marked as\ndeprecated and raise the `DeprecationWarning` or `PendingDeprecationWarning` warning.\n\nAlso, this inspection highlights usages of `abc.abstractstaticmethod`, `abc.abstractproperty`, and `abc.abstractclassmethod`\ndecorators.\n\n**Example:**\n\n\n class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\n foo = Foo()\n print(foo.bar)\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyTestParametrized", + "suppressToolId": "PyDeprecation", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2874,7 +2886,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2886,19 +2898,19 @@ ] }, { - "id": "PyDecoratorInspection", + "id": "PyUnnecessaryBackslashInspection", "shortDescription": { - "text": "Class-specific decorator is used outside the class" + "text": "Unnecessary backslash" }, "fullDescription": { - "text": "Reports usages of '@classmethod' or '@staticmethod' decorators in methods outside a class. Example: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n@classmethod\ndef change_state(self):\n pass' The 'change_state' method should not use the '@classmethod' decorator or it should be moved to the 'State' class declaration. If you apply the 'Remove decorator' action, the code changes to: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\ndef change_state(self):\n pass'", - "markdown": "Reports usages of `@classmethod` or `@staticmethod` decorators\nin methods outside a class.\n\n**Example:**\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n @classmethod\n def change_state(self):\n pass\n\nThe `change_state` method should not use the `@classmethod` decorator or it should be\nmoved to the `State` class declaration.\n\nIf you apply the `Remove decorator` action, the code changes to:\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n def change_state(self):\n pass\n" + "text": "Reports backslashes in places where line continuation is implicit inside '()', '[]', and '{}'. Example: 'a = ('first', \\\n 'second', 'third')' When the quick-fix is applied, the redundant backslash is deleted.", + "markdown": "Reports backslashes in places where line continuation is implicit inside `()`,\n`[]`, and `{}`.\n\n**Example:**\n\n\n a = ('first', \\\n 'second', 'third')\n\nWhen the quick-fix is applied, the redundant backslash is deleted." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyDecorator", + "suppressToolId": "PyUnnecessaryBackslash", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -2907,7 +2919,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2919,28 +2931,28 @@ ] }, { - "id": "PyAsyncCallInspection", + "id": "PyShadowingNamesInspection", "shortDescription": { - "text": "Missing `await` syntax in coroutine calls" + "text": "Shadowing names from outer scopes" }, "fullDescription": { - "text": "Reports coroutines that were called without using the 'await' syntax. Example: 'async def bar():\n pass\n\n\nasync def foo():\n bar()' After the quick-fix is applied, the code changes to: 'async def bar():\n pass\n\n\nasync def foo():\n await bar()'", - "markdown": "Reports coroutines that were called\nwithout using the `await` syntax.\n\n**Example:**\n\n\n async def bar():\n pass\n\n\n async def foo():\n bar()\n\nAfter the quick-fix is applied, the code changes to:\n\n\n async def bar():\n pass\n\n\n async def foo():\n await bar()\n" + "text": "Reports shadowing names defined in outer scopes. Example: 'def outer(p):\n def inner(p):\n pass' As a quick-fix, the IDE offers to remove a parameter or rename it.", + "markdown": "Reports shadowing names defined in outer scopes.\n\n**Example:**\n\n\n def outer(p):\n def inner(p):\n pass\n\nAs a quick-fix, the IDE offers to remove a parameter or rename it." }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyAsyncCall", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyShadowingNames", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2952,28 +2964,28 @@ ] }, { - "id": "PyComparisonWithNoneInspection", + "id": "PyFinalInspection", "shortDescription": { - "text": "Using equality operators to compare with None" + "text": "Invalid usages of final classes, methods, and variables" }, "fullDescription": { - "text": "Reports comparisons with 'None'. That type of comparisons should always be done with 'is' or 'is not', never the equality operators. Example: 'a = 2\n\n\nif a == None:\n print(\"Success\")' Once the quick-fix is applied, the code changes to: 'a = 2\n\n\nif a is None:\n print(\"Success\")'", - "markdown": "Reports comparisons with `None`. That type of comparisons\nshould always be done with `is` or `is not`, never\nthe equality operators.\n\n**Example:**\n\n\n a = 2\n\n\n if a == None:\n print(\"Success\")\n\nOnce the quick-fix is applied, the code changes to:\n\n\n a = 2\n\n\n if a is None:\n print(\"Success\")\n" + "text": "Reports invalid usages of final classes, methods and variables. Example: 'from typing import final\n\n\n@final\nclass A:\n def a_method(self):\n pass\n\n\nclass B(A):\n def a_method(self):\n pass'", + "markdown": "Reports invalid usages of final classes,\nmethods and variables.\n\n**Example:**\n\n\n from typing import final\n\n\n @final\n class A:\n def a_method(self):\n pass\n\n\n class B(A):\n def a_method(self):\n pass\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyComparisonWithNone", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyFinal", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -2985,19 +2997,19 @@ ] }, { - "id": "CommandLineInspection", + "id": "DjangoCloseTagInspection", "shortDescription": { - "text": "Incorrect CLI syntax" + "text": "Mismatched opening and closing tags" }, "fullDescription": { - "text": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies that option names and arguments are correct. Do not disable the inspection if you are going to use command-line interfaces like manage.py in Django.", - "markdown": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies\nthat option names and arguments are correct.\n\nDo not disable the inspection if you are going to use command-line interfaces like [manage.py in Django](https://www.jetbrains.com/help/pycharm/running-manage-py.html)." + "text": "Reports cases when opening tags in Django templates are not correctly matched by closing tags. Example: '{% if error_message %}

{{ error_message }}

{% endif %}' The IDE reports an error on the 'strong' tag not being closed.", + "markdown": "Reports cases when opening tags in Django templates are not correctly matched by closing tags.\n\n**Example:**\n\n\n {% if error_message %}

{{ error_message }}

{% endif %}\n\nThe IDE reports an error on the `strong` tag not being closed." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "CommandLineInspection", + "suppressToolId": "DjangoCloseTagInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3005,8 +3017,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -3018,19 +3030,19 @@ ] }, { - "id": "PyMethodParametersInspection", + "id": "PySingleQuotedDocstringInspection", "shortDescription": { - "text": "Improper first parameter" + "text": "Single quoted docstring" }, "fullDescription": { - "text": "Reports methods that lack the first parameter that is usually named 'self'. Example: 'class Movie:\n\n def show():\n pass' When the quick-fix is applied, the code changes to: 'class Movie:\n\n def show(self):\n pass' The inspection also reports naming issues in class methods. Example: 'class Movie:\n @classmethod\n def show(abc):\n pass' Since the first parameter of a class method should be 'cls', the IDE provides a quick-fix to rename it.", - "markdown": "Reports methods that lack the first parameter that is usually\nnamed `self`.\n\n**Example:**\n\n\n class Movie:\n\n def show():\n pass\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Movie:\n\n def show(self):\n pass\n\nThe inspection also reports naming issues in class methods.\n\n**Example:**\n\n\n class Movie:\n @classmethod\n def show(abc):\n pass\n\nSince the first parameter of a class method should be `cls`, the IDE provides a quick-fix\nto rename it." + "text": "Reports docstrings that do not adhere to the triple double-quoted string format. Example: 'def calc(self, balance=0):\n 'param: balance'\n self.balance = balance' When the quick-fix is applied, the code changes to: 'def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance'", + "markdown": "Reports docstrings that do not adhere to the triple double-quoted string format.\n\n**Example:**\n\n\n def calc(self, balance=0):\n 'param: balance'\n self.balance = balance\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance\n" }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyMethodParameters", + "suppressToolId": "PySingleQuotedDocstring", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -3039,7 +3051,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3051,19 +3063,19 @@ ] }, { - "id": "PyDocstringTypesInspection", + "id": "PyUnusedLocalInspection", "shortDescription": { - "text": "Type in docstring does not match inferred type" + "text": "Unused local symbols" }, "fullDescription": { - "text": "Reports types in docstring that do not match dynamically inferred types.", - "markdown": "Reports types in docstring that do not match dynamically inferred types." + "text": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function.", + "markdown": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function." }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyDocstringTypes", + "suppressToolId": "PyUnusedLocal", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -3072,7 +3084,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3084,19 +3096,19 @@ ] }, { - "id": "PyMethodFirstArgAssignmentInspection", + "id": "PyReturnFromInitInspection", "shortDescription": { - "text": "First argument of the method is reassigned" + "text": "__init__ method that returns a value" }, "fullDescription": { - "text": "Reports cases when the first parameter, such as 'self' or 'cls', is reassigned in a method. Because in most cases, there are no objectives in such reassignment, the IDE indicates an error. Example: 'class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self' As a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct, you can invoke intention actions for this code and opt to ignore the warning.", - "markdown": "Reports cases when the first parameter,\nsuch as `self` or `cls`, is reassigned in a method.\nBecause in most cases, there are no objectives in such reassignment, the\nIDE indicates an error.\n\n**Example:**\n\n\n class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self\n\nAs a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct,\nyou can invoke intention actions for this code and opt to ignore the warning." + "text": "Reports occurrences of 'return' statements with a return value inside '__init__' methods of classes. Example: 'class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum' A constructor should not return any value. The '__init__' method should only initialize the values of instance members for news objects. As a quick-fix, the IDE offers to remove the 'return' statement.", + "markdown": "Reports occurrences of `return` statements with a return value inside\n`__init__` methods of classes.\n\n**Example:**\n\n\n class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum\n\nA constructor should not return any value. The `__init__` method should\nonly initialize the values of instance members for news objects.\n\nAs a quick-fix, the IDE offers to remove the `return` statement." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyMethodFirstArgAssignment", + "suppressToolId": "PyReturnFromInit", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3105,7 +3117,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3117,19 +3129,19 @@ ] }, { - "id": "PyTupleAssignmentBalanceInspection", + "id": "Query_restricted", "shortDescription": { - "text": "Tuple assignment balance is incorrect" + "text": "Query does not comply with the query restrictions" }, "fullDescription": { - "text": "Reports cases when the number of expressions on the right-hand side and targets on the left-hand side are not the same. Example: 't = ('red', 'blue', 'green', 'white')\n(c1, c2, c3) = t' As a quick-fix, you can modify the highlighted code fragment to restore the tuple balance.", - "markdown": "Reports cases when the number of expressions on the right-hand side\nand targets on the left-hand side are not the same.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n (c1, c2, c3) = t\n\nAs a quick-fix, you can modify the highlighted code fragment to restore the tuple\nbalance." + "text": "Reports GQL queries that do not comply with the restrictions for queries allowed on the Google App Engine server. See the App Engine documentation for more information.", + "markdown": "Reports GQL queries that do not comply with the restrictions for queries allowed\non the Google App Engine server.\nSee the [App Engine documentation](http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Restrictions_on_Queries) for more information." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyTupleAssignmentBalance", + "suppressToolId": "Query_restricted", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3137,8 +3149,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Google App Engine (Python)", + "index": 4, "toolComponent": { "name": "QDPY" } @@ -3150,19 +3162,19 @@ ] }, { - "id": "PyClassHasNoInitInspection", + "id": "PyMissingOrEmptyDocstringInspection", "shortDescription": { - "text": "Class has no `__init__` method" + "text": "Missing or empty docstring" }, "fullDescription": { - "text": "Reports cases in Python 2 when a class has no '__init__' method, neither its parent classes. Example: 'class Book():\n pass' The quick-fix adds the '__init__' method: 'class Book():\n def __init__(self):\n pass'", - "markdown": "Reports cases in Python 2 when a class has no `__init__` method, neither its parent\nclasses.\n\n**Example:**\n\n\n class Book():\n pass\n\nThe quick-fix adds the `__init__` method:\n\n\n class Book():\n def __init__(self):\n pass\n" + "text": "Reports missing and empty docstrings. Example of a missing docstring 'def demo(a):\n c = a ** 2' Example of an empty docstring 'def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2' When the quick-fix is applied, the code fragments change to: 'def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2' You need to provide some details about the parameter in the generated template.", + "markdown": "Reports missing and empty docstrings.\n\n**Example of a missing docstring**\n\n\n def demo(a):\n c = a ** 2\n\n**Example of an empty docstring**\n\n\n def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2\n\nWhen the quick-fix is applied, the code fragments change to:\n\n\n def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2\n\nYou need to provide some details about the parameter in the generated template." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "note", "parameters": { - "suppressToolId": "PyClassHasNoInit", + "suppressToolId": "PyMissingOrEmptyDocstring", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -3171,7 +3183,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3183,19 +3195,19 @@ ] }, { - "id": "PyArgumentEqualDefaultInspection", + "id": "PyPep8NamingInspection", "shortDescription": { - "text": "The function argument is equal to the default parameter value" + "text": "PEP 8 naming convention violation" }, "fullDescription": { - "text": "Reports a problem when an argument passed to the function is equal to the default parameter value. This inspection is disabled by default to avoid performance degradation. Example: 'def my_function(a: int = 2):\n print(a)\n\n\nmy_function(2)'", - "markdown": "Reports a problem when an argument\npassed to the function is equal to the default parameter value.\n\nThis inspection is disabled by default to avoid performance degradation.\n\n**Example:**\n\n\n def my_function(a: int = 2):\n print(a)\n\n\n my_function(2)\n" + "text": "Reports violations of the PEP8 naming conventions. Example: 'class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")' In this code fragment, IDE offers to rename 'mammalia' to 'Mammalia'. When the quick-fix is applied, the code change to: 'class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")'", + "markdown": "Reports violations of the\n[PEP8](https://www.python.org/dev/peps/pep-0008/) naming conventions.\n\n**Example:**\n\n\n class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n\nIn this code fragment, IDE offers to rename `mammalia` to `Mammalia`.\nWhen the quick-fix is applied, the code change to:\n\n\n class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyArgumentEqualDefault", + "suppressToolId": "PyPep8Naming", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -3204,7 +3216,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3216,19 +3228,19 @@ ] }, { - "id": "PyClassVarInspection", + "id": "DjangoUnresolvedLoadInspection", "shortDescription": { - "text": "Invalid usage of ClassVar variables" + "text": "Unresolved library inspection" }, "fullDescription": { - "text": "Reports invalid usages of ClassVar annotations. Example: 'from typing import ClassVar\n\n\nclass Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\nCat.color = \"black\" # OK\nmy_cat = Cat(5)\nmy_cat.color = \"gray\" # Error, setting class variable on instance'", - "markdown": "Reports invalid usages of [ClassVar](https://docs.python.org/3/library/typing.html#typing.ClassVar) annotations.\n\n**Example:**\n\n\n from typing import ClassVar\n\n\n class Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\n Cat.color = \"black\" # OK\n my_cat = Cat(5)\n my_cat.color = \"gray\" # Error, setting class variable on instance\n" + "text": "Reports unresolved references in Django load tags. Example: '{% load something_nonexistent %}'", + "markdown": "Reports unresolved references in Django load tags.\n\n**Example:**\n\n\n {% load something_nonexistent %}\n" }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyClassVar", + "suppressToolId": "DjangoUnresolvedLoadInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3236,8 +3248,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -3249,19 +3261,19 @@ ] }, { - "id": "DjangoRelationInspection", + "id": "PyDictDuplicateKeysInspection", "shortDescription": { - "text": "Incorrect comparison expression in Django templates" + "text": "Dictionary contains duplicate keys" }, "fullDescription": { - "text": "Reports missing whitespaces before and after comparison operators in Django templates. Example: '{% if my_var==1 %}\n{% endif %}'", - "markdown": "Reports missing whitespaces before and after comparison operators in Django templates.\n\n**Example:**\n\n\n {% if my_var==1 %}\n {% endif %}\n" + "text": "Reports using the same value as the dictionary key twice. Example: 'dic = {\"a\": [1, 2], \"a\": [3, 4]}'", + "markdown": "Reports using the same value as the dictionary key twice.\n\n**Example:**\n\n\n dic = {\"a\": [1, 2], \"a\": [3, 4]}\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "DjangoRelationInspection", + "suppressToolId": "PyDictDuplicateKeys", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3269,8 +3281,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3282,28 +3294,28 @@ ] }, { - "id": "PyFromFutureImportInspection", + "id": "PyNoneFunctionAssignmentInspection", "shortDescription": { - "text": "Improper position of from __future__ import" + "text": "Assigning function calls that don't return anything" }, "fullDescription": { - "text": "Reports 'from __future__ import' statements that are used not at the beginning of a file. Example: 'a = 1\nfrom __future__ import print_function\nprint()' When the quick-fix is applied, the code changes to: 'from __future__ import print_function\n\na = 1\nprint()'", - "markdown": "Reports `from __future__ import`\nstatements that are used not at\nthe beginning of a file.\n\n**Example:**\n\n\n a = 1\n from __future__ import print_function\n print()\n\nWhen the quick-fix is applied, the code changes to:\n\n\n from __future__ import print_function\n\n a = 1\n print()\n" + "text": "Reports cases when an assignment is done on a function that does not return anything. This inspection is similar to pylint inspection E1111. Example: 'def just_print():\n print(\"Hello!\")\n\n\naction = just_print()' As a quick-fix, the IDE offers to remove the assignment.", + "markdown": "Reports cases when an assignment is done on a function that does not return anything.\nThis inspection is similar to [pylint inspection E1111](https://docs.pylint.org/en/1.6.0/features.html#id6).\n\n**Example:**\n\n\n def just_print():\n print(\"Hello!\")\n\n\n action = just_print()\n\nAs a quick-fix, the IDE offers to remove the assignment." }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyFromFutureImport", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyNoneFunctionAssignment", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3315,19 +3327,19 @@ ] }, { - "id": "PyUnresolvedReferencesInspection", + "id": "JupyterPackageInspection", "shortDescription": { - "text": "Unresolved references" + "text": "The 'jupyter' package is not installed" }, "fullDescription": { - "text": "Reports references in your code that cannot be resolved. In a dynamically typed language, this is possible in a limited number of cases. If a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be: 'def print_string(s):\n print(s.abc())' In this code fragment 's' is always a string and 'abc' should be highlighted as unresolved. However, 's' type is inferred as 'Any' and no warning is reported. The IDE provides quick-fix actions to add missing references on-the-fly.", - "markdown": "Reports references in your code that cannot be resolved.\n\nIn a dynamically typed language, this is possible in a limited number of cases.\n\nIf a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be:\n\n\n def print_string(s):\n print(s.abc())\n\nIn this code fragment `s` is always a string and `abc` should be highlighted as unresolved. However, `s`\ntype is inferred as `Any` and no warning is reported.\n\nThe IDE provides quick-fix actions to add missing references on-the-fly." + "text": "Reports cases when the 'jupyter' package is not installed for the selected Python interpreter. Without a properly installed 'jupyter' package, you cannot execute Jupyter notebooks. Click the corresponding link on the warning banner to install the missing package. You can also install the package in the Project Settings/Preferences or in the Python Packages tool window. See Installing Python package for more details.", + "markdown": "Reports cases when the `jupyter` package is not installed for the selected\nPython interpreter. Without a properly installed `jupyter` package, you cannot\nexecute Jupyter notebooks.\n\nClick the corresponding link on the warning banner to install the missing\npackage. You can also install the package in the Project **Settings/Preferences** or in the\n**Python Packages** tool window.\n\nSee [Installing Python package](https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-upgrading-packages.html) for more details." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PyUnresolvedReferences", + "suppressToolId": "JupyterPackage", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3335,8 +3347,8 @@ "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Jupyter", + "index": 58, "toolComponent": { "name": "QDPY" } @@ -3348,19 +3360,19 @@ ] }, { - "id": "PyPackageRequirementsInspection", + "id": "PyStatementEffectInspection", "shortDescription": { - "text": "Unsatisfied package requirements" + "text": "Statement has no effect" }, "fullDescription": { - "text": "Reports packages mentioned in requirements files (for example, 'requirements.txt' or 'Pipfile') but not installed, or imported but not mentioned in requirements files. The IDE shows a quick-fix banner so that you can install the missing packages in one click.", - "markdown": "Reports packages mentioned in requirements files (for example, `requirements.txt` or `Pipfile`) but not installed,\nor imported but not mentioned in requirements files.\n\n\nThe IDE shows a quick-fix banner so that you can install the missing packages in one click." + "text": "Reports statements that have no effect. Example: 'class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n2 + 3 # has no effect' In this example, you can either add a field 'time' to the 'Car' class or introduce variables for the problematic statements.", + "markdown": "Reports statements that have no effect.\n\n**Example:**\n\n\n class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n 2 + 3 # has no effect\n\nIn this example, you can either add a field `time` to the `Car` class or\nintroduce variables for the problematic statements." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyPackageRequirements", + "suppressToolId": "PyStatementEffect", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3369,7 +3381,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3381,19 +3393,19 @@ ] }, { - "id": "Restricted_Python_calls", + "id": "PyMandatoryEncodingInspection", "shortDescription": { - "text": "Feature is not supported in the App Engine sandbox" + "text": "No encoding specified for file" }, "fullDescription": { - "text": "Reports usages of Python features that are restricted by the Google App Engine sandbox and will cause a failure on the production server.", - "markdown": "Reports usages of Python features that are restricted by the Google App\nEngine sandbox and will cause a failure on the production server." + "text": "Reports a missing encoding comment in Python 2. Example: 'class Book(object):\n def __init__(self):\n pass' When the quick-fix is applied, the missing comment is added: '# coding=utf-8\nclass Book(object):\n def __init__(self):\n pass'", + "markdown": "Reports a missing encoding comment in Python 2.\n\n**Example:**\n\n\n class Book(object):\n def __init__(self):\n pass\n\nWhen the quick-fix is applied, the missing comment is added:\n\n\n # coding=utf-8\n class Book(object):\n def __init__(self):\n pass\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "Restricted_Python_calls", + "suppressToolId": "PyMandatoryEncoding", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3401,8 +3413,8 @@ "relationships": [ { "target": { - "id": "Google App Engine (Python)", - "index": 4, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3414,28 +3426,28 @@ ] }, { - "id": "PyRedundantParenthesesInspection", + "id": "PyInconsistentIndentationInspection", "shortDescription": { - "text": "Redundant parentheses" + "text": "Inconsistent indentation" }, "fullDescription": { - "text": "Reports about redundant parentheses in expressions. The IDE provides the quick-fix action to remove the redundant parentheses.", - "markdown": "Reports about redundant parentheses in expressions.\n\nThe IDE provides the quick-fix action to remove the redundant parentheses." + "text": "Reports inconsistent indentation in Python source files when, for example, you use a mixture of tabs and spaces in your code.", + "markdown": "Reports inconsistent indentation in Python source files when, for example,\nyou use a mixture of tabs and spaces in your code." }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyRedundantParentheses", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyInconsistentIndentation", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3447,28 +3459,28 @@ ] }, { - "id": "PyTrailingSemicolonInspection", + "id": "PyAttributeOutsideInitInspection", "shortDescription": { - "text": "Prohibited trailing semicolon in a statement" + "text": "An instance attribute is defined outside `__init__`" }, "fullDescription": { - "text": "Reports trailing semicolons in statements. Example: 'def my_func(a):\n c = a ** 2;\n return c' IDE provides a quick-fix that removes a trailing semicolon. When you apply it, the code changes to: 'def my_func(a):\n c = a ** 2\n return c'", - "markdown": "Reports trailing semicolons in statements.\n\n**Example:**\n\n\n def my_func(a):\n c = a ** 2;\n return c\n\nIDE provides a quick-fix that removes a trailing semicolon. When you\napply it, the code changes to:\n\n\n def my_func(a):\n c = a ** 2\n return c\n" + "text": "Reports a problem when instance attribute definition is outside '__init__' method. Example: 'class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'' When the quick-fix is applied, the code sample changes to: 'class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass'", + "markdown": "Reports a problem when instance attribute definition is outside `__init__` method.\n\n**Example:**\n\n\n class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'\n\n\nWhen the quick-fix is applied, the code sample changes to:\n\n\n class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass\n" }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyTrailingSemicolon", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyAttributeOutsideInit", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3480,19 +3492,19 @@ ] }, { - "id": "ExtendsTagPositionInspection", + "id": "PyTypedDictInspection", "shortDescription": { - "text": "Misplaced {% extends %} tag" + "text": "Invalid TypedDict definition and usages" }, "fullDescription": { - "text": "Reports the '{% extends %}' tag that is not the first tag in a Django template. Example: '{% load my_custom_tags %}\n{% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}' In this example, the '{% extends %}' tag is highlighted, because it should be placed before the '{% load %}' tag.", - "markdown": "Reports the `{% extends %}` tag that is not the first tag in a\nDjango template.\n\n**Example:**\n\n\n {% load my_custom_tags %}\n {% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}\n\nIn this example, the `{% extends %}` tag is highlighted, because it should be placed before\nthe `{% load %}` tag." + "text": "Reports invalid definition and usage of TypedDict. Example: 'from typing import TypedDict\n\n\nclass Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\nm = Movie(name=\"name\", year=1000, rate=9)\nprint(m[\"director\"]) # There is no the 'director' key in 'Movie'\ndel m[\"name\"] # The 'name' key cannot be deleted\nm[\"year\"] = \"1001\" # Expected 'int', got 'str''", + "markdown": "Reports invalid definition and usage of\n[TypedDict](https://www.python.org/dev/peps/pep-0589/).\n\n**Example:**\n\n\n from typing import TypedDict\n\n\n class Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\n m = Movie(name=\"name\", year=1000, rate=9)\n print(m[\"director\"]) # There is no the 'director' key in 'Movie'\n del m[\"name\"] # The 'name' key cannot be deleted\n m[\"year\"] = \"1001\" # Expected 'int', got 'str'\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "ExtendsTagPositionInspection", + "suppressToolId": "PyTypedDict", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3500,8 +3512,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3513,28 +3525,28 @@ ] }, { - "id": "PyArgumentListInspection", + "id": "PyPep8Inspection", "shortDescription": { - "text": "Incorrect call arguments" + "text": "PEP 8 coding style violation" }, "fullDescription": { - "text": "Reports discrepancies between declared parameters and actual arguments, as well as incorrect arguments, for example, duplicate named arguments, and incorrect argument order. Example: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__() # unfilled parameter\nbar(5, \"#\") # unexpected argument' The correct code fragment looks at follows: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__(5)\nbar(5, p2=\"#\")'", - "markdown": "Reports discrepancies between declared parameters and actual arguments, as well as\nincorrect arguments, for example, duplicate named arguments, and incorrect argument order.\n\n**Example:**\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__() # unfilled parameter\n bar(5, \"#\") # unexpected argument\n\nThe correct code fragment looks at follows:\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__(5)\n bar(5, p2=\"#\")\n" + "text": "Reports violations of the PEP 8 coding style guide by running the bundled pycodestyle.py tool.", + "markdown": "Reports violations of the [PEP 8 coding style guide](https://www.python.org/dev/peps/pep-0008/) by running the bundled [pycodestyle.py](https://github.com/PyCQA/pycodestyle) tool." }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyArgumentList", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyPep8", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3546,28 +3558,28 @@ ] }, { - "id": "PyInterpreterInspection", + "id": "PyMissingTypeHintsInspection", "shortDescription": { - "text": "An invalid interpreter" + "text": "Missing type hinting for function definition" }, "fullDescription": { - "text": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly configured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features. The IDE provides quick access to the interpreter settings.", - "markdown": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly\nconfigured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features.\n\nThe IDE provides quick access to the interpreter settings." + "text": "Reports missing type hints for function declaration in one of the two formats: parameter annotations or a type comment. Select the Only when types are known checkbox if you want the inspection check the types collected from runtime or inferred.", + "markdown": "Reports missing type hints for function declaration in\none of the two formats: parameter annotations or a type comment.\n\nSelect the **Only when types are known** checkbox if you want the inspection check\nthe types collected from runtime or inferred." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyInterpreter", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyMissingTypeHints", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3579,19 +3591,19 @@ ] }, { - "id": "PyPropertyAccessInspection", + "id": "PyTupleItemAssignmentInspection", "shortDescription": { - "text": "Inappropriate access to properties" + "text": "Tuple item assignment is prohibited" }, "fullDescription": { - "text": "Reports cases when properties are accessed inappropriately: Read-only properties are set Write-only properties are read Non-deletable properties are deleted Example: 'class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\na = MyClass()\na.read_only = 10 # property cannot be set\ndel a.read_only # property cannot be deleted\nprint(a.write_only) # property cannot be read'", - "markdown": "Reports cases when properties are accessed inappropriately:\n\n* Read-only properties are set\n* Write-only properties are read\n* Non-deletable properties are deleted\n\n**Example:**\n\n\n class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\n a = MyClass()\n a.read_only = 10 # property cannot be set\n del a.read_only # property cannot be deleted\n print(a.write_only) # property cannot be read\n" + "text": "Reports assignments to a tuple item. Example: 't = ('red', 'blue', 'green', 'white')\nt[3] = 'black'' A quick-fix offers to replace the tuple with a list.", + "markdown": "Reports assignments to a tuple item.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n t[3] = 'black'\n\nA quick-fix offers to replace the tuple with a list." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyPropertyAccess", + "suppressToolId": "PyTupleItemAssignment", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3600,7 +3612,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3612,28 +3624,28 @@ ] }, { - "id": "PyStubPackagesAdvertiser", + "id": "DjangoUnresolvedUrlInspection", "shortDescription": { - "text": "Stub packages advertiser" + "text": "Django {% url %} tag arguments are unresolved" }, "fullDescription": { - "text": "Reports availability of stub packages. Stub package is a package that contains type information for the corresponding runtime package. Using stub packages ensures better coding assistance for the corresponding python package.", - "markdown": "Reports availability of stub packages.\n\n\n[Stub package](https://www.python.org/dev/peps/pep-0561/) is a package that contains type information for the corresponding\nruntime package.\n\nUsing stub packages ensures better coding assistance for the corresponding python package." + "text": "Reports a missing url in the 'url' tag. Example: '{% url 'url_name' %}' The IDE shows a warning if 'url_name' is not defined in the 'urls' file.", + "markdown": "Reports a missing url in the `url` tag.\n\n**Example:**\n\n\n {% url 'url_name' %}\n\nThe IDE shows a warning if `url_name` is not defined in the `urls` file." }, "defaultConfiguration": { - "enabled": true, - "level": "warning", + "enabled": false, + "level": "note", "parameters": { - "suppressToolId": "PyStubPackagesAdvertiser", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "DjangoUnresolvedUrlInspection", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -3645,28 +3657,28 @@ ] }, { - "id": "PyRelativeImportInspection", + "id": "DjangoUnresolvedStaticReferenceInspection", "shortDescription": { - "text": "Suspicious relative imports" + "text": "Unresolved static reference" }, "fullDescription": { - "text": "Reports usages of relative imports inside plain directories, for example, directories neither containing '__init__.py' nor explicitly marked as namespace packages.", - "markdown": "Reports usages of relative imports inside plain directories, for example, directories neither containing `__init__.py` nor\nexplicitly marked as namespace packages." + "text": "Reports unresolved references to static resources. Example: '{% load staticfiles %}\n' In this example, 'style.css' is highlighted if there is no such a file in the 'static/poll' directory.", + "markdown": "Reports unresolved references to static resources.\n\n**Example:**\n\n\n {% load staticfiles %}\n \n\nIn this example, `style.css` is highlighted if there is no such a file in the `static/poll`\ndirectory." }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyPackages", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "DjangoUnresolvedStaticReferenceInspection", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -3678,19 +3690,19 @@ ] }, { - "id": "PyRedeclarationInspection", + "id": "PyDunderSlotsInspection", "shortDescription": { - "text": "Redeclared names without usages" + "text": "Invalid usages of classes with '__slots__' definitions" }, "fullDescription": { - "text": "Reports unconditional redeclarations of names without being used in between. Example: 'def x(): pass\n\n\nx = 2' It applies to function and class declarations, and top-level assignments. When the warning is shown, you can try a recommended action, for example, you might be prompted to rename the variable.", - "markdown": "Reports unconditional redeclarations of names without being used in between.\n\n**Example:**\n\n\n def x(): pass\n\n\n x = 2\n\nIt applies to function and class declarations, and top-level assignments.\n\nWhen the warning is shown, you can try a recommended action, for example, you might be prompted to\nrename the variable." + "text": "Reports invalid usages of a class with '__slots__' definitions. Example: 'class Foo:\n __slots__ = ['foo', 'bar']\n\n\nfoo = Foo()\nfoo.baz = 'spam''", + "markdown": "Reports invalid usages of a class with `__slots__` definitions.\n\n**Example:**\n\n\n class Foo:\n __slots__ = ['foo', 'bar']\n\n\n foo = Foo()\n foo.baz = 'spam'\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyRedeclaration", + "suppressToolId": "PyDunderSlots", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3699,7 +3711,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3711,19 +3723,19 @@ ] }, { - "id": "PyramidSetupInspection", + "id": "PyDefaultArgumentInspection", "shortDescription": { - "text": "Project is not installed for development" + "text": "The default argument is mutable" }, "fullDescription": { - "text": "Reports cases when no 'python setup.py develop' command was executed for the Pyramid project. You need to execute this command to install the newly created project for development.", - "markdown": "Reports cases when no `python setup.py develop` command was executed for the Pyramid project.\n\nYou need to execute this command to install the newly created project for development." + "text": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for an argument. Default argument values are evaluated only once at function definition time, which means that modifying the default value of the argument will affect all subsequent calls of that function. Example: 'def func(s, cache={}):\n cache[s] = None' When the quick-fix is applied, the code changes to: 'def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None'", + "markdown": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for\nan argument. \n\nDefault argument values are evaluated only once at function definition time,\nwhich means that modifying the\ndefault value of the argument will affect all subsequent calls of that function.\n\n**Example:**\n\n\n def func(s, cache={}):\n cache[s] = None\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyramidSetup", + "suppressToolId": "PyDefaultArgument", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3731,8 +3743,8 @@ "relationships": [ { "target": { - "id": "Pyramid", - "index": 62, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3744,19 +3756,19 @@ ] }, { - "id": "PyProtectedMemberInspection", + "id": "PyShadowingBuiltinsInspection", "shortDescription": { - "text": "Accessing a protected member of a class or a module" + "text": "Shadowing built-in names" }, "fullDescription": { - "text": "Reports cases when a protected member is accessed outside the class, a descendant of the class where it is defined, or a module. Example: 'class Foo:\n def _protected_method(self):\n pass\n\n\nclass Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\nfoo = Foo()\nfoo._protected_method() # Access to a protected method'", - "markdown": "Reports cases when a protected member is accessed outside the class,\na descendant of the class where it is defined, or a module.\n\n**Example:**\n\n\n class Foo:\n def _protected_method(self):\n pass\n\n\n class Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\n foo = Foo()\n foo._protected_method() # Access to a protected method\n" + "text": "Reports shadowing built-in names, such as 'len' or 'list'. Example: 'def len(a, b, c):\n d = a + b + c\n return d' In this code fragment, the 'len' built-in name is used. The IDE offers to apply the Rename refactoring as a fix.", + "markdown": "Reports shadowing built-in names, such as `len` or `list`.\n\n**Example:**\n\n\n def len(a, b, c):\n d = a + b + c\n return d\n\nIn this code fragment, the `len` built-in name is used. The IDE offers to\napply the Rename refactoring as a fix." }, "defaultConfiguration": { "enabled": true, "level": "note", "parameters": { - "suppressToolId": "PyProtectedMember", + "suppressToolId": "PyShadowingBuiltins", "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate" } @@ -3765,7 +3777,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3777,19 +3789,19 @@ ] }, { - "id": "PyStubPackagesCompatibilityInspection", + "id": "PyMethodOverridingInspection", "shortDescription": { - "text": "Incompatible stub packages" + "text": "Method signature does not match signature of overridden method" }, "fullDescription": { - "text": "Reports stub packages that do not support the version of the corresponding runtime package. A stub package contains type information for some runtime package.", - "markdown": "Reports stub packages that do not support the version of the corresponding runtime package.\n\nA [stub package](https://www.python.org/dev/peps/pep-0561/) contains type information for some runtime package." + "text": "Reports inconsistencies in overriding method signatures. Example: 'class Book:\n def add_title(self):\n pass\n\n\nclass Novel(Book):\n def add_title(self, text):\n pass' Parameters of the 'add_title' method in the 'Novel' class do not match the method signature specified in the 'Book' class. As a fix, the IDE offers to apply the Change Signature refactoring.", + "markdown": "Reports inconsistencies in overriding method signatures.\n\n**Example:**\n\n\n class Book:\n def add_title(self):\n pass\n\n\n class Novel(Book):\n def add_title(self, text):\n pass\n\nParameters of the `add_title` method in the `Novel` class do not match the method\nsignature specified in the `Book` class. As a fix, the IDE offers to apply the Change Signature\nrefactoring." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyStubPackagesCompatibility", + "suppressToolId": "PyMethodOverriding", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3798,7 +3810,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3810,19 +3822,19 @@ ] }, { - "id": "PyUnboundLocalVariableInspection", + "id": "PyTestParametrizedInspection", "shortDescription": { - "text": "Unbound local variables" + "text": "Incorrect arguments in @pytest.mark.parametrize" }, "fullDescription": { - "text": "Reports local variables referenced before assignment. Example: 'x = 0\nif x > 10:\n b = 3\nprint(b)' The IDE reports a problem for 'print(b)'. A possible fix is: 'x = 0\nif x > 10:\n b = 3\n print(b)'", - "markdown": "Reports local variables referenced before assignment.\n\n**Example:**\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n\nThe IDE reports a problem for `print(b)`. A possible fix is:\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n" + "text": "Reports functions that are decorated with @pytest.mark.parametrize but do not have arguments to accept parameters of the decorator.", + "markdown": "Reports functions that are decorated with [@pytest.mark.parametrize](https://docs.pytest.org/en/stable/parametrize.html) but do not have arguments to accept\nparameters of the decorator." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyUnboundLocalVariable", + "suppressToolId": "PyTestParametrized", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3831,7 +3843,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3843,19 +3855,19 @@ ] }, { - "id": "PyNamedTupleInspection", + "id": "PyDecoratorInspection", "shortDescription": { - "text": "Invalid definition of 'typing.NamedTuple'" + "text": "Class-specific decorator is used outside the class" }, "fullDescription": { - "text": "Reports invalid definition of a typing.NamedTuple. Example: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str' As a fix, place the field with the default value after the fields without default values: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"'", - "markdown": "Reports invalid definition of a\n[typing.NamedTuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).\n\n**Example:**\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str\n\nAs a fix, place the field with the default value after the fields without default values:\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"\n" + "text": "Reports usages of '@classmethod' or '@staticmethod' decorators in methods outside a class. Example: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n@classmethod\ndef change_state(self):\n pass' The 'change_state' method should not use the '@classmethod' decorator or it should be moved to the 'State' class declaration. If you apply the 'Remove decorator' action, the code changes to: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\ndef change_state(self):\n pass'", + "markdown": "Reports usages of `@classmethod` or `@staticmethod` decorators\nin methods outside a class.\n\n**Example:**\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n @classmethod\n def change_state(self):\n pass\n\nThe `change_state` method should not use the `@classmethod` decorator or it should be\nmoved to the `State` class declaration.\n\nIf you apply the `Remove decorator` action, the code changes to:\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n def change_state(self):\n pass\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyNamedTuple", + "suppressToolId": "PyDecorator", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3864,7 +3876,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3876,28 +3888,28 @@ ] }, { - "id": "PyNestedDecoratorsInspection", + "id": "PyAsyncCallInspection", "shortDescription": { - "text": "Problematic nesting of decorators" + "text": "Missing `await` syntax in coroutine calls" }, "fullDescription": { - "text": "Reports problems with nesting decorators. The inspection highlights the cases when 'classmethod' or 'staticmethod' is applied before another decorator. Example: 'def innocent(f):\n return f\n\n\nclass A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass' As a quick-fix, the IDE offers to remove the decorator.", - "markdown": "Reports problems with nesting decorators. The inspection highlights the cases when `classmethod` or `staticmethod`\nis applied before another decorator.\n\n**Example:**\n\n\n def innocent(f):\n return f\n\n\n class A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass\n\nAs a quick-fix, the IDE offers to remove the decorator." + "text": "Reports coroutines that were called without using the 'await' syntax. Example: 'async def bar():\n pass\n\n\nasync def foo():\n bar()' After the quick-fix is applied, the code changes to: 'async def bar():\n pass\n\n\nasync def foo():\n await bar()'", + "markdown": "Reports coroutines that were called\nwithout using the `await` syntax.\n\n**Example:**\n\n\n async def bar():\n pass\n\n\n async def foo():\n bar()\n\nAfter the quick-fix is applied, the code changes to:\n\n\n async def bar():\n pass\n\n\n async def foo():\n await bar()\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyNestedDecorators", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyAsyncCall", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3909,19 +3921,19 @@ ] }, { - "id": "DuplicatedBlockNamesInspection", + "id": "CommandLineInspection", "shortDescription": { - "text": "Duplicated block names" + "text": "Incorrect CLI syntax" }, "fullDescription": { - "text": "Reports duplicated block names in Django templates. Example: '\n\n\n \n {% block title %}My amazing site{% endblock %}\n\n\n\n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n\n'", - "markdown": "Reports duplicated block names in Django templates.\n\n**Example:**\n\n\n \n \n \n \n {% block title %}My amazing site{% endblock %}\n \n\n \n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n \n \n" + "text": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies that option names and arguments are correct. Do not disable the inspection if you are going to use command-line interfaces like manage.py in Django.", + "markdown": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies\nthat option names and arguments are correct.\n\nDo not disable the inspection if you are going to use command-line interfaces like [manage.py in Django](https://www.jetbrains.com/help/pycharm/running-manage-py.html)." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "DuplicatedBlockNamesInspection", + "suppressToolId": "CommandLineInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -3929,8 +3941,8 @@ "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3942,28 +3954,28 @@ ] }, { - "id": "PyOverloadsInspection", + "id": "PyComparisonWithNoneInspection", "shortDescription": { - "text": "Overloads in regular Python files" + "text": "Using equality operators to compare with None" }, "fullDescription": { - "text": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are not compatible with the implementation. Example: 'from typing import overload\n\n\n@overload\ndef foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n@overload\ndef foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\ndef foo(p1, p2, p3):\n print(p1, p2, p3)'", - "markdown": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are\nnot compatible with the implementation.\n\n**Example:**\n\n\n from typing import overload\n\n\n @overload\n def foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n @overload\n def foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\n def foo(p1, p2, p3):\n print(p1, p2, p3)\n" + "text": "Reports comparisons with 'None'. That type of comparisons should always be done with 'is' or 'is not', never the equality operators. Example: 'a = 2\n\n\nif a == None:\n print(\"Success\")' Once the quick-fix is applied, the code changes to: 'a = 2\n\n\nif a is None:\n print(\"Success\")'", + "markdown": "Reports comparisons with `None`. That type of comparisons\nshould always be done with `is` or `is not`, never\nthe equality operators.\n\n**Example:**\n\n\n a = 2\n\n\n if a == None:\n print(\"Success\")\n\nOnce the quick-fix is applied, the code changes to:\n\n\n a = 2\n\n\n if a is None:\n print(\"Success\")\n" }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyOverloads", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyComparisonWithNone", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -3975,28 +3987,28 @@ ] }, { - "id": "AppEngineThreadsafeInspection", + "id": "PyMethodParametersInspection", "shortDescription": { - "text": "Threadsafe is not available or set inappropriately" + "text": "Improper first parameter" }, "fullDescription": { - "text": "Reports cases when threadsafe is not present or it is not set to either 'yes' or 'no'.", - "markdown": "Reports cases when threadsafe is not present or it is not set to either `yes` or `no`." + "text": "Reports methods that lack the first parameter that is usually named 'self'. Example: 'class Movie:\n\n def show():\n pass' When the quick-fix is applied, the code changes to: 'class Movie:\n\n def show(self):\n pass' The inspection also reports naming issues in class methods. Example: 'class Movie:\n @classmethod\n def show(abc):\n pass' Since the first parameter of a class method should be 'cls', the IDE provides a quick-fix to rename it.", + "markdown": "Reports methods that lack the first parameter that is usually\nnamed `self`.\n\n**Example:**\n\n\n class Movie:\n\n def show():\n pass\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Movie:\n\n def show(self):\n pass\n\nThe inspection also reports naming issues in class methods.\n\n**Example:**\n\n\n class Movie:\n @classmethod\n def show(abc):\n pass\n\nSince the first parameter of a class method should be `cls`, the IDE provides a quick-fix\nto rename it." }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "AppEngineThreadsafe", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyMethodParameters", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Google App Engine (Python)", - "index": 4, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4008,28 +4020,28 @@ ] }, { - "id": "PyExceptClausesOrderInspection", + "id": "PyDocstringTypesInspection", "shortDescription": { - "text": "Wrong order of 'except' clauses" + "text": "Type in docstring does not match inferred type" }, "fullDescription": { - "text": "Reports cases when 'except' clauses are not in the proper order, from the more specific to the more generic, or one exception class is caught twice. If you do not fix the order, some exceptions may not be caught by the most specific handler. Example: 'try:\n call()\nexcept ValueError:\n pass\nexcept UnicodeError:\n pass' The IDE recommends moving the clause up. When the quick-fix is applied, the code changes to: 'try:\n call()\nexcept UnicodeError:\n pass\nexcept ValueError:\n pass'", - "markdown": "Reports cases when `except` clauses are not in the proper order,\nfrom the more specific to the more generic, or one exception class is caught twice.\n\n\nIf you do not fix the order, some exceptions may not be caught by the most specific handler.\n\n**Example:**\n\n\n try:\n call()\n except ValueError:\n pass\n except UnicodeError:\n pass\n\nThe IDE recommends moving the clause up. When the quick-fix is applied, the code changes to:\n\n\n try:\n call()\n except UnicodeError:\n pass\n except ValueError:\n pass\n" + "text": "Reports types in docstring that do not match dynamically inferred types.", + "markdown": "Reports types in docstring that do not match dynamically inferred types." }, "defaultConfiguration": { "enabled": true, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "PyExceptClausesOrder", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyDocstringTypes", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4041,19 +4053,19 @@ ] }, { - "id": "PyDataclassInspection", + "id": "PyMethodFirstArgAssignmentInspection", "shortDescription": { - "text": "Invalid definition and usage of Data Classes" + "text": "First argument of the method is reassigned" }, "fullDescription": { - "text": "Reports invalid definitions and usages of classes created with 'dataclasses' or 'attr' modules. Example: 'import dataclasses\n\n\n@dataclasses.dataclass\nclass FullName:\n first: str\n middle: str = \"\"\n last: str'", - "markdown": "Reports invalid definitions and usages of classes created with\n`dataclasses` or `attr` modules.\n\n**Example:**\n\n\n import dataclasses\n\n\n @dataclasses.dataclass\n class FullName:\n first: str\n middle: str = \"\"\n last: str\n" + "text": "Reports cases when the first parameter, such as 'self' or 'cls', is reassigned in a method. Because in most cases, there are no objectives in such reassignment, the IDE indicates an error. Example: 'class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self' As a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct, you can invoke intention actions for this code and opt to ignore the warning.", + "markdown": "Reports cases when the first parameter,\nsuch as `self` or `cls`, is reassigned in a method.\nBecause in most cases, there are no objectives in such reassignment, the\nIDE indicates an error.\n\n**Example:**\n\n\n class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self\n\nAs a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct,\nyou can invoke intention actions for this code and opt to ignore the warning." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyDataclass", + "suppressToolId": "PyMethodFirstArgAssignment", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4062,7 +4074,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4074,19 +4086,19 @@ ] }, { - "id": "PyprojectInspection", + "id": "PyTupleAssignmentBalanceInspection", "shortDescription": { - "text": "Depencencies in pyproject.toml" + "text": "Tuple assignment balance is incorrect" }, "fullDescription": { - "text": "Reports unsatisfied dependencies, declared [project.dependencies] table in pyproject.toml. Shows a quick-fix to install missing packages.", - "markdown": "Reports unsatisfied dependencies, declared \\[project.dependencies\\] table in pyproject.toml.\n\n\nShows a quick-fix to install missing packages." + "text": "Reports cases when the number of expressions on the right-hand side and targets on the left-hand side are not the same. Example: 't = ('red', 'blue', 'green', 'white')\n(c1, c2, c3) = t' As a quick-fix, you can modify the highlighted code fragment to restore the tuple balance.", + "markdown": "Reports cases when the number of expressions on the right-hand side\nand targets on the left-hand side are not the same.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n (c1, c2, c3) = t\n\nAs a quick-fix, you can modify the highlighted code fragment to restore the tuple\nbalance." }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyprojectInspection", + "suppressToolId": "PyTupleAssignmentBalance", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4095,7 +4107,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4107,28 +4119,28 @@ ] }, { - "id": "PyClassicStyleClassInspection", + "id": "PyClassHasNoInitInspection", "shortDescription": { - "text": "Classic style class usage" + "text": "Class has no `__init__` method" }, "fullDescription": { - "text": "Reports classic style classes usage. This inspection applies only to Python 2. Example: 'class A:\n pass' With quick-fixes provided by the IDE, this code fragment changes to: 'class A(object):\n def __init__(self):\n pass'", - "markdown": "Reports [classic style classes](https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes) usage. This inspection applies only to Python 2.\n\n**Example:**\n\n\n class A:\n pass\n\nWith quick-fixes provided by the IDE, this code fragment changes to:\n\n\n class A(object):\n def __init__(self):\n pass\n" + "text": "Reports cases in Python 2 when a class has no '__init__' method, neither its parent classes. Example: 'class Book():\n pass' The quick-fix adds the '__init__' method: 'class Book():\n def __init__(self):\n pass'", + "markdown": "Reports cases in Python 2 when a class has no `__init__` method, neither its parent\nclasses.\n\n**Example:**\n\n\n class Book():\n pass\n\nThe quick-fix adds the `__init__` method:\n\n\n class Book():\n def __init__(self):\n pass\n" }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "PyClassicStyleClass", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyClassHasNoInit", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4140,28 +4152,28 @@ ] }, { - "id": "DjangoUrlArgumentsInspection", + "id": "PyArgumentEqualDefaultInspection", "shortDescription": { - "text": "Incorrect arguments in the ' {% url %}' tag" + "text": "The function argument is equal to the default parameter value" }, "fullDescription": { - "text": "Reports missing parameters in the template file if the 'url()' function has parameters in its URL path. Example: In the 'url.py' file 'url(r'^(?P[0-9]+)/', views.detail, name='detail')' In the template file '{% url 'polls:detail' %}'", - "markdown": "Reports missing parameters in the template file if the `url()`\nfunction has parameters in its URL path.\n\n**Example:**\n\nIn the `url.py` file\n\n\n url(r'^(?P[0-9]+)/', views.detail, name='detail')\n\nIn the template file\n\n\n {% url 'polls:detail' %}\n" + "text": "Reports a problem when an argument passed to the function is equal to the default parameter value. This inspection is disabled by default to avoid performance degradation. Example: 'def my_function(a: int = 2):\n print(a)\n\n\nmy_function(2)'", + "markdown": "Reports a problem when an argument\npassed to the function is equal to the default parameter value.\n\nThis inspection is disabled by default to avoid performance degradation.\n\n**Example:**\n\n\n def my_function(a: int = 2):\n print(a)\n\n\n my_function(2)\n" }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "DjangoUrlArgumentsInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyArgumentEqualDefault", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "Django", - "index": 21, + "id": "Python", + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4173,19 +4185,19 @@ ] }, { - "id": "PyPropertyDefinitionInspection", + "id": "PyClassVarInspection", "shortDescription": { - "text": "Incorrect property definition" + "text": "Invalid usage of ClassVar variables" }, "fullDescription": { - "text": "Reports problems with the arguments of 'property()' and functions annotated with '@property'. 'class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass' A quick-fix offers to update parameters.", - "markdown": "Reports problems with the arguments of `property()` and functions\nannotated with `@property`.\n\n\n class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass\n\nA quick-fix offers to update parameters." + "text": "Reports invalid usages of ClassVar annotations. Example: 'from typing import ClassVar\n\n\nclass Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\nCat.color = \"black\" # OK\nmy_cat = Cat(5)\nmy_cat.color = \"gray\" # Error, setting class variable on instance'", + "markdown": "Reports invalid usages of [ClassVar](https://docs.python.org/3/library/typing.html#typing.ClassVar) annotations.\n\n**Example:**\n\n\n from typing import ClassVar\n\n\n class Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\n Cat.color = \"black\" # OK\n my_cat = Cat(5)\n my_cat.color = \"gray\" # Error, setting class variable on instance\n" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "PyPropertyDefinition", + "suppressToolId": "PyClassVar", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4194,7 +4206,7 @@ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4206,28 +4218,28 @@ ] }, { - "id": "PyIncorrectDocstringInspection", + "id": "DjangoRelationInspection", "shortDescription": { - "text": "Incorrect docstring" + "text": "Incorrect comparison expression in Django templates" }, "fullDescription": { - "text": "Reports mismatched parameters in a docstring. For example, 'b' is highlighted, because there is no such a parameter in the 'add' function. 'def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass' The inspection does not warn you of missing parameters if none of them is mentioned in a docstring: 'def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass'", - "markdown": "Reports mismatched parameters in a docstring. For example, `b` is highlighted, because there is no\nsuch a parameter in the `add` function.\n\n\n def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass\n\nThe inspection does not warn you of missing parameters if none of them is mentioned in a docstring:\n\n\n def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass\n" + "text": "Reports missing whitespaces before and after comparison operators in Django templates. Example: '{% if my_var==1 %}\n{% endif %}'", + "markdown": "Reports missing whitespaces before and after comparison operators in Django templates.\n\n**Example:**\n\n\n {% if my_var==1 %}\n {% endif %}\n" }, "defaultConfiguration": { - "enabled": true, - "level": "note", + "enabled": false, + "level": "warning", "parameters": { - "suppressToolId": "PyIncorrectDocstring", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "DjangoRelationInspection", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "Python", - "index": 0, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -4239,28 +4251,28 @@ ] }, { - "id": "PyListCreationInspection", + "id": "PyFromFutureImportInspection", "shortDescription": { - "text": "Non-optimal list declaration" + "text": "Improper position of from __future__ import" }, "fullDescription": { - "text": "Reports cases when a list declaration can be rewritten with a list literal. This ensures better performance of your application. Example: 'l = [1]\nl.append(2)' When the quick-fix is applied, the code changes to: 'l = [1, 2]'", - "markdown": "Reports cases when a list declaration\ncan be rewritten with a list literal.\n\nThis ensures better performance of your application.\n\n**Example:**\n\n\n l = [1]\n l.append(2)\n\nWhen the quick-fix is applied, the code changes to:\n\n\n l = [1, 2]\n" + "text": "Reports 'from __future__ import' statements that are used not at the beginning of a file. Example: 'a = 1\nfrom __future__ import print_function\nprint()' When the quick-fix is applied, the code changes to: 'from __future__ import print_function\n\na = 1\nprint()'", + "markdown": "Reports `from __future__ import`\nstatements that are used not at\nthe beginning of a file.\n\n**Example:**\n\n\n a = 1\n from __future__ import print_function\n print()\n\nWhen the quick-fix is applied, the code changes to:\n\n\n from __future__ import print_function\n\n a = 1\n print()\n" }, "defaultConfiguration": { "enabled": true, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "PyListCreation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyFromFutureImport", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "Python", - "index": 0, + "index": 1, "toolComponent": { "name": "QDPY" } @@ -4270,33 +4282,21 @@ ] } ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.editorconfig.editorconfigjetbrains", - "version": "232.9876", - "rules": [ + }, { - "id": "EditorConfigCharClassRedundancy", + "id": "PyUnresolvedReferencesInspection", "shortDescription": { - "text": "Unnecessary character class" + "text": "Unresolved references" }, "fullDescription": { - "text": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example '[a]'→'a'.", - "markdown": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example `[a]`→`a`." + "text": "Reports references in your code that cannot be resolved. In a dynamically typed language, this is possible in a limited number of cases. If a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be: 'def print_string(s):\n print(s.abc())' In this code fragment 's' is always a string and 'abc' should be highlighted as unresolved. However, 's' type is inferred as 'Any' and no warning is reported. The IDE provides quick-fix actions to add missing references on-the-fly.", + "markdown": "Reports references in your code that cannot be resolved.\n\nIn a dynamically typed language, this is possible in a limited number of cases.\n\nIf a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be:\n\n\n def print_string(s):\n print(s.abc())\n\nIn this code fragment `s` is always a string and `abc` should be highlighted as unresolved. However, `s`\ntype is inferred as `Any` and no warning is reported.\n\nThe IDE provides quick-fix actions to add missing references on-the-fly." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigCharClassRedundancy", + "suppressToolId": "PyUnresolvedReferences", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4304,7 +4304,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4317,27 +4317,27 @@ ] }, { - "id": "EditorConfigRootDeclarationUniqueness", + "id": "PyPackageRequirementsInspection", "shortDescription": { - "text": "Extra top-level declaration" + "text": "Unsatisfied package requirements" }, "fullDescription": { - "text": "Reports multiple top-level declarations. There can be only one optional “root=true” top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed.", - "markdown": "Reports multiple top-level declarations. There can be only one optional \"root=true\" top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed." + "text": "Reports packages mentioned in requirements files (for example, 'requirements.txt' or 'Pipfile') but not installed, or imported but not mentioned in requirements files. The IDE shows a quick-fix banner so that you can install the missing packages in one click.", + "markdown": "Reports packages mentioned in requirements files (for example, `requirements.txt` or `Pipfile`) but not installed,\nor imported but not mentioned in requirements files.\n\n\nThe IDE shows a quick-fix banner so that you can install the missing packages in one click." }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigRootDeclarationUniqueness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyPackageRequirements", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4350,28 +4350,28 @@ ] }, { - "id": "EditorConfigNumerousWildcards", + "id": "Restricted_Python_calls", "shortDescription": { - "text": "Too many wildcards" + "text": "Feature is not supported in the App Engine sandbox" }, "fullDescription": { - "text": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues.", - "markdown": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues." + "text": "Reports usages of Python features that are restricted by the Google App Engine sandbox and will cause a failure on the production server.", + "markdown": "Reports usages of Python features that are restricted by the Google App\nEngine sandbox and will cause a failure on the production server." }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigNumerousWildcards", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "Restricted_Python_calls", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Google App Engine (Python)", + "index": 4, "toolComponent": { "name": "QDPY" } @@ -4383,27 +4383,27 @@ ] }, { - "id": "EditorConfigPartialOverride", + "id": "PyTrailingSemicolonInspection", "shortDescription": { - "text": "Overlapping sections" + "text": "Prohibited trailing semicolon in a statement" }, "fullDescription": { - "text": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: '[{foo,bar}]' and '[{foo,bas}]' both contain “foo”.", - "markdown": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: `[{foo,bar}]` and `[{foo,bas}]` both contain \"foo\"." + "text": "Reports trailing semicolons in statements. Example: 'def my_func(a):\n c = a ** 2;\n return c' IDE provides a quick-fix that removes a trailing semicolon. When you apply it, the code changes to: 'def my_func(a):\n c = a ** 2\n return c'", + "markdown": "Reports trailing semicolons in statements.\n\n**Example:**\n\n\n def my_func(a):\n c = a ** 2;\n return c\n\nIDE provides a quick-fix that removes a trailing semicolon. When you\napply it, the code changes to:\n\n\n def my_func(a):\n c = a ** 2\n return c\n" }, "defaultConfiguration": { - "enabled": false, - "level": "note", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigPartialOverride", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "PyTrailingSemicolon", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4416,27 +4416,27 @@ ] }, { - "id": "EditorConfigEmptySection", + "id": "PyRedundantParenthesesInspection", "shortDescription": { - "text": "Empty section" + "text": "Redundant parentheses" }, "fullDescription": { - "text": "Reports sections that do not contain any EditorConfig properties.", - "markdown": "Reports sections that do not contain any EditorConfig properties." + "text": "Reports about redundant parentheses in expressions. The IDE provides the quick-fix action to remove the redundant parentheses.", + "markdown": "Reports about redundant parentheses in expressions.\n\nThe IDE provides the quick-fix action to remove the redundant parentheses." }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigEmptySection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyRedundantParentheses", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4449,19 +4449,19 @@ ] }, { - "id": "EditorConfigShadowingOption", + "id": "ExtendsTagPositionInspection", "shortDescription": { - "text": "Overriding property" + "text": "Misplaced {% extends %} tag" }, "fullDescription": { - "text": "Reports properties that override the same properties defined earlier in the file. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes the same files as '[*.java]' but also sets indent_size to value 2. Thus the first declaration 'indent_size=4'will be ignored.", - "markdown": "Reports properties that override the same properties defined earlier in the file.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes the same files as `[*.java]` but also sets indent_size to value 2. Thus the first declaration `indent_size=4`will be ignored." + "text": "Reports the '{% extends %}' tag that is not the first tag in a Django template. Example: '{% load my_custom_tags %}\n{% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}' In this example, the '{% extends %}' tag is highlighted, because it should be placed before the '{% load %}' tag.", + "markdown": "Reports the `{% extends %}` tag that is not the first tag in a\nDjango template.\n\n**Example:**\n\n\n {% load my_custom_tags %}\n {% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}\n\nIn this example, the `{% extends %}` tag is highlighted, because it should be placed before\nthe `{% load %}` tag." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigShadowingOption", + "suppressToolId": "ExtendsTagPositionInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4469,8 +4469,8 @@ "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -4482,27 +4482,27 @@ ] }, { - "id": "EditorConfigListAcceptability", + "id": "PyArgumentListInspection", "shortDescription": { - "text": "Unexpected value list" + "text": "Incorrect call arguments" }, "fullDescription": { - "text": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified.", - "markdown": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified." + "text": "Reports discrepancies between declared parameters and actual arguments, as well as incorrect arguments, for example, duplicate named arguments, and incorrect argument order. Example: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__() # unfilled parameter\nbar(5, \"#\") # unexpected argument' The correct code fragment looks at follows: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__(5)\nbar(5, p2=\"#\")'", + "markdown": "Reports discrepancies between declared parameters and actual arguments, as well as\nincorrect arguments, for example, duplicate named arguments, and incorrect argument order.\n\n**Example:**\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__() # unfilled parameter\n bar(5, \"#\") # unexpected argument\n\nThe correct code fragment looks at follows:\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__(5)\n bar(5, p2=\"#\")\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigListAcceptability", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyArgumentList", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4515,19 +4515,19 @@ ] }, { - "id": "EditorConfigKeyCorrectness", + "id": "PyInterpreterInspection", "shortDescription": { - "text": "Unknown property" + "text": "An invalid interpreter" }, "fullDescription": { - "text": "Reports properties that are not supported by the IDE. Note: some “ij” domain properties may require specific language plugins.", - "markdown": "Reports properties that are not supported by the IDE. Note: some \"ij\" domain properties may require specific language plugins." + "text": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly configured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features. The IDE provides quick access to the interpreter settings.", + "markdown": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly\nconfigured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features.\n\nThe IDE provides quick access to the interpreter settings." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigKeyCorrectness", + "suppressToolId": "PyInterpreter", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4535,7 +4535,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4548,27 +4548,27 @@ ] }, { - "id": "EditorConfigPatternEnumerationRedundancy", + "id": "PyPropertyAccessInspection", "shortDescription": { - "text": "Unnecessary braces" + "text": "Inappropriate access to properties" }, "fullDescription": { - "text": "Reports pattern lists that are either empty '{}' or contain just one pattern, for example '{foo}' in contrast to a list containing multiple patterns, for example '{foo,bar}'. In this case braces are handled as a part of the name. For example, the pattern '*.{a}' will match the file 'my.{a}' but not 'my.a'.", - "markdown": "Reports pattern lists that are either empty `{}` or contain just one pattern, for example `{foo}` in contrast to a list containing multiple patterns, for example `{foo,bar}`. In this case braces are handled as a part of the name. For example, the pattern `*.{a}` will match the file `my.{a}` but not `my.a`." + "text": "Reports cases when properties are accessed inappropriately: Read-only properties are set Write-only properties are read Non-deletable properties are deleted Example: 'class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\na = MyClass()\na.read_only = 10 # property cannot be set\ndel a.read_only # property cannot be deleted\nprint(a.write_only) # property cannot be read'", + "markdown": "Reports cases when properties are accessed inappropriately:\n\n* Read-only properties are set\n* Write-only properties are read\n* Non-deletable properties are deleted\n\n**Example:**\n\n\n class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\n a = MyClass()\n a.read_only = 10 # property cannot be set\n del a.read_only # property cannot be deleted\n print(a.write_only) # property cannot be read\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigPatternEnumerationRedundancy", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyPropertyAccess", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4581,19 +4581,19 @@ ] }, { - "id": "EditorConfigEncoding", + "id": "PyStubPackagesAdvertiser", "shortDescription": { - "text": "File encoding doesn't match EditorConfig charset" + "text": "Stub packages advertiser" }, "fullDescription": { - "text": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file.", - "markdown": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file." + "text": "Reports availability of stub packages. Stub package is a package that contains type information for the corresponding runtime package. Using stub packages ensures better coding assistance for the corresponding python package.", + "markdown": "Reports availability of stub packages.\n\n\n[Stub package](https://www.python.org/dev/peps/pep-0561/) is a package that contains type information for the corresponding\nruntime package.\n\nUsing stub packages ensures better coding assistance for the corresponding python package." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigEncoding", + "suppressToolId": "PyStubPackagesAdvertiser", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4601,7 +4601,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4614,27 +4614,27 @@ ] }, { - "id": "EditorConfigRootDeclarationCorrectness", + "id": "PyRelativeImportInspection", "shortDescription": { - "text": "Unexpected top-level declaration" + "text": "Suspicious relative imports" }, "fullDescription": { - "text": "Reports unexpected top-level declarations. Top-level declarations other than “root=true” are not allowed in the EditorConfig file.", - "markdown": "Reports unexpected top-level declarations. Top-level declarations other than \"root=true\" are not allowed in the EditorConfig file." + "text": "Reports usages of relative imports inside plain directories, for example, directories neither containing '__init__.py' nor explicitly marked as namespace packages.", + "markdown": "Reports usages of relative imports inside plain directories, for example, directories neither containing `__init__.py` nor\nexplicitly marked as namespace packages." }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigRootDeclarationCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyPackages", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4647,27 +4647,27 @@ ] }, { - "id": "EditorConfigReferenceCorrectness", + "id": "PyRedeclarationInspection", "shortDescription": { - "text": "Invalid reference" + "text": "Redeclared names without usages" }, "fullDescription": { - "text": "Reports identifiers that are either unknown or have a wrong type.", - "markdown": "Reports identifiers that are either unknown or have a wrong type." + "text": "Reports unconditional redeclarations of names without being used in between. Example: 'def x(): pass\n\n\nx = 2' It applies to function and class declarations, and top-level assignments. When the warning is shown, you can try a recommended action, for example, you might be prompted to rename the variable.", + "markdown": "Reports unconditional redeclarations of names without being used in between.\n\n**Example:**\n\n\n def x(): pass\n\n\n x = 2\n\nIt applies to function and class declarations, and top-level assignments.\n\nWhen the warning is shown, you can try a recommended action, for example, you might be prompted to\nrename the variable." }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigReferenceCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyRedeclaration", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4680,28 +4680,28 @@ ] }, { - "id": "EditorConfigPairAcceptability", + "id": "PyramidSetupInspection", "shortDescription": { - "text": "Unexpected key-value pair" + "text": "Project is not installed for development" }, "fullDescription": { - "text": "Reports key-value pairs that are not allowed in the current context.", - "markdown": "Reports key-value pairs that are not allowed in the current context." + "text": "Reports cases when no 'python setup.py develop' command was executed for the Pyramid project. You need to execute this command to install the newly created project for development.", + "markdown": "Reports cases when no `python setup.py develop` command was executed for the Pyramid project.\n\nYou need to execute this command to install the newly created project for development." }, "defaultConfiguration": { "enabled": false, - "level": "error", + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigPairAcceptability", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyramidSetup", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Pyramid", + "index": 62, "toolComponent": { "name": "QDPY" } @@ -4713,27 +4713,27 @@ ] }, { - "id": "EditorConfigPatternRedundancy", + "id": "PyProtectedMemberInspection", "shortDescription": { - "text": "Duplicate or redundant pattern" + "text": "Accessing a protected member of a class or a module" }, "fullDescription": { - "text": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in '[{*.java,*}]' the first '*.java' pattern defines a narrower scope compared to '*'. That is why it is redundant and can be removed.", - "markdown": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in `[{*.java,*}]` the first `*.java` pattern defines a narrower scope compared to `*`. That is why it is redundant and can be removed." + "text": "Reports cases when a protected member is accessed outside the class, a descendant of the class where it is defined, or a module. Example: 'class Foo:\n def _protected_method(self):\n pass\n\n\nclass Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\nfoo = Foo()\nfoo._protected_method() # Access to a protected method'", + "markdown": "Reports cases when a protected member is accessed outside the class,\na descendant of the class where it is defined, or a module.\n\n**Example:**\n\n\n class Foo:\n def _protected_method(self):\n pass\n\n\n class Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\n foo = Foo()\n foo._protected_method() # Access to a protected method\n" }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigPatternRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyProtectedMember", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4746,19 +4746,19 @@ ] }, { - "id": "EditorConfigNoMatchingFiles", + "id": "PyStubPackagesCompatibilityInspection", "shortDescription": { - "text": "No matching files" + "text": "Incompatible stub packages" }, "fullDescription": { - "text": "Reports sections with wildcard patterns that do not match any files under the directory in which the '.editorconfig' file is located.", - "markdown": "Reports sections with wildcard patterns that do not match any files under the directory in which the `.editorconfig` file is located." + "text": "Reports stub packages that do not support the version of the corresponding runtime package. A stub package contains type information for some runtime package.", + "markdown": "Reports stub packages that do not support the version of the corresponding runtime package.\n\nA [stub package](https://www.python.org/dev/peps/pep-0561/) contains type information for some runtime package." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigNoMatchingFiles", + "suppressToolId": "PyStubPackagesCompatibility", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4766,7 +4766,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4779,19 +4779,19 @@ ] }, { - "id": "EditorConfigDeprecatedDescriptor", + "id": "PyUnboundLocalVariableInspection", "shortDescription": { - "text": "Deprecated property" + "text": "Unbound local variables" }, "fullDescription": { - "text": "Reports EditorConfig properties that are no longer supported.", - "markdown": "Reports EditorConfig properties that are no longer supported." + "text": "Reports local variables referenced before assignment. Example: 'x = 0\nif x > 10:\n b = 3\nprint(b)' The IDE reports a problem for 'print(b)'. A possible fix is: 'x = 0\nif x > 10:\n b = 3\n print(b)'", + "markdown": "Reports local variables referenced before assignment.\n\n**Example:**\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n\nThe IDE reports a problem for `print(b)`. A possible fix is:\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigDeprecatedDescriptor", + "suppressToolId": "PyUnboundLocalVariable", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4799,7 +4799,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4812,19 +4812,19 @@ ] }, { - "id": "EditorConfigWildcardRedundancy", + "id": "PyNamedTupleInspection", "shortDescription": { - "text": "Redundant wildcard" + "text": "Invalid definition of 'typing.NamedTuple'" }, "fullDescription": { - "text": "Reports wildcards that become redundant when the “**” wildcard is used in the same section. The “**” wildcard defines a broader set of files than any other wildcard. That is why, any other wildcard used in the same section has no affect and can be removed.", - "markdown": "Reports wildcards that become redundant when the \"\\*\\*\" wildcard is used in the same section.\n\n\nThe \"\\*\\*\" wildcard defines a broader set of files than any other wildcard.\nThat is why, any other wildcard used in the same section has no affect and can be removed." + "text": "Reports invalid definition of a typing.NamedTuple. Example: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str' As a fix, place the field with the default value after the fields without default values: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"'", + "markdown": "Reports invalid definition of a\n[typing.NamedTuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).\n\n**Example:**\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str\n\nAs a fix, place the field with the default value after the fields without default values:\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"\n" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigWildcardRedundancy", + "suppressToolId": "PyNamedTuple", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4832,7 +4832,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4845,27 +4845,27 @@ ] }, { - "id": "EditorConfigHeaderUniqueness", + "id": "PyNestedDecoratorsInspection", "shortDescription": { - "text": "EditorConfig section is not unique" + "text": "Problematic nesting of decorators" }, "fullDescription": { - "text": "Reports sections that define the same file pattern as other sections.", - "markdown": "Reports sections that define the same file pattern as other sections." + "text": "Reports problems with nesting decorators. The inspection highlights the cases when 'classmethod' or 'staticmethod' is applied before another decorator. Example: 'def innocent(f):\n return f\n\n\nclass A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass' As a quick-fix, the IDE offers to remove the decorator.", + "markdown": "Reports problems with nesting decorators. The inspection highlights the cases when `classmethod` or `staticmethod`\nis applied before another decorator.\n\n**Example:**\n\n\n def innocent(f):\n return f\n\n\n class A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass\n\nAs a quick-fix, the IDE offers to remove the decorator." }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigHeaderUniqueness", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyNestedDecorators", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4878,19 +4878,19 @@ ] }, { - "id": "EditorConfigShadowedOption", + "id": "DuplicatedBlockNamesInspection", "shortDescription": { - "text": "Overridden property" + "text": "Duplicated block names" }, "fullDescription": { - "text": "Reports properties that are already defined in other sections. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes all '*.java' files too but it also redefines indent_size. As a result the value 2 will be used for files matching '*.java'.", - "markdown": "Reports properties that are already defined in other sections.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes all `*.java` files too but it also redefines indent_size. As a result the value 2 will be used for files matching `*.java`." + "text": "Reports duplicated block names in Django templates. Example: '\n\n\n \n {% block title %}My amazing site{% endblock %}\n\n\n\n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n\n'", + "markdown": "Reports duplicated block names in Django templates.\n\n**Example:**\n\n\n \n \n \n \n {% block title %}My amazing site{% endblock %}\n \n\n \n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n \n \n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigShadowedOption", + "suppressToolId": "DuplicatedBlockNamesInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -4898,8 +4898,8 @@ "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -4911,27 +4911,27 @@ ] }, { - "id": "EditorConfigEmptyHeader", + "id": "PyOverloadsInspection", "shortDescription": { - "text": "Empty header" + "text": "Overloads in regular Python files" }, "fullDescription": { - "text": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by 'gitignore'.", - "markdown": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by `gitignore`." + "text": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are not compatible with the implementation. Example: 'from typing import overload\n\n\n@overload\ndef foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n@overload\ndef foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\ndef foo(p1, p2, p3):\n print(p1, p2, p3)'", + "markdown": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are\nnot compatible with the implementation.\n\n**Example:**\n\n\n from typing import overload\n\n\n @overload\n def foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n @overload\n def foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\n def foo(p1, p2, p3):\n print(p1, p2, p3)\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigEmptyHeader", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyOverloads", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -4944,28 +4944,28 @@ ] }, { - "id": "EditorConfigValueCorrectness", + "id": "AppEngineThreadsafeInspection", "shortDescription": { - "text": "Invalid property value" + "text": "Threadsafe is not available or set inappropriately" }, "fullDescription": { - "text": "Reports property values that do not meet value restrictions. For example, some properties may be only “true” or “false”, others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them.", - "markdown": "Reports property values that do not meet value restrictions. For example, some properties may be only \"true\" or \"false\", others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them." + "text": "Reports cases when threadsafe is not present or it is not set to either 'yes' or 'no'.", + "markdown": "Reports cases when threadsafe is not present or it is not set to either `yes` or `no`." }, "defaultConfiguration": { "enabled": false, - "level": "error", + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigValueCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "AppEngineThreadsafe", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Google App Engine (Python)", + "index": 4, "toolComponent": { "name": "QDPY" } @@ -4977,27 +4977,27 @@ ] }, { - "id": "EditorConfigVerifyByCore", + "id": "PyExceptClausesOrderInspection", "shortDescription": { - "text": "Invalid .editorconfig file" + "text": "Wrong order of 'except' clauses" }, "fullDescription": { - "text": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied.", - "markdown": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied." + "text": "Reports cases when 'except' clauses are not in the proper order, from the more specific to the more generic, or one exception class is caught twice. If you do not fix the order, some exceptions may not be caught by the most specific handler. Example: 'try:\n call()\nexcept ValueError:\n pass\nexcept UnicodeError:\n pass' The IDE recommends moving the clause up. When the quick-fix is applied, the code changes to: 'try:\n call()\nexcept UnicodeError:\n pass\nexcept ValueError:\n pass'", + "markdown": "Reports cases when `except` clauses are not in the proper order,\nfrom the more specific to the more generic, or one exception class is caught twice.\n\n\nIf you do not fix the order, some exceptions may not be caught by the most specific handler.\n\n**Example:**\n\n\n try:\n call()\n except ValueError:\n pass\n except UnicodeError:\n pass\n\nThe IDE recommends moving the clause up. When the quick-fix is applied, the code changes to:\n\n\n try:\n call()\n except UnicodeError:\n pass\n except ValueError:\n pass\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigVerifyByCore", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyExceptClausesOrder", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5010,27 +5010,27 @@ ] }, { - "id": "EditorConfigValueUniqueness", + "id": "PyDataclassInspection", "shortDescription": { - "text": "Non-unique list value" + "text": "Invalid definition and usage of Data Classes" }, "fullDescription": { - "text": "Reports duplicates in lists of values.", - "markdown": "Reports duplicates in lists of values." + "text": "Reports invalid definitions and usages of classes created with 'dataclasses' or 'attr' modules. Example: 'import dataclasses\n\n\n@dataclasses.dataclass\nclass FullName:\n first: str\n middle: str = \"\"\n last: str'", + "markdown": "Reports invalid definitions and usages of classes created with\n`dataclasses` or `attr` modules.\n\n**Example:**\n\n\n import dataclasses\n\n\n @dataclasses.dataclass\n class FullName:\n first: str\n middle: str = \"\"\n last: str\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigValueUniqueness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyDataclass", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5043,27 +5043,27 @@ ] }, { - "id": "EditorConfigMissingRequiredDeclaration", + "id": "PyClassicStyleClassInspection", "shortDescription": { - "text": "Required declarations are missing" + "text": "Classic style class usage" }, "fullDescription": { - "text": "Reports properties that miss the required declarations. Refer to the documentation for more information.", - "markdown": "Reports properties that miss the required declarations. Refer to the documentation for more information." + "text": "Reports classic style classes usage. This inspection applies only to Python 2. Example: 'class A:\n pass' With quick-fixes provided by the IDE, this code fragment changes to: 'class A(object):\n def __init__(self):\n pass'", + "markdown": "Reports [classic style classes](https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes) usage. This inspection applies only to Python 2.\n\n**Example:**\n\n\n class A:\n pass\n\nWith quick-fixes provided by the IDE, this code fragment changes to:\n\n\n class A(object):\n def __init__(self):\n pass\n" }, "defaultConfiguration": { "enabled": false, - "level": "error", + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigMissingRequiredDeclaration", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyClassicStyleClass", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5076,19 +5076,19 @@ ] }, { - "id": "EditorConfigCharClassLetterRedundancy", + "id": "PyprojectInspection", "shortDescription": { - "text": "Duplicate character class letter" + "text": "Depencencies in pyproject.toml" }, "fullDescription": { - "text": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example '[aa]'.", - "markdown": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example `[aa]`." + "text": "Reports unsatisfied dependencies, declared [project.dependencies] table in pyproject.toml. Shows a quick-fix to install missing packages.", + "markdown": "Reports unsatisfied dependencies, declared \\[project.dependencies\\] table in pyproject.toml.\n\n\nShows a quick-fix to install missing packages." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigCharClassLetterRedundancy", + "suppressToolId": "PyprojectInspection", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -5096,7 +5096,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5109,28 +5109,28 @@ ] }, { - "id": "EditorConfigSpaceInHeader", + "id": "DjangoUrlArgumentsInspection", "shortDescription": { - "text": "Space in file pattern" + "text": "Incorrect arguments in the ' {% url %}' tag" }, "fullDescription": { - "text": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed.", - "markdown": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed." + "text": "Reports missing parameters in the template file if the 'url()' function has parameters in its URL path. Example: In the 'url.py' file 'url(r'^(?P[0-9]+)/', views.detail, name='detail')' In the template file '{% url 'polls:detail' %}'", + "markdown": "Reports missing parameters in the template file if the `url()`\nfunction has parameters in its URL path.\n\n**Example:**\n\nIn the `url.py` file\n\n\n url(r'^(?P[0-9]+)/', views.detail, name='detail')\n\nIn the template file\n\n\n {% url 'polls:detail' %}\n" }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "EditorConfigSpaceInHeader", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "DjangoUrlArgumentsInspection", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "EditorConfig", - "index": 1, + "id": "Django", + "index": 21, "toolComponent": { "name": "QDPY" } @@ -5142,19 +5142,19 @@ ] }, { - "id": "EditorConfigOptionRedundancy", + "id": "PyPropertyDefinitionInspection", "shortDescription": { - "text": "Redundant property" + "text": "Incorrect property definition" }, "fullDescription": { - "text": "Reports properties that are redundant when another applicable section already contains the same property and value. For example: '[*]\nindent_size=4\n[*.java]\nindent_size=4' are both applicable to '*.java' files and define the same 'indent_size' value.", - "markdown": "Reports properties that are redundant when another applicable section already contains the same property and value.\n\n\nFor example:\n\n\n [*]\n indent_size=4\n [*.java]\n indent_size=4\n\nare both applicable to `*.java` files and define the same `indent_size` value." + "text": "Reports problems with the arguments of 'property()' and functions annotated with '@property'. 'class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass' A quick-fix offers to update parameters.", + "markdown": "Reports problems with the arguments of `property()` and functions\nannotated with `@property`.\n\n\n class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass\n\nA quick-fix offers to update parameters." }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "EditorConfigOptionRedundancy", + "suppressToolId": "PyPropertyDefinition", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -5162,7 +5162,7 @@ "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5175,27 +5175,27 @@ ] }, { - "id": "EditorConfigUnusedDeclaration", + "id": "PyIncorrectDocstringInspection", "shortDescription": { - "text": "Unused declaration" + "text": "Incorrect docstring" }, "fullDescription": { - "text": "Reports unused declarations. Such declarations can be removed.", - "markdown": "Reports unused declarations. Such declarations can be removed." + "text": "Reports mismatched parameters in a docstring. For example, 'b' is highlighted, because there is no such a parameter in the 'add' function. 'def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass' The inspection does not warn you of missing parameters if none of them is mentioned in a docstring: 'def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass'", + "markdown": "Reports mismatched parameters in a docstring. For example, `b` is highlighted, because there is no\nsuch a parameter in the `add` function.\n\n\n def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass\n\nThe inspection does not warn you of missing parameters if none of them is mentioned in a docstring:\n\n\n def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass\n" }, "defaultConfiguration": { - "enabled": false, - "level": "warning", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigUnusedDeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "PyIncorrectDocstring", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5208,27 +5208,27 @@ ] }, { - "id": "EditorConfigUnexpectedComma", + "id": "PyListCreationInspection", "shortDescription": { - "text": "Unexpected comma" + "text": "Non-optimal list declaration" }, "fullDescription": { - "text": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists.", - "markdown": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists." + "text": "Reports cases when a list declaration can be rewritten with a list literal. This ensures better performance of your application. Example: 'l = [1]\nl.append(2)' When the quick-fix is applied, the code changes to: 'l = [1, 2]'", + "markdown": "Reports cases when a list declaration\ncan be rewritten with a list literal.\n\nThis ensures better performance of your application.\n\n**Example:**\n\n\n l = [1]\n l.append(2)\n\nWhen the quick-fix is applied, the code changes to:\n\n\n l = [1, 2]\n" }, "defaultConfiguration": { - "enabled": false, - "level": "error", + "enabled": true, + "level": "note", "parameters": { - "suppressToolId": "EditorConfigUnexpectedComma", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "PyListCreation", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "EditorConfig", + "id": "Python", "index": 1, "toolComponent": { "name": "QDPY" @@ -5319,19 +5319,19 @@ ] }, { - "id": "NonBlockStatementBodyJS", + "id": "JSValidateJSDoc", "shortDescription": { - "text": "Statement body without braces" + "text": "Syntax errors and unresolved references in JSDoc" }, "fullDescription": { - "text": "Reports a 'if', 'while', 'for', or 'with' statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance.", - "markdown": "Reports a `if`, `while`, `for`, or `with` statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance." + "text": "Reports a syntax discrepancy in a documentation comment.", + "markdown": "Reports a syntax discrepancy in a documentation comment." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "NonBlockStatementBodyJS", + "suppressToolId": "JSValidateJSDoc", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -5339,7 +5339,7 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Code style issues", + "id": "JavaScript and TypeScript/General", "index": 11, "toolComponent": { "name": "QDPY" @@ -5352,19 +5352,19 @@ ] }, { - "id": "JSValidateJSDoc", + "id": "IfStatementWithTooManyBranchesJS", "shortDescription": { - "text": "Syntax errors and unresolved references in JSDoc" + "text": "'if' statement with too many branches" }, "fullDescription": { - "text": "Reports a syntax discrepancy in a documentation comment.", - "markdown": "Reports a syntax discrepancy in a documentation comment." + "text": "Reports an 'if' statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction. Use the field below to specify the maximum number of branches expected.", + "markdown": "Reports an `if` statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction.\n\n\nUse the field below to specify the maximum number of branches expected." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "JSValidateJSDoc", + "suppressToolId": "IfStatementWithTooManyBranchesJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -5372,8 +5372,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/General", - "index": 12, + "id": "JavaScript and TypeScript/Control flow issues", + "index": 3, "toolComponent": { "name": "QDPY" } @@ -5385,19 +5385,19 @@ ] }, { - "id": "IfStatementWithTooManyBranchesJS", + "id": "NonBlockStatementBodyJS", "shortDescription": { - "text": "'if' statement with too many branches" + "text": "Statement body without braces" }, "fullDescription": { - "text": "Reports an 'if' statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction. Use the field below to specify the maximum number of branches expected.", - "markdown": "Reports an `if` statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction.\n\n\nUse the field below to specify the maximum number of branches expected." + "text": "Reports a 'if', 'while', 'for', or 'with' statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance.", + "markdown": "Reports a `if`, `while`, `for`, or `with` statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "IfStatementWithTooManyBranchesJS", + "suppressToolId": "NonBlockStatementBodyJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -5405,8 +5405,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, + "id": "JavaScript and TypeScript/Code style issues", + "index": 12, "toolComponent": { "name": "QDPY" } @@ -5703,7 +5703,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6066,7 +6066,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6099,7 +6099,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -6231,7 +6231,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6243,28 +6243,28 @@ ] }, { - "id": "UnnecessaryLabelOnBreakStatementJS", + "id": "ES6ShorthandObjectProperty", "shortDescription": { - "text": "Unnecessary label on 'break' statement" + "text": "Property can be replaced with shorthand" }, "fullDescription": { - "text": "Reports a labeled 'break' statement whose labels may be removed without changing the flow of control.", - "markdown": "Reports a labeled `break` statement whose labels may be removed without changing the flow of control." + "text": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it. Example: 'var obj = {foo:foo}' After applying the quick-fix the code looks as follows: 'var obj = {foo}'", + "markdown": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it.\n\nExample:\n\n\n var obj = {foo:foo}\n\nAfter applying the quick-fix the code looks as follows:\n\n\n var obj = {foo}\n" }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "UnnecessaryLabelOnBreakStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "ES6ShorthandObjectProperty", + "ideaSeverity": "INFORMATION", + "qodanaSeverity": "Info" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, + "id": "JavaScript and TypeScript/General", + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6276,28 +6276,28 @@ ] }, { - "id": "ES6ShorthandObjectProperty", + "id": "UnnecessaryLabelOnBreakStatementJS", "shortDescription": { - "text": "Property can be replaced with shorthand" + "text": "Unnecessary label on 'break' statement" }, "fullDescription": { - "text": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it. Example: 'var obj = {foo:foo}' After applying the quick-fix the code looks as follows: 'var obj = {foo}'", - "markdown": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it.\n\nExample:\n\n\n var obj = {foo:foo}\n\nAfter applying the quick-fix the code looks as follows:\n\n\n var obj = {foo}\n" + "text": "Reports a labeled 'break' statement whose labels may be removed without changing the flow of control.", + "markdown": "Reports a labeled `break` statement whose labels may be removed without changing the flow of control." }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "ES6ShorthandObjectProperty", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" + "suppressToolId": "UnnecessaryLabelOnBreakStatementJS", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/General", - "index": 12, + "id": "JavaScript and TypeScript/Control flow issues", + "index": 3, "toolComponent": { "name": "QDPY" } @@ -6495,7 +6495,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6561,7 +6561,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6660,7 +6660,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6738,19 +6738,19 @@ ] }, { - "id": "PointlessBooleanExpressionJS", + "id": "JSReferencingMutableVariableFromClosure", "shortDescription": { - "text": "Pointless statement or boolean expression" + "text": "Referencing mutable variable from closure" }, "fullDescription": { - "text": "Reports a pointless or pointlessly complicated boolean expression or statement. Example: 'let a = !(false && x);\n let b = false || x;' After the quick fix is applied the result looks like: 'let a = true;\n let b = x;'", - "markdown": "Reports a pointless or pointlessly complicated boolean expression or statement.\n\nExample:\n\n\n let a = !(false && x);\n let b = false || x;\n\nAfter the quick fix is applied the result looks like:\n\n\n let a = true;\n let b = x;\n" + "text": "Reports access to outer mutable variables from functions. Example: 'for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }'", + "markdown": "Reports access to outer mutable variables from functions.\n\nExample:\n\n\n for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PointlessBooleanExpressionJS", + "suppressToolId": "JSReferencingMutableVariableFromClosure", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -6758,8 +6758,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, + "id": "JavaScript and TypeScript/General", + "index": 11, "toolComponent": { "name": "QDPY" } @@ -6771,19 +6771,19 @@ ] }, { - "id": "JSReferencingMutableVariableFromClosure", + "id": "PointlessBooleanExpressionJS", "shortDescription": { - "text": "Referencing mutable variable from closure" + "text": "Pointless statement or boolean expression" }, "fullDescription": { - "text": "Reports access to outer mutable variables from functions. Example: 'for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }'", - "markdown": "Reports access to outer mutable variables from functions.\n\nExample:\n\n\n for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }\n" + "text": "Reports a pointless or pointlessly complicated boolean expression or statement. Example: 'let a = !(false && x);\n let b = false || x;' After the quick fix is applied the result looks like: 'let a = true;\n let b = x;'", + "markdown": "Reports a pointless or pointlessly complicated boolean expression or statement.\n\nExample:\n\n\n let a = !(false && x);\n let b = false || x;\n\nAfter the quick fix is applied the result looks like:\n\n\n let a = true;\n let b = x;\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "JSReferencingMutableVariableFromClosure", + "suppressToolId": "PointlessBooleanExpressionJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -6791,8 +6791,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/General", - "index": 12, + "id": "JavaScript and TypeScript/Control flow issues", + "index": 3, "toolComponent": { "name": "QDPY" } @@ -6957,7 +6957,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -7056,7 +7056,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -7167,28 +7167,28 @@ ] }, { - "id": "UnusedCatchParameterJS", + "id": "NpmUsedModulesInstalled", "shortDescription": { - "text": "Unused 'catch' parameter" + "text": "Missing module dependency" }, "fullDescription": { - "text": "Reports a 'catch' parameter that is not used in the corresponding block. The 'catch' parameters named 'ignore' or 'ignored' are ignored. Use the checkbox below to disable this inspection for 'catch' blocks with comments.", - "markdown": "Reports a `catch` parameter that is not used in the corresponding block. The `catch` parameters named `ignore` or `ignored` are ignored.\n\n\nUse the checkbox below to disable this inspection for `catch`\nblocks with comments." + "text": "Reports a module from a 'require()' call or an 'import' statement that is not installed or is not listed in package.json dependencies. Suggests installing the module and/or including it into package.json. For 'require()' calls, works only in the files from the scope of Node.js Core JavaScript library.", + "markdown": "Reports a module from a `require()` call or an `import` statement that is not installed or is not listed in package.json dependencies.\n\nSuggests installing the module and/or including it into package.json.\n\nFor `require()` calls, works only in the files from the scope of *Node.js Core* JavaScript library." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "UnusedCatchParameterJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "NpmUsedModulesInstalled", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, + "id": "JavaScript and TypeScript/Imports and dependencies", + "index": 47, "toolComponent": { "name": "QDPY" } @@ -7200,28 +7200,28 @@ ] }, { - "id": "NpmUsedModulesInstalled", + "id": "UnusedCatchParameterJS", "shortDescription": { - "text": "Missing module dependency" + "text": "Unused 'catch' parameter" }, "fullDescription": { - "text": "Reports a module from a 'require()' call or an 'import' statement that is not installed or is not listed in package.json dependencies. Suggests installing the module and/or including it into package.json. For 'require()' calls, works only in the files from the scope of Node.js Core JavaScript library.", - "markdown": "Reports a module from a `require()` call or an `import` statement that is not installed or is not listed in package.json dependencies.\n\nSuggests installing the module and/or including it into package.json.\n\nFor `require()` calls, works only in the files from the scope of *Node.js Core* JavaScript library." + "text": "Reports a 'catch' parameter that is not used in the corresponding block. The 'catch' parameters named 'ignore' or 'ignored' are ignored. Use the checkbox below to disable this inspection for 'catch' blocks with comments.", + "markdown": "Reports a `catch` parameter that is not used in the corresponding block. The `catch` parameters named `ignore` or `ignored` are ignored.\n\n\nUse the checkbox below to disable this inspection for `catch`\nblocks with comments." }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "warning", "parameters": { - "suppressToolId": "NpmUsedModulesInstalled", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "UnusedCatchParameterJS", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, + "id": "JavaScript and TypeScript/Try statement issues", + "index": 33, "toolComponent": { "name": "QDPY" } @@ -7419,7 +7419,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -7452,7 +7452,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8112,7 +8112,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8343,7 +8343,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8508,7 +8508,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8541,7 +8541,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8673,7 +8673,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -8739,7 +8739,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -8772,7 +8772,7 @@ { "target": { "id": "CSS/Code quality tools", - "index": 58, + "index": 57, "toolComponent": { "name": "QDPY" } @@ -8838,7 +8838,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -9201,7 +9201,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -9444,28 +9444,28 @@ ] }, { - "id": "JSUnfilteredForInLoop", + "id": "JSIncompatibleTypesComparison", "shortDescription": { - "text": "Unfiltered for..in loop" + "text": "Comparison of expressions having incompatible types" }, "fullDescription": { - "text": "Reports unfiltered 'for-in' loops. The use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when 'Object''s prototype may be incorrectly modified. For example, the following code will print 42 and myMethod: 'Object.prototype.myMethod = function myMethod() {};\nlet a = { foo: 42 };\nfor (let i in a) {\n console.log(a[i]);\n}' Suggests replacing the whole loop with a 'Object.keys()' method or adding a 'hasOwnProperty()' check. After applying the quick-fix the code looks as follows: 'for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n}'", - "markdown": "Reports unfiltered `for-in` loops. \n\nThe use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when `Object`'s prototype may be incorrectly modified. For example, the following code will print **42** and **myMethod** : \n\n\n Object.prototype.myMethod = function myMethod() {};\n let a = { foo: 42 };\n for (let i in a) {\n console.log(a[i]);\n }\n\nSuggests replacing the whole loop with a `Object.keys()` method or adding a `hasOwnProperty()` check. After applying the quick-fix the code looks as follows:\n\n\n for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n }\n" + "text": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values.", + "markdown": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values." }, "defaultConfiguration": { "enabled": false, - "level": "warning", + "level": "note", "parameters": { - "suppressToolId": "JSUnfilteredForInLoop", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" + "suppressToolId": "JSIncompatibleTypesComparison", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/General", - "index": 12, + "id": "JavaScript and TypeScript/Probable bugs", + "index": 17, "toolComponent": { "name": "QDPY" } @@ -9477,28 +9477,28 @@ ] }, { - "id": "JSIncompatibleTypesComparison", + "id": "JSAnnotator", "shortDescription": { - "text": "Comparison of expressions having incompatible types" + "text": "ECMAScript specification is not followed" }, "fullDescription": { - "text": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values.", - "markdown": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values." + "text": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. Generally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors.", + "markdown": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. \nGenerally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors." }, "defaultConfiguration": { "enabled": false, - "level": "note", + "level": "error", "parameters": { - "suppressToolId": "JSIncompatibleTypesComparison", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" + "suppressToolId": "JSAnnotator", + "ideaSeverity": "ERROR", + "qodanaSeverity": "Critical" } }, "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, + "id": "JavaScript and TypeScript/General", + "index": 11, "toolComponent": { "name": "QDPY" } @@ -9510,28 +9510,28 @@ ] }, { - "id": "JSAnnotator", + "id": "JSUnfilteredForInLoop", "shortDescription": { - "text": "ECMAScript specification is not followed" + "text": "Unfiltered for..in loop" }, "fullDescription": { - "text": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. Generally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors.", - "markdown": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. \nGenerally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors." + "text": "Reports unfiltered 'for-in' loops. The use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when 'Object''s prototype may be incorrectly modified. For example, the following code will print 42 and myMethod: 'Object.prototype.myMethod = function myMethod() {};\nlet a = { foo: 42 };\nfor (let i in a) {\n console.log(a[i]);\n}' Suggests replacing the whole loop with a 'Object.keys()' method or adding a 'hasOwnProperty()' check. After applying the quick-fix the code looks as follows: 'for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n}'", + "markdown": "Reports unfiltered `for-in` loops. \n\nThe use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when `Object`'s prototype may be incorrectly modified. For example, the following code will print **42** and **myMethod** : \n\n\n Object.prototype.myMethod = function myMethod() {};\n let a = { foo: 42 };\n for (let i in a) {\n console.log(a[i]);\n }\n\nSuggests replacing the whole loop with a `Object.keys()` method or adding a `hasOwnProperty()` check. After applying the quick-fix the code looks as follows:\n\n\n for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n }\n" }, "defaultConfiguration": { "enabled": false, - "level": "error", + "level": "warning", "parameters": { - "suppressToolId": "JSAnnotator", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" + "suppressToolId": "JSUnfilteredForInLoop", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" } }, "relationships": [ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -9564,7 +9564,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -9828,7 +9828,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -10059,7 +10059,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -10158,7 +10158,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -10290,7 +10290,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -10488,7 +10488,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -10587,7 +10587,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -10719,7 +10719,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -10785,7 +10785,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -10917,7 +10917,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -10950,7 +10950,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -11049,7 +11049,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -11148,7 +11148,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -11280,7 +11280,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -11313,7 +11313,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -11412,7 +11412,7 @@ { "target": { "id": "JavaScript and TypeScript/Code style issues", - "index": 11, + "index": 12, "toolComponent": { "name": "QDPY" } @@ -11424,19 +11424,19 @@ ] }, { - "id": "PlatformDetectionJS", + "id": "IfStatementWithIdenticalBranchesJS", "shortDescription": { - "text": "Inaccurate platform detection" + "text": "'if' statement with identical branches" }, "fullDescription": { - "text": "Reports a common JavaScript pattern for detecting the browser or operating system in which the script is run. In addition to pointing out non-portable constructs, these platform detection patterns are often incomplete and easily fooled. For most cases, detection of individual environment features is preferable to attempting to detect the entire platform. Patterns detected include: 'document.all' 'document.layers' 'navigator.userAgent' 'navigator.oscpu' 'navigator.appName' 'navigator.appCodeName' 'navigator.platform'", - "markdown": "Reports a common JavaScript pattern for detecting the browser or operating system in which the script is run. In addition to pointing out non-portable constructs, these platform detection patterns are often incomplete and easily fooled. For most cases, detection of individual environment features is preferable to attempting to detect the entire platform.\n\nPatterns detected include:\n\n* `document.all`\n* `document.layers`\n* `navigator.userAgent`\n* `navigator.oscpu`\n* `navigator.appName`\n* `navigator.appCodeName`\n* `navigator.platform`" + "text": "Reports an 'if' statement with identical 'then' and 'else' branches. Such statements are almost certainly an error.", + "markdown": "Reports an `if` statement with identical `then` and `else` branches. Such statements are almost certainly an error." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "PlatformDetectionJS", + "suppressToolId": "IfStatementWithIdenticalBranchesJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -11444,8 +11444,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/DOM issues", - "index": 52, + "id": "JavaScript and TypeScript/Control flow issues", + "index": 3, "toolComponent": { "name": "QDPY" } @@ -11457,19 +11457,19 @@ ] }, { - "id": "IfStatementWithIdenticalBranchesJS", + "id": "PlatformDetectionJS", "shortDescription": { - "text": "'if' statement with identical branches" + "text": "Inaccurate platform detection" }, "fullDescription": { - "text": "Reports an 'if' statement with identical 'then' and 'else' branches. Such statements are almost certainly an error.", - "markdown": "Reports an `if` statement with identical `then` and `else` branches. Such statements are almost certainly an error." + "text": "Reports a common JavaScript pattern for detecting the browser or operating system in which the script is run. In addition to pointing out non-portable constructs, these platform detection patterns are often incomplete and easily fooled. For most cases, detection of individual environment features is preferable to attempting to detect the entire platform. Patterns detected include: 'document.all' 'document.layers' 'navigator.userAgent' 'navigator.oscpu' 'navigator.appName' 'navigator.appCodeName' 'navigator.platform'", + "markdown": "Reports a common JavaScript pattern for detecting the browser or operating system in which the script is run. In addition to pointing out non-portable constructs, these platform detection patterns are often incomplete and easily fooled. For most cases, detection of individual environment features is preferable to attempting to detect the entire platform.\n\nPatterns detected include:\n\n* `document.all`\n* `document.layers`\n* `navigator.userAgent`\n* `navigator.oscpu`\n* `navigator.appName`\n* `navigator.appCodeName`\n* `navigator.platform`" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "IfStatementWithIdenticalBranchesJS", + "suppressToolId": "PlatformDetectionJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -11477,8 +11477,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, + "id": "JavaScript and TypeScript/DOM issues", + "index": 52, "toolComponent": { "name": "QDPY" } @@ -11720,39 +11720,6 @@ } ] }, - { - "id": "TypeScriptDuplicateUnionOrIntersectionType", - "shortDescription": { - "text": "Duplicate union or intersection type component" - }, - "fullDescription": { - "text": "Reports a duplicate type inside a union or intersection.", - "markdown": "Reports a duplicate type inside a union or intersection." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TypeScriptDuplicateUnionOrIntersectionType", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, { "id": "TrivialConditionalJS", "shortDescription": { @@ -11787,19 +11754,19 @@ ] }, { - "id": "ES6UnusedImports", + "id": "TypeScriptDuplicateUnionOrIntersectionType", "shortDescription": { - "text": "Unused import" + "text": "Duplicate union or intersection type component" }, "fullDescription": { - "text": "Reports a redundant 'import' statement. This is usually the case if the imported symbols are not used in the source file. To avoid side-effects, consider using bare import 'import 'packageName'' instead of the regular one.", - "markdown": "Reports a redundant `import` statement. This is usually the case if the imported symbols are not used in the source file. To avoid side-effects, consider using bare import `import 'packageName'` instead of the regular one." + "text": "Reports a duplicate type inside a union or intersection.", + "markdown": "Reports a duplicate type inside a union or intersection." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "ES6UnusedImports", + "suppressToolId": "TypeScriptDuplicateUnionOrIntersectionType", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -11807,8 +11774,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, + "id": "JavaScript and TypeScript/TypeScript", + "index": 27, "toolComponent": { "name": "QDPY" } @@ -11885,6 +11852,39 @@ } ] }, + { + "id": "ES6UnusedImports", + "shortDescription": { + "text": "Unused import" + }, + "fullDescription": { + "text": "Reports a redundant 'import' statement. This is usually the case if the imported symbols are not used in the source file. To avoid side-effects, consider using bare import 'import 'packageName'' instead of the regular one.", + "markdown": "Reports a redundant `import` statement. This is usually the case if the imported symbols are not used in the source file. To avoid side-effects, consider using bare import `import 'packageName'` instead of the regular one." + }, + "defaultConfiguration": { + "enabled": false, + "level": "warning", + "parameters": { + "suppressToolId": "ES6UnusedImports", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" + } + }, + "relationships": [ + { + "target": { + "id": "JavaScript and TypeScript/Imports and dependencies", + "index": 47, + "toolComponent": { + "name": "QDPY" + } + }, + "kinds": [ + "superset" + ] + } + ] + }, { "id": "JSSwitchVariableDeclarationIssue", "shortDescription": { @@ -11973,7 +11973,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -12183,19 +12183,19 @@ ] }, { - "id": "ReturnFromFinallyBlockJS", + "id": "JSUnusedLocalSymbols", "shortDescription": { - "text": "'return' inside 'finally' block" + "text": "Unused local symbol" }, "fullDescription": { - "text": "Reports a 'return' statement inside a 'finally' block. Such 'return' statements may mask exceptions thrown, and complicate debugging.", - "markdown": "Reports a `return` statement inside a `finally` block. Such `return` statements may mask exceptions thrown, and complicate debugging." + "text": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration.", + "markdown": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "ReturnInsideFinallyBlockJS", + "suppressToolId": "JSUnusedLocalSymbols", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -12203,8 +12203,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, + "id": "JavaScript and TypeScript/Unused symbols", + "index": 19, "toolComponent": { "name": "QDPY" } @@ -12216,19 +12216,19 @@ ] }, { - "id": "JSUnusedLocalSymbols", + "id": "ReturnFromFinallyBlockJS", "shortDescription": { - "text": "Unused local symbol" + "text": "'return' inside 'finally' block" }, "fullDescription": { - "text": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration.", - "markdown": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration." + "text": "Reports a 'return' statement inside a 'finally' block. Such 'return' statements may mask exceptions thrown, and complicate debugging.", + "markdown": "Reports a `return` statement inside a `finally` block. Such `return` statements may mask exceptions thrown, and complicate debugging." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "JSUnusedLocalSymbols", + "suppressToolId": "ReturnInsideFinallyBlockJS", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -12236,8 +12236,8 @@ "relationships": [ { "target": { - "id": "JavaScript and TypeScript/Unused symbols", - "index": 19, + "id": "JavaScript and TypeScript/Try statement issues", + "index": 33, "toolComponent": { "name": "QDPY" } @@ -12270,7 +12270,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -14190,19 +14190,19 @@ ] }, { - "id": "RegExpRedundantNestedCharacterClass", + "id": "XmlDeprecatedElement", "shortDescription": { - "text": "Redundant nested character class" + "text": "Deprecated symbol" }, "fullDescription": { - "text": "Reports unnecessary nested character classes. Example: '[a-c[x-z]]' After the quick-fix is applied: '[a-cx-z]' New in 2020.2", - "markdown": "Reports unnecessary nested character classes.\n\n**Example:**\n\n\n [a-c[x-z]]\n\nAfter the quick-fix is applied:\n\n\n [a-cx-z]\n\nNew in 2020.2" + "text": "Reports a deprecated XML element or attribute. Symbols can be marked by XML comment or documentation tag with text 'deprecated'.", + "markdown": "Reports a deprecated XML element or attribute.\n\nSymbols can be marked by XML comment or documentation tag with text 'deprecated'." }, "defaultConfiguration": { - "enabled": true, + "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "RegExpRedundantNestedCharacterClass", + "suppressToolId": "XmlDeprecatedElement", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -14210,8 +14210,8 @@ "relationships": [ { "target": { - "id": "RegExp", - "index": 43, + "id": "XML", + "index": 38, "toolComponent": { "name": "QDPY" } @@ -14223,19 +14223,19 @@ ] }, { - "id": "XmlDeprecatedElement", + "id": "RegExpRedundantNestedCharacterClass", "shortDescription": { - "text": "Deprecated symbol" + "text": "Redundant nested character class" }, "fullDescription": { - "text": "Reports a deprecated XML element or attribute. Symbols can be marked by XML comment or documentation tag with text 'deprecated'.", - "markdown": "Reports a deprecated XML element or attribute.\n\nSymbols can be marked by XML comment or documentation tag with text 'deprecated'." + "text": "Reports unnecessary nested character classes. Example: '[a-c[x-z]]' After the quick-fix is applied: '[a-cx-z]' New in 2020.2", + "markdown": "Reports unnecessary nested character classes.\n\n**Example:**\n\n\n [a-c[x-z]]\n\nAfter the quick-fix is applied:\n\n\n [a-cx-z]\n\nNew in 2020.2" }, "defaultConfiguration": { - "enabled": false, + "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "XmlDeprecatedElement", + "suppressToolId": "RegExpRedundantNestedCharacterClass", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -14243,8 +14243,8 @@ "relationships": [ { "target": { - "id": "XML", - "index": 38, + "id": "RegExp", + "index": 43, "toolComponent": { "name": "QDPY" } @@ -14586,19 +14586,19 @@ ] }, { - "id": "RegExpRepeatedSpace", + "id": "RegExpDuplicateAlternationBranch", "shortDescription": { - "text": "Consecutive spaces" + "text": "Duplicate branch in alternation" }, "fullDescription": { - "text": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier. Example: '( )' After the quick-fix is applied: '( {5})' New in 2017.1", - "markdown": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier.\n\n**Example:**\n\n\n ( )\n\nAfter the quick-fix is applied:\n\n\n ( {5})\n\n\nNew in 2017.1" + "text": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression. Example: '(alpha|bravo|charlie|alpha)' After the quick-fix is applied: '(alpha|bravo|charlie)' New in 2017.1", + "markdown": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression.\n\n**Example:**\n\n\n (alpha|bravo|charlie|alpha)\n\nAfter the quick-fix is applied:\n\n\n (alpha|bravo|charlie)\n\nNew in 2017.1" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "RegExpRepeatedSpace", + "suppressToolId": "RegExpDuplicateAlternationBranch", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -14619,19 +14619,19 @@ ] }, { - "id": "RegExpDuplicateAlternationBranch", + "id": "RegExpRepeatedSpace", "shortDescription": { - "text": "Duplicate branch in alternation" + "text": "Consecutive spaces" }, "fullDescription": { - "text": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression. Example: '(alpha|bravo|charlie|alpha)' After the quick-fix is applied: '(alpha|bravo|charlie)' New in 2017.1", - "markdown": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression.\n\n**Example:**\n\n\n (alpha|bravo|charlie|alpha)\n\nAfter the quick-fix is applied:\n\n\n (alpha|bravo|charlie)\n\nNew in 2017.1" + "text": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier. Example: '( )' After the quick-fix is applied: '( {5})' New in 2017.1", + "markdown": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier.\n\n**Example:**\n\n\n ( )\n\nAfter the quick-fix is applied:\n\n\n ( {5})\n\n\nNew in 2017.1" }, "defaultConfiguration": { "enabled": true, "level": "warning", "parameters": { - "suppressToolId": "RegExpDuplicateAlternationBranch", + "suppressToolId": "RegExpRepeatedSpace", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -16215,19 +16215,19 @@ ] }, { - "id": "SqlRedundantAliasInspection", + "id": "SqlIdentifierInspection", "shortDescription": { - "text": "Redundant alias expressions" + "text": "Identifier should be quoted" }, "fullDescription": { - "text": "Reports alias expressions that duplicate names of columns in tables and might be redundant. Example (PostgreSQL): 'CREATE TABLE foo(a INT, b INT);\n\nSELECT * FROM foo foo(a, b);\nSELECT * FROM foo foo(a);\nSELECT * FROM foo foo(x);\nSELECT * FROM foo foo(x, y);' The first two aliases use the same column names as in the 'foo' table. They are considered redundant because they column names are identical.", - "markdown": "Reports alias expressions that duplicate names of columns in tables and might be redundant.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT, b INT);\n\n SELECT * FROM foo foo(a, b);\n SELECT * FROM foo foo(a);\n SELECT * FROM foo foo(x);\n SELECT * FROM foo foo(x, y);\n\nThe first two aliases use the same column names as in the `foo` table. They are considered redundant because they\ncolumn names are identical." + "text": "Reports situations when you use SQL reserved keywords as identifier names in your query. Example (Microsoft SQL Server): 'CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);' We use 'select', 'identity', and 'order' as table and column names. But they are also reserved keywords in Microsoft SQL Server. Therefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the Quote identifier quick-fix. After the quick-fix is applied: 'CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);'", + "markdown": "Reports situations when you use SQL reserved keywords as identifier names in your query.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);\n\nWe use `select`, `identity`, and `order` as table and column names.\nBut they are also reserved keywords in Microsoft SQL Server.\nTherefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the\n**Quote identifier** quick-fix.\n\nAfter the quick-fix is applied:\n\n CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "SqlRedundantAlias", + "suppressToolId": "SqlIdentifier", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -16248,19 +16248,19 @@ ] }, { - "id": "SqlIdentifierInspection", + "id": "SqlRedundantAliasInspection", "shortDescription": { - "text": "Identifier should be quoted" + "text": "Redundant alias expressions" }, "fullDescription": { - "text": "Reports situations when you use SQL reserved keywords as identifier names in your query. Example (Microsoft SQL Server): 'CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);' We use 'select', 'identity', and 'order' as table and column names. But they are also reserved keywords in Microsoft SQL Server. Therefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the Quote identifier quick-fix. After the quick-fix is applied: 'CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);'", - "markdown": "Reports situations when you use SQL reserved keywords as identifier names in your query.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);\n\nWe use `select`, `identity`, and `order` as table and column names.\nBut they are also reserved keywords in Microsoft SQL Server.\nTherefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the\n**Quote identifier** quick-fix.\n\nAfter the quick-fix is applied:\n\n CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);\n" + "text": "Reports alias expressions that duplicate names of columns in tables and might be redundant. Example (PostgreSQL): 'CREATE TABLE foo(a INT, b INT);\n\nSELECT * FROM foo foo(a, b);\nSELECT * FROM foo foo(a);\nSELECT * FROM foo foo(x);\nSELECT * FROM foo foo(x, y);' The first two aliases use the same column names as in the 'foo' table. They are considered redundant because they column names are identical.", + "markdown": "Reports alias expressions that duplicate names of columns in tables and might be redundant.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT, b INT);\n\n SELECT * FROM foo foo(a, b);\n SELECT * FROM foo foo(a);\n SELECT * FROM foo foo(x);\n SELECT * FROM foo foo(x, y);\n\nThe first two aliases use the same column names as in the `foo` table. They are considered redundant because they\ncolumn names are identical." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "SqlIdentifier", + "suppressToolId": "SqlRedundantAlias", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -16743,19 +16743,19 @@ ] }, { - "id": "MongoJSExtResolveInspection", + "id": "SqlGotoInspection", "shortDescription": { - "text": "Resolution problems" + "text": "Usages of GOTO statements" }, "fullDescription": { - "text": "Reports unresolved references in MongoDB and JavaScript code.", - "markdown": "Reports unresolved references in MongoDB and JavaScript code." + "text": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop. The extensive use of GOTO statements is generally not recommended. For details, see GOTO statement in SQL procedures at ibm.com. Instead of jumping back to a previous statement using GOTO, consider using a loop. Instead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK). Example (Oracle): 'CREATE PROCEDURE test(n INT) AS\nDECLARE\n x INT;\nBEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\nEND;'", + "markdown": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop.\n\nThe extensive use of GOTO statements is generally\nnot recommended. For details, see [GOTO statement in\nSQL\nprocedures at ibm.com](https://www.ibm.com/docs/no/db2/11.5?topic=procedures-goto-statement-in-sql).\n\nInstead of jumping back to a previous statement using GOTO, consider using a loop.\n\nInstead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK).\n\nExample (Oracle):\n\n CREATE PROCEDURE test(n INT) AS\n DECLARE\n x INT;\n BEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\n END;\n" }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "MongoJSResolve", + "suppressToolId": "SqlGoto", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -16763,8 +16763,8 @@ "relationships": [ { "target": { - "id": "MongoJS", - "index": 10, + "id": "SQL", + "index": 32, "toolComponent": { "name": "QDPY" } @@ -16776,19 +16776,19 @@ ] }, { - "id": "SqlGotoInspection", + "id": "MongoJSExtResolveInspection", "shortDescription": { - "text": "Usages of GOTO statements" + "text": "Resolution problems" }, "fullDescription": { - "text": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop. The extensive use of GOTO statements is generally not recommended. For details, see GOTO statement in SQL procedures at ibm.com. Instead of jumping back to a previous statement using GOTO, consider using a loop. Instead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK). Example (Oracle): 'CREATE PROCEDURE test(n INT) AS\nDECLARE\n x INT;\nBEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\nEND;'", - "markdown": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop.\n\nThe extensive use of GOTO statements is generally\nnot recommended. For details, see [GOTO statement in\nSQL\nprocedures at ibm.com](https://www.ibm.com/docs/no/db2/11.5?topic=procedures-goto-statement-in-sql).\n\nInstead of jumping back to a previous statement using GOTO, consider using a loop.\n\nInstead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK).\n\nExample (Oracle):\n\n CREATE PROCEDURE test(n INT) AS\n DECLARE\n x INT;\n BEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\n END;\n" + "text": "Reports unresolved references in MongoDB and JavaScript code.", + "markdown": "Reports unresolved references in MongoDB and JavaScript code." }, "defaultConfiguration": { "enabled": false, "level": "warning", "parameters": { - "suppressToolId": "SqlGoto", + "suppressToolId": "MongoJSResolve", "ideaSeverity": "WARNING", "qodanaSeverity": "High" } @@ -16796,8 +16796,8 @@ "relationships": [ { "target": { - "id": "SQL", - "index": 32, + "id": "MongoJS", + "index": 10, "toolComponent": { "name": "QDPY" } @@ -19482,7 +19482,7 @@ { "target": { "id": "JavaScript and TypeScript/General", - "index": 12, + "index": 11, "toolComponent": { "name": "QDPY" } @@ -19587,7 +19587,7 @@ "toolExecutionNotifications": [ { "message": { - "text": "Reporting from [\"An invalid interpreter\", \"Sanity\", \"Unresolved references\"] 'sanity' inspections was suspended due to high problems count." + "text": "Reporting from [\"Sanity\", \"Unresolved references\", \"An invalid interpreter\"] 'sanity' inspections was suspended due to high problems count." }, "level": "error" } @@ -19599,11 +19599,11 @@ "versionControlProvenance": [ { "repositoryUri": "https://github.com/Pale-Blue-Dot-97/Minerva.git", - "revisionId": "f82489002d81ad4e66fbe6a679decdd7689b3b44", - "branch": "v0.26-dev", + "revisionId": "7a23092940ae572c0dd637d13478238d83406d13", + "branch": "downstream-tasks-module", "properties": { "repoUrl": "https://github.com/Pale-Blue-Dot-97/Minerva.git", - "lastAuthorName": "Harry", + "lastAuthorName": "Harry Baker", "vcsType": "Git", "lastAuthorEmail": "hjbaker97@gmail.com" } @@ -19626,9 +19626,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 525, + "startLine": 527, "startColumn": 5, - "charOffset": 17381, + "charOffset": 17438, "charLength": 6, "snippet": { "text": "except" @@ -19636,9 +19636,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 523, + "startLine": 525, "startColumn": 1, - "charOffset": 17293, + "charOffset": 17350, "charLength": 160, "snippet": { "text": " if \"VSCODE_PID\" in os.environ: # pragma: no cover\n return False\n except: # noqa: E722\n return False\n else: # pragma: no cover" @@ -19655,7 +19655,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "7b6beeaf8484f6c73aeb2478641e552a454a5875f80dca47bdda4cc85b0151cb" + "equalIndicator/v1": "fde4c482b4e89a58866efaf001419f5699512eb5fb724aa6a5fcc17be3b212ca" }, "baselineState": "unchanged", "properties": { @@ -20858,9 +20858,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 301, + "startLine": 303, "startColumn": 17, - "charOffset": 10701, + "charOffset": 10758, "charLength": 3, "snippet": { "text": "cls" @@ -20868,9 +20868,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 299, + "startLine": 301, "startColumn": 1, - "charOffset": 10683, + "charOffset": 10740, "charLength": 182, "snippet": { "text": "\n\ndef tg_to_torch(cls, keys: Optional[Sequence[str]] = None):\n \"\"\"Ensures wrapped transform can handle both :class:`~torch.Tensor` and :mod:`torchgeo` style :class:`dict` inputs.\n" @@ -20887,7 +20887,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "3d314f58842c9c99fcfda2b8be565ef6266060f7302721ab56f64be4cbeeaf03" + "equalIndicator/v1": "8f20ea2c64e63a5d997c22f139e2a79159327a2890354344a12b4194164fe8d0" }, "baselineState": "unchanged", "properties": { @@ -20910,250 +20910,26 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1646, - "startColumn": 5, - "charOffset": 57017, - "charLength": 22, - "snippet": { - "text": "_testing: bool = False" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1644, - "startColumn": 1, - "charOffset": 56948, - "charLength": 182, - "snippet": { - "text": " env_name: str = \"env\",\n host_num: Union[str, int] = 6006,\n _testing: bool = False,\n) -> Optional[int]:\n \"\"\"Runs the :mod:`TensorBoard` logs and hosts on a local webpage." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "9394196b9aaacc9f8371e8f45a6a4ba35b55a070b98693265fb8a43d16986c7c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "CamelCase variable imported as constant", - "markdown": "CamelCase variable imported as constant" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 66, - "startColumn": 58, - "charOffset": 2705, - "charLength": 3, - "snippet": { - "text": "DDP" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 64, - "startColumn": 1, - "charOffset": 2587, - "charLength": 162, - "snippet": { - "text": "from torch import Tensor\nfrom torch.nn.modules import Module\nfrom torch.nn.parallel import DistributedDataParallel as DDP\nfrom torch.utils.data import DataLoader\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "18fadfd07813c24d18234568648f6b8710e56b5434399a407c380febd2b7c943" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Lowercase variable imported as non-lowercase", - "markdown": "Lowercase variable imported as non-lowercase" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 166, - "startColumn": 36, - "charOffset": 5914, - "charLength": 1, - "snippet": { - "text": "F" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 164, - "startColumn": 1, - "charOffset": 5812, - "charLength": 171, - "snippet": { - "text": "from tabulate import tabulate\nfrom torch import LongTensor, Tensor\nfrom torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "1ad04cc5c56a238fe61cd39cf4599baecff1d4f0239e96b92183768f65ff5d9b" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Lowercase variable imported as non-lowercase", - "markdown": "Lowercase variable imported as non-lowercase" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 57, - "startColumn": 31, - "charOffset": 2346, - "charLength": 1, - "snippet": { - "text": "F" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 55, - "startColumn": 1, - "charOffset": 2302, - "charLength": 100, - "snippet": { - "text": "\nimport torch\nimport torch.nn.functional as F\nimport torch.nn.modules as nn\nfrom torch import Tensor" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8fd630246011f5a0c017663c439dbc7f6e1a7453b09421c90330187aa0484199" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _api of a class", - "markdown": "Access to a protected member _api of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/resnet.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 55, - "startColumn": 6, - "charOffset": 2352, - "charLength": 23, + "startLine": 1648, + "startColumn": 5, + "charOffset": 57090, + "charLength": 22, "snippet": { - "text": "torchvision.models._api" + "text": "_testing: bool = False" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 53, + "startLine": 1646, "startColumn": 1, - "charOffset": 2286, - "charLength": 179, + "charOffset": 57021, + "charLength": 182, "snippet": { - "text": "from torch import Tensor\nfrom torch.nn.modules import Module\nfrom torchvision.models._api import WeightsEnum\nfrom torchvision.models.resnet import BasicBlock, Bottleneck, conv1x1\n" + "text": " env_name: str = \"env\",\n host_num: Union[str, int] = 6006,\n _testing: bool = False,\n) -> Optional[int]:\n \"\"\"Runs the :mod:`TensorBoard` logs and hosts on a local webpage." }, "sourceLanguage": "Python" } @@ -21167,7 +20943,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "0472c2c74b7833a451026d4b481a6631f9280b669e00a4f94029b634e200a889" + "equalIndicator/v1": "ecc48a2ba0d041faaba2b7cbd6a334047d3a874d7b346ea1487866137449397c" }, "baselineState": "unchanged", "properties": { @@ -21179,37 +20955,37 @@ } }, { - "ruleId": "PyProtectedMemberInspection", + "ruleId": "PyPep8NamingInspection", "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _device of a class", - "markdown": "Access to a protected member _device of a class" + "text": "CamelCase variable imported as constant", + "markdown": "CamelCase variable imported as constant" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/trainer.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 168, - "startColumn": 25, - "charOffset": 5976, - "charLength": 7, + "startLine": 50, + "startColumn": 58, + "charOffset": 2439, + "charLength": 3, "snippet": { - "text": "_device" + "text": "DDP" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 166, + "startLine": 48, "startColumn": 1, - "charOffset": 5879, - "charLength": 202, + "charOffset": 2293, + "charLength": 188, "snippet": { - "text": "from torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device\nfrom torchgeo.datasets.utils import BoundingBox\nfrom urllib3.exceptions import NewConnectionError" + "text": "from inputimeout import TimeoutOccurred, inputimeout\nfrom torch.nn.modules import Module\nfrom torch.nn.parallel import DistributedDataParallel as DDP\n\nif TYPE_CHECKING: # pragma: no cover" }, "sourceLanguage": "Python" } @@ -21223,7 +20999,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "0f2456a8fdbed764c165244423c9057c5e152f35b1668ebf50d5b09897b6b4e9" + "equalIndicator/v1": "61309292db3ee6fe81a69b91a9fa4dbe99cb27784f7083f58845873760156a62" }, "baselineState": "unchanged", "properties": { @@ -21235,37 +21011,37 @@ } }, { - "ruleId": "PyProtectedMemberInspection", + "ruleId": "PyPep8NamingInspection", "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" + "text": "Lowercase variable imported as non-lowercase", + "markdown": "Lowercase variable imported as non-lowercase" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/trainer.py", + "uri": "minerva/models/unet.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 514, - "startColumn": 21, - "charOffset": 25297, - "charLength": 22, + "startLine": 57, + "startColumn": 31, + "charOffset": 2346, + "charLength": 1, "snippet": { - "text": "utils._optional_import" + "text": "F" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 512, + "startLine": 55, "startColumn": 1, - "charOffset": 25211, - "charLength": 154, + "charOffset": 2302, + "charLength": 100, "snippet": { - "text": " MinervaModel: Loaded model ready for use.\n \"\"\"\n onnx_load = utils._optional_import(\n \"onnx\",\n name=\"load\"," + "text": "\nimport torch\nimport torch.nn.functional as F\nimport torch.nn.modules as nn\nfrom torch import Tensor" }, "sourceLanguage": "Python" } @@ -21279,7 +21055,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "4e9207c276c14d079dbc202c219df96d956816700971f3331aaf754bee81bff1" + "equalIndicator/v1": "8fd630246011f5a0c017663c439dbc7f6e1a7453b09421c90330187aa0484199" }, "baselineState": "unchanged", "properties": { @@ -21291,37 +21067,37 @@ } }, { - "ruleId": "PyProtectedMemberInspection", + "ruleId": "PyPep8NamingInspection", "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _print_banner of a module", - "markdown": "Access to a protected member _print_banner of a module" + "text": "Lowercase variable imported as non-lowercase", + "markdown": "Lowercase variable imported as non-lowercase" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "scripts/MinervaExp.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 84, - "startColumn": 5, - "charOffset": 3249, - "charLength": 19, + "startLine": 168, + "startColumn": 36, + "charOffset": 5971, + "charLength": 1, "snippet": { - "text": "utils._print_banner" + "text": "F" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 82, + "startLine": 166, "startColumn": 1, - "charOffset": 3216, - "charLength": 97, + "charOffset": 5869, + "charLength": 171, "snippet": { - "text": "\n # Print Minerva banner.\n utils._print_banner()\n\n with runner.WandbConnectionManager():" + "text": "from tabulate import tabulate\nfrom torch import LongTensor, Tensor\nfrom torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device" }, "sourceLanguage": "Python" } @@ -21335,7 +21111,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6164e8df1c5babd87fb4edb7e111aede2178ed7ff0f793fa8712c350d3b268e4" + "equalIndicator/v1": "c9821a4400d8da88d2822ddc6d87338c1d2f2c52820fc45717d148bb349686f8" }, "baselineState": "unchanged", "properties": { @@ -21358,13 +21134,13 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/logger.py", + "uri": "minerva/trainer.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 80, - "startColumn": 26, - "charOffset": 3117, + "startLine": 468, + "startColumn": 19, + "charOffset": 23647, "charLength": 22, "snippet": { "text": "utils._optional_import" @@ -21372,12 +21148,12 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 78, + "startLine": 466, "startColumn": 1, - "charOffset": 3038, - "charLength": 174, + "charOffset": 23591, + "charLength": 133, "snippet": { - "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," + "text": " package=\"onnx\",\n )\n convert = utils._optional_import(\n \"onnx2torch\",\n name=\"convert\"," }, "sourceLanguage": "Python" } @@ -21391,7 +21167,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "8a70c13dacc609d8b7bcf49b10acaa087d51ab2a4fcb0346cd54916c1e10e800" + "equalIndicator/v1": "0349e9710547309113fb65590b35837ba470f08228b62165be7fc8f5adc261b6" }, "baselineState": "unchanged", "properties": { @@ -21414,13 +21190,13 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/core.py", + "uri": "minerva/models/resnet.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 74, + "startLine": 55, "startColumn": 6, - "charOffset": 2705, + "charOffset": 2352, "charLength": 23, "snippet": { "text": "torchvision.models._api" @@ -21428,12 +21204,12 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 72, + "startLine": 53, "startColumn": 1, - "charOffset": 2598, - "charLength": 194, + "charOffset": 2286, + "charLength": 179, "snippet": { - "text": "from torch.nn.parallel import DataParallel, DistributedDataParallel\nfrom torch.optim import Optimizer\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.utils.utils import func_by_str" + "text": "from torch import Tensor\nfrom torch.nn.modules import Module\nfrom torchvision.models._api import WeightsEnum\nfrom torchvision.models.resnet import BasicBlock, Bottleneck, conv1x1\n" }, "sourceLanguage": "Python" } @@ -21447,7 +21223,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "8b51e20bf8f917d419736322b28dabc097341417ece59c6496a2e5c02233c33f" + "equalIndicator/v1": "0472c2c74b7833a451026d4b481a6631f9280b669e00a4f94029b634e200a889" }, "baselineState": "unchanged", "properties": { @@ -21463,33 +21239,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _to_tuple of a class", - "markdown": "Access to a protected member _to_tuple of a class" + "text": "Access to a protected member _optional_import of a module", + "markdown": "Access to a protected member _optional_import of a module" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/samplers.py", + "uri": "minerva/trainer.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 51, - "startColumn": 37, - "charOffset": 2452, - "charLength": 9, + "startLine": 78, + "startColumn": 26, + "charOffset": 3467, + "charLength": 22, "snippet": { - "text": "_to_tuple" + "text": "utils._optional_import" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 49, + "startLine": 76, "startColumn": 1, - "charOffset": 2297, - "charLength": 222, + "charOffset": 3388, + "charLength": 174, "snippet": { - "text": "from torchgeo.datasets.utils import BoundingBox\nfrom torchgeo.samplers import BatchGeoSampler, RandomGeoSampler, Units\nfrom torchgeo.samplers.utils import _to_tuple, get_random_bounding_box\n\nfrom minerva.utils import utils" + "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," }, "sourceLanguage": "Python" } @@ -21503,7 +21279,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "b2c2959ec4e8ff08e68ad8c76689f48f42da52cfabcc7c68f67f75d05cd40b9f" + "equalIndicator/v1": "220477eebf686f2e357a93574f4dc131e22d41a7e23cec1c45ac8cd72cd904ab" }, "baselineState": "unchanged", "properties": { @@ -21519,33 +21295,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _api of a class", - "markdown": "Access to a protected member _api of a class" + "text": "Access to a protected member _device of a class", + "markdown": "Access to a protected member _device of a class" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "scripts/TorchWeightDownloader.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 41, - "startColumn": 6, - "charOffset": 1766, - "charLength": 23, + "startLine": 170, + "startColumn": 25, + "charOffset": 6033, + "charLength": 7, "snippet": { - "text": "torchvision.models._api" + "text": "_device" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 39, + "startLine": 168, "startColumn": 1, - "charOffset": 1732, - "charLength": 122, + "charOffset": 5936, + "charLength": 202, "snippet": { - "text": "from typing import Optional\n\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.models import get_torch_weights" + "text": "from torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device\nfrom torchgeo.datasets.utils import BoundingBox\nfrom urllib3.exceptions import NewConnectionError" }, "sourceLanguage": "Python" } @@ -21559,7 +21335,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "e1858e4087549f5d60c37a7259b7e8301a75bb755f8fc63ba58a31bb4d092d6b" + "equalIndicator/v1": "358613aa9ea51d004c3d7b4cf758a94fb478784a99aa8c3068caa4d491dfb13c" }, "baselineState": "unchanged", "properties": { @@ -21575,33 +21351,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" + "text": "Access to a protected member _print_banner of a module", + "markdown": "Access to a protected member _print_banner of a module" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/trainer.py", + "uri": "scripts/MinervaExp.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 98, - "startColumn": 26, - "charOffset": 3896, - "charLength": 22, + "startLine": 84, + "startColumn": 5, + "charOffset": 3249, + "charLength": 19, "snippet": { - "text": "utils._optional_import" + "text": "utils._print_banner" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 96, + "startLine": 82, "startColumn": 1, - "charOffset": 3817, - "charLength": 174, + "charOffset": 3216, + "charLength": 97, "snippet": { - "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," + "text": "\n # Print Minerva banner.\n utils._print_banner()\n\n with runner.WandbConnectionManager():" }, "sourceLanguage": "Python" } @@ -21615,7 +21391,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "e5bba2fcf2c896511e7a99d9599db24436317e8717dfcc09b9ccda001c85ed71" + "equalIndicator/v1": "6164e8df1c5babd87fb4edb7e111aede2178ed7ff0f793fa8712c350d3b268e4" }, "baselineState": "unchanged", "properties": { @@ -21631,33 +21407,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" + "text": "Access to a protected member _api of a class", + "markdown": "Access to a protected member _api of a class" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/trainer.py", + "uri": "minerva/models/core.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 519, - "startColumn": 19, - "charOffset": 25422, - "charLength": 22, + "startLine": 74, + "startColumn": 6, + "charOffset": 2705, + "charLength": 23, "snippet": { - "text": "utils._optional_import" + "text": "torchvision.models._api" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 517, + "startLine": 72, "startColumn": 1, - "charOffset": 25366, - "charLength": 133, + "charOffset": 2598, + "charLength": 194, "snippet": { - "text": " package=\"onnx\",\n )\n convert = utils._optional_import(\n \"onnx2torch\",\n name=\"convert\"," + "text": "from torch.nn.parallel import DataParallel, DistributedDataParallel\nfrom torch.optim import Optimizer\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.utils.utils import func_by_str" }, "sourceLanguage": "Python" } @@ -21671,7 +21447,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "fd498f8cd4045fab9f4f79903b9c4754be28b8afdfe713c1d8ddaf58cf2f6bdd" + "equalIndicator/v1": "8b51e20bf8f917d419736322b28dabc097341417ece59c6496a2e5c02233c33f" }, "baselineState": "unchanged", "properties": { @@ -21683,37 +21459,37 @@ } }, { - "ruleId": "PyRedeclarationInspection", + "ruleId": "PyProtectedMemberInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "Redeclared 'step' defined above without usage", - "markdown": "Redeclared 'step' defined above without usage" + "text": "Access to a protected member _to_tuple of a class", + "markdown": "Access to a protected member _to_tuple of a class" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/core.py", + "uri": "minerva/samplers.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 159, - "startColumn": 9, - "charOffset": 6293, - "charLength": 4, + "startLine": 51, + "startColumn": 37, + "charOffset": 2452, + "charLength": 9, "snippet": { - "text": "step" + "text": "_to_tuple" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 157, + "startLine": 49, "startColumn": 1, - "charOffset": 6252, - "charLength": 79, + "charOffset": 2297, + "charLength": 222, "snippet": { - "text": " ... # pragma: no cover\n\n def step(\n self,\n x: Tensor," + "text": "from torchgeo.datasets.utils import BoundingBox\nfrom torchgeo.samplers import BatchGeoSampler, RandomGeoSampler, Units\nfrom torchgeo.samplers.utils import _to_tuple, get_random_bounding_box\n\nfrom minerva.utils import utils" }, "sourceLanguage": "Python" } @@ -21727,49 +21503,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "100440895dcf044186110430da49ceb01c344a6633474c17a06526549c0153fe" + "equalIndicator/v1": "b2c2959ec4e8ff08e68ad8c76689f48f42da52cfabcc7c68f67f75d05cd40b9f" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] } }, { - "ruleId": "PyRedeclarationInspection", + "ruleId": "PyProtectedMemberInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "Redeclared 'transform_coordinates' defined above without usage", - "markdown": "Redeclared 'transform_coordinates' defined above without usage" + "text": "Access to a protected member _optional_import of a module", + "markdown": "Access to a protected member _optional_import of a module" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/trainer.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 707, - "startColumn": 5, - "charOffset": 22626, - "charLength": 21, + "startLine": 463, + "startColumn": 21, + "charOffset": 23522, + "charLength": 22, "snippet": { - "text": "transform_coordinates" + "text": "utils._optional_import" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 705, + "startLine": 461, "startColumn": 1, - "charOffset": 22620, - "charLength": 104, + "charOffset": 23436, + "charLength": 154, "snippet": { - "text": "\n\ndef transform_coordinates(\n x: Union[Sequence[float], float],\n y: Union[Sequence[float], float]," + "text": " MinervaModel: Loaded model ready for use.\n \"\"\"\n onnx_load = utils._optional_import(\n \"onnx\",\n name=\"load\"," }, "sourceLanguage": "Python" } @@ -21783,49 +21559,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "108602141d0e61edadcb774e088b4f405e728fd1a35e5082dcb7051c5ff70e0a" + "equalIndicator/v1": "cc57de3a4fc5dd2a258e7a94baeb7a63d0083b96e9832dfda42e397fd373b3e8" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] } }, { - "ruleId": "PyRedeclarationInspection", + "ruleId": "PyProtectedMemberInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "Redeclared 'mask_transform' defined above without usage", - "markdown": "Redeclared 'mask_transform' defined above without usage" + "text": "Access to a protected member _api of a class", + "markdown": "Access to a protected member _api of a class" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "scripts/TorchWeightDownloader.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1141, - "startColumn": 5, - "charOffset": 38475, - "charLength": 14, + "startLine": 41, + "startColumn": 6, + "charOffset": 1766, + "charLength": 23, "snippet": { - "text": "mask_transform" + "text": "torchvision.models._api" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1139, + "startLine": 39, "startColumn": 1, - "charOffset": 38469, - "charLength": 98, + "charOffset": 1732, + "charLength": 122, "snippet": { - "text": "\n\ndef mask_transform(\n array: Union[NDArray[Any, Int], LongTensor],\n matrix: Dict[int, int]," + "text": "from typing import Optional\n\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.models import get_torch_weights" }, "sourceLanguage": "Python" } @@ -21839,49 +21615,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "3bceedfbd687fab050dd89027a5c1e27baf1d77a7243f7572e6dc404f8182b94" + "equalIndicator/v1": "e1858e4087549f5d60c37a7259b7e8301a75bb755f8fc63ba58a31bb4d092d6b" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] } }, { - "ruleId": "PyRedeclarationInspection", + "ruleId": "PyProtectedMemberInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "Redeclared '_optional_import' defined above without usage", - "markdown": "Redeclared '_optional_import' defined above without usage" + "text": "Access to a protected member _optional_import of a module", + "markdown": "Access to a protected member _optional_import of a module" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/logger/steplog.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 466, - "startColumn": 5, - "charOffset": 15514, - "charLength": 16, + "startLine": 85, + "startColumn": 26, + "charOffset": 3307, + "charLength": 22, "snippet": { - "text": "_optional_import" + "text": "utils._optional_import" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 464, + "startLine": 83, "startColumn": 1, - "charOffset": 15508, - "charLength": 145, + "charOffset": 3228, + "charLength": 174, "snippet": { - "text": "\n\ndef _optional_import(\n module: str, *, name: Optional[str] = None, package: Optional[str] = None\n) -> Union[ModuleType, Callable[..., Any]]:" + "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," }, "sourceLanguage": "Python" } @@ -21895,12 +21671,12 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6925f78d42489c88685dd71f19f25f1a69600fa98d382233a3f4a5387f382067" + "equalIndicator/v1": "e9a177ffdac094aa30ddf0bec186799e43e246ed7166c521f50ba49712687c28" }, - "baselineState": "unchanged", + "baselineState": "new", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] @@ -21911,33 +21687,33 @@ "kind": "fail", "level": "warning", "message": { - "text": "Redeclared '__call__' defined above without usage", - "markdown": "Redeclared '__call__' defined above without usage" + "text": "Redeclared 'step' defined above without usage", + "markdown": "Redeclared 'step' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/models/core.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 335, - "startColumn": 13, - "charOffset": 11943, - "charLength": 8, + "startLine": 168, + "startColumn": 9, + "charOffset": 6547, + "charLength": 4, "snippet": { - "text": "__call__" + "text": "step" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 333, + "startLine": 166, "startColumn": 1, - "charOffset": 11894, - "charLength": 202, + "charOffset": 6506, + "charLength": 79, "snippet": { - "text": " ... # pragma: no cover\n\n def __call__(self, batch: Union[Dict[str, Any], Tensor]) -> Dict[str, Any]:\n if isinstance(batch, Tensor):\n return self.wrap(batch)" + "text": " ... # pragma: no cover\n\n def step(\n self,\n x: Tensor," }, "sourceLanguage": "Python" } @@ -21951,7 +21727,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6efbc109fb340bbfa1d7c1d5e6a8ebb43dd13c9c61ab75e8f4e5f653745eab11" + "equalIndicator/v1": "08c240f31814bdcdc137428c4ade3faa0078881a4d4e76f8dad5504c8db774ac" }, "baselineState": "unchanged", "properties": { @@ -21967,33 +21743,33 @@ "kind": "fail", "level": "warning", "message": { - "text": "Redeclared '__init__' defined above without usage", - "markdown": "Redeclared '__init__' defined above without usage" + "text": "Redeclared 'mask_transform' defined above without usage", + "markdown": "Redeclared 'mask_transform' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/paired.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 95, - "startColumn": 9, - "charOffset": 3968, - "charLength": 8, + "startLine": 1143, + "startColumn": 5, + "charOffset": 38548, + "charLength": 14, "snippet": { - "text": "__init__" + "text": "mask_transform" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 93, + "startLine": 1141, "startColumn": 1, - "charOffset": 3927, - "charLength": 127, + "charOffset": 38542, + "charLength": 98, "snippet": { - "text": " ... # pragma: no cover\n\n def __init__(\n self,\n dataset: Union[Callable[..., GeoDataset], GeoDataset]," + "text": "\n\ndef mask_transform(\n array: Union[NDArray[Any, Int], LongTensor],\n matrix: Dict[int, int]," }, "sourceLanguage": "Python" } @@ -22007,7 +21783,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "a00682d1db8abcf9858e9e8ff6058bc3c35d337bdcb30e738edfe1cff9c1091f" + "equalIndicator/v1": "1fecd676ba08b11a2c6e99fc0980bee6d0bbada5926f4cc8cb3b7b7496f3458f" }, "baselineState": "unchanged", "properties": { @@ -22023,33 +21799,33 @@ "kind": "fail", "level": "warning", "message": { - "text": "Redeclared '__call__' defined above without usage", - "markdown": "Redeclared '__call__' defined above without usage" + "text": "Redeclared 'transform_coordinates' defined above without usage", + "markdown": "Redeclared 'transform_coordinates' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/transforms.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 491, - "startColumn": 9, - "charOffset": 17125, - "charLength": 8, + "startLine": 709, + "startColumn": 5, + "charOffset": 22699, + "charLength": 21, "snippet": { - "text": "__call__" + "text": "transform_coordinates" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 489, + "startLine": 707, "startColumn": 1, - "charOffset": 17084, - "charLength": 142, + "charOffset": 22693, + "charLength": 104, "snippet": { - "text": " ... # pragma: no cover\n\n def __call__(\n self, sample: Union[Tensor, Dict[str, Any]]\n ) -> Union[Tensor, Dict[str, Any]]:" + "text": "\n\ndef transform_coordinates(\n x: Union[Sequence[float], float],\n y: Union[Sequence[float], float]," }, "sourceLanguage": "Python" } @@ -22063,7 +21839,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "d593716f8b2680b54c5d806f5ab4c7351c2a7b480dc3b449711dc4d5dba05408" + "equalIndicator/v1": "7cb06c2202498c1088fc2cfd03472ebfd9a00f67026ce05e55aa13a73ca90885" }, "baselineState": "unchanged", "properties": { @@ -22075,37 +21851,37 @@ } }, { - "ruleId": "PyShadowingNamesInspection", + "ruleId": "PyRedeclarationInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Shadows name 'transform_params' from outer scope", - "markdown": "Shadows name 'transform_params' from outer scope" + "text": "Redeclared '__init__' defined above without usage", + "markdown": "Redeclared '__init__' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/transforms.py", + "uri": "minerva/datasets/paired.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 716, - "startColumn": 13, - "charOffset": 25555, - "charLength": 16, + "startLine": 95, + "startColumn": 9, + "charOffset": 3968, + "charLength": 8, "snippet": { - "text": "transform_params" + "text": "__init__" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 714, + "startLine": 93, "startColumn": 1, - "charOffset": 25529, - "charLength": 213, + "charOffset": 3927, + "charLength": 127, "snippet": { - "text": "\n Example:\n >>> transform_params = {\n >>> \"CenterCrop\": {\"module\": \"torchvision.transforms\", \"size\": 128},\n >>> \"RandomHorizontalFlip\": {\"module\": \"torchvision.transforms\", \"p\": 0.7}" + "text": " ... # pragma: no cover\n\n def __init__(\n self,\n dataset: Union[Callable[..., GeoDataset], GeoDataset]," }, "sourceLanguage": "Python" } @@ -22119,49 +21895,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "5d191e4788335efc4f0b23e3edc3ef7e567f0837bdb4be55c7f5f598bbf38e2a" + "equalIndicator/v1": "a00682d1db8abcf9858e9e8ff6058bc3c35d337bdcb30e738edfe1cff9c1091f" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] } }, { - "ruleId": "PyShadowingNamesInspection", + "ruleId": "PyRedeclarationInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Shadows name 'err' from outer scope", - "markdown": "Shadows name 'err' from outer scope" + "text": "Redeclared '__call__' defined above without usage", + "markdown": "Redeclared '__call__' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/trainer.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1198, - "startColumn": 46, - "charOffset": 54453, - "charLength": 3, + "startLine": 337, + "startColumn": 13, + "charOffset": 12000, + "charLength": 8, "snippet": { - "text": "err" + "text": "__call__" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1196, + "startLine": 335, "startColumn": 1, - "charOffset": 54343, - "charLength": 233, + "charOffset": 11951, + "charLength": 202, "snippet": { - "text": " metrics_df.to_csv(f\"{self.exp_fn}_metrics.csv\")\n\n except (ValueError, KeyError) as err: # pragma: no cover\n self.print(err)\n self.print(\"\\n*ERROR* in saving metrics to file.\")" + "text": " ... # pragma: no cover\n\n def __call__(self, batch: Union[Dict[str, Any], Tensor]) -> Dict[str, Any]:\n if isinstance(batch, Tensor):\n return self.wrap(batch)" }, "sourceLanguage": "Python" } @@ -22175,49 +21951,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "5f4cf129751d5f94b639376e05dd165f2ba8fdf5701a440aed1b012587c21d16" + "equalIndicator/v1": "b9030b8d90b23ca06f2e5f3a19e314f37e4efe03209eae54395987d450b4dd59" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] } }, { - "ruleId": "PyShadowingNamesInspection", + "ruleId": "PyRedeclarationInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Shadows name 'name' from outer scope", - "markdown": "Shadows name 'name' from outer scope" + "text": "Redeclared '_optional_import' defined above without usage", + "markdown": "Redeclared '_optional_import' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/transforms.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 683, - "startColumn": 13, - "charOffset": 24218, - "charLength": 4, + "startLine": 468, + "startColumn": 5, + "charOffset": 15571, + "charLength": 16, "snippet": { - "text": "name" + "text": "_optional_import" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 681, + "startLine": 466, "startColumn": 1, - "charOffset": 24192, - "charLength": 175, + "charOffset": 15565, + "charLength": 145, "snippet": { - "text": "\n Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)" + "text": "\n\ndef _optional_import(\n module: str, *, name: Optional[str] = None, package: Optional[str] = None\n) -> Union[ModuleType, Callable[..., Any]]:" }, "sourceLanguage": "Python" } @@ -22231,49 +22007,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "7f4f024ca4fd5e9fdcd319c015fe15bed5a26395c1cc94eff00b59e4632e74ab" + "equalIndicator/v1": "c50875a96215277454107f37d08aa0b7cb99f53a51a16e33b5f100410984e723" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] } }, { - "ruleId": "PyShadowingNamesInspection", + "ruleId": "PyRedeclarationInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Shadows name 'err' from outer scope", - "markdown": "Shadows name 'err' from outer scope" + "text": "Redeclared '__call__' defined above without usage", + "markdown": "Redeclared '__call__' defined above without usage" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/trainer.py", + "uri": "minerva/transforms.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 402, - "startColumn": 44, - "charOffset": 20868, - "charLength": 3, + "startLine": 491, + "startColumn": 9, + "charOffset": 17125, + "charLength": 8, "snippet": { - "text": "err" + "text": "__call__" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 400, + "startLine": 489, "startColumn": 1, - "charOffset": 20711, - "charLength": 278, + "charOffset": 17084, + "charLength": 142, "snippet": { - "text": " input_to_model=torch.rand(*input_size, device=self.device),\n )\n except RuntimeError as err: # pragma: no cover\n print(err)\n print(\"ABORT adding graph to writer\")" + "text": " ... # pragma: no cover\n\n def __call__(\n self, sample: Union[Tensor, Dict[str, Any]]\n ) -> Union[Tensor, Dict[str, Any]]:" }, "sourceLanguage": "Python" } @@ -22287,12 +22063,12 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "c8807cec042e2d996c893a37f30098b81bb859e694af7e3bdb6f603688b2d399" + "equalIndicator/v1": "d593716f8b2680b54c5d806f5ab4c7351c2a7b480dc3b449711dc4d5dba05408" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] @@ -22303,8 +22079,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Shadows name 'transform' from outer scope", - "markdown": "Shadows name 'transform' from outer scope" + "text": "Shadows name 'transform_params' from outer scope", + "markdown": "Shadows name 'transform_params' from outer scope" }, "locations": [ { @@ -22314,22 +22090,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 685, + "startLine": 716, "startColumn": 13, - "charOffset": 24328, - "charLength": 9, + "charOffset": 25555, + "charLength": 16, "snippet": { - "text": "transform" + "text": "transform_params" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 683, + "startLine": 714, "startColumn": 1, - "charOffset": 24206, - "charLength": 174, + "charOffset": 25529, + "charLength": 213, "snippet": { - "text": " >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n\n Raises:" + "text": "\n Example:\n >>> transform_params = {\n >>> \"CenterCrop\": {\"module\": \"torchvision.transforms\", \"size\": 128},\n >>> \"RandomHorizontalFlip\": {\"module\": \"torchvision.transforms\", \"p\": 0.7}" }, "sourceLanguage": "Python" } @@ -22343,9 +22119,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "d9f46f829599ac3e9053a875980a65bd188091c26d51bcc2d14eba71bfe81480" + "equalIndicator/v1": "5d191e4788335efc4f0b23e3edc3ef7e567f0837bdb4be55c7f5f598bbf38e2a" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate", @@ -22359,8 +22135,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Shadows name 'params' from outer scope", - "markdown": "Shadows name 'params' from outer scope" + "text": "Shadows name 'name' from outer scope", + "markdown": "Shadows name 'name' from outer scope" }, "locations": [ { @@ -22370,22 +22146,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 684, + "startLine": 683, "startColumn": 13, - "charOffset": 24257, - "charLength": 6, + "charOffset": 24218, + "charLength": 4, "snippet": { - "text": "params" + "text": "name" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 682, + "startLine": 681, "startColumn": 1, - "charOffset": 24193, + "charOffset": 24192, "charLength": 175, "snippet": { - "text": " Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n" + "text": "\n Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)" }, "sourceLanguage": "Python" } @@ -22399,9 +22175,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "fee3860681fcdc20774c711da4a5c00a144128b6fbd1d3f3cc96af41216afb4a" + "equalIndicator/v1": "7f4f024ca4fd5e9fdcd319c015fe15bed5a26395c1cc94eff00b59e4632e74ab" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate", @@ -22411,37 +22187,37 @@ } }, { - "ruleId": "PyTypeHintsInspection", + "ruleId": "PyShadowingNamesInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" + "text": "Shadows name 'transform' from outer scope", + "markdown": "Shadows name 'transform' from outer scope" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/fcn.py", + "uri": "minerva/transforms.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 97, - "startColumn": 30, - "charOffset": 4620, - "charLength": 15, + "startLine": 685, + "startColumn": 13, + "charOffset": 24328, + "charLength": 9, "snippet": { - "text": "\"32\", \"16\", \"8\"" + "text": "transform" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 95, + "startLine": 683, "startColumn": 1, - "charOffset": 4554, - "charLength": 108, + "charOffset": 24206, + "charLength": 174, "snippet": { - "text": "\n backbone_name: str = \"ResNet18\"\n decoder_variant: Literal[\"32\", \"16\", \"8\"] = \"32\"\n\n def __init__(" + "text": " >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n\n Raises:" }, "sourceLanguage": "Python" } @@ -22455,49 +22231,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "2ed1d866d5dc3cc75fe869d8c8ea49dff49475d2a419726cad763c145bf34970" + "equalIndicator/v1": "d9f46f829599ac3e9053a875980a65bd188091c26d51bcc2d14eba71bfe81480" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] } }, { - "ruleId": "PyTypeHintsInspection", + "ruleId": "PyShadowingNamesInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" + "text": "Shadows name 'err' from outer scope", + "markdown": "Shadows name 'err' from outer scope" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/fcn.py", + "uri": "minerva/trainer.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 205, - "startColumn": 31, - "charOffset": 9905, - "charLength": 15, + "startLine": 358, + "startColumn": 44, + "charOffset": 19450, + "charLength": 3, "snippet": { - "text": "\"32\", \"16\", \"8\"" + "text": "err" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 203, + "startLine": 356, "startColumn": 1, - "charOffset": 9805, - "charLength": 170, + "charOffset": 19293, + "charLength": 278, "snippet": { - "text": " ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)\n self.variant: Literal[\"32\", \"16\", \"8\"] = variant\n\n assert type(self.n_classes) is int" + "text": " input_to_model=torch.rand(*input_size, device=self.device),\n )\n except RuntimeError as err: # pragma: no cover\n print(err)\n print(\"ABORT adding graph to writer\")" }, "sourceLanguage": "Python" } @@ -22511,49 +22287,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "52dbedae57240155661b7fedbef3b3e41329c899cf5cc6acdc8f005e9b6ba49e" + "equalIndicator/v1": "df986ba126c6307961f1dee6d13c08fa37ee1914f2e018cbb8e41c70fb4acc77" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] } }, { - "ruleId": "PyTypeHintsInspection", + "ruleId": "PyShadowingNamesInspection", "kind": "fail", - "level": "warning", + "level": "note", "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" + "text": "Shadows name 'params' from outer scope", + "markdown": "Shadows name 'params' from outer scope" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/fcn.py", + "uri": "minerva/transforms.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 202, - "startColumn": 26, - "charOffset": 9780, - "charLength": 15, + "startLine": 684, + "startColumn": 13, + "charOffset": 24257, + "charLength": 6, "snippet": { - "text": "\"32\", \"16\", \"8\"" + "text": "params" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 200, + "startLine": 682, "startColumn": 1, - "charOffset": 9695, - "charLength": 179, + "charOffset": 24193, + "charLength": 175, "snippet": { - "text": " in_channel: int = 512,\n n_classes: int = 21,\n variant: Literal[\"32\", \"16\", \"8\"] = \"32\",\n ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)" + "text": " Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n" }, "sourceLanguage": "Python" } @@ -22567,12 +22343,12 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "5b5e41b16a5159a0fe9b280d34b360c02051b9d096ba831c6b6f961a4e2a0b17" + "equalIndicator/v1": "fee3860681fcdc20774c711da4a5c00a144128b6fbd1d3f3cc96af41216afb4a" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", + "ideaSeverity": "WEAK WARNING", + "qodanaSeverity": "Moderate", "tags": [ "Python" ] @@ -22590,26 +22366,26 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/transforms.py", + "uri": "minerva/datasets/factory.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 704, - "startColumn": 53, - "charOffset": 24978, - "charLength": 5, + "startLine": 134, + "startColumn": 41, + "charOffset": 5793, + "charLength": 8, "snippet": { - "text": "False" + "text": "\"params\"" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 702, + "startLine": 132, "startColumn": 1, - "charOffset": 24899, - "charLength": 217, + "charOffset": 5661, + "charLength": 221, "snippet": { - "text": "\ndef make_transformations(\n transform_params: Union[Dict[str, Any], Literal[False]], key: Optional[str] = None\n) -> Optional[Any]:\n \"\"\"Constructs a transform or series of transforms based on parameters provided." + "text": " dataset_class: Callable[..., GeoDataset],\n paths: Union[str, Iterable[str]],\n subdataset_params: Dict[Literal[\"params\"], Dict[str, Any]],\n _transformations: Optional[Any],\n ) -> GeoDataset:" }, "sourceLanguage": "Python" } @@ -22623,9 +22399,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "5c14208f93acb01973367275b33371a643e9a93d4e4c6df1f18a4cd57d9443fb" + "equalIndicator/v1": "11ea8b82ea3e295e1035d00a8abc2ea947c0c1de5462c2ba54a8ff716fb26f4b" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { "ideaSeverity": "WARNING", "qodanaSeverity": "High", @@ -22646,26 +22422,26 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/factory.py", + "uri": "minerva/models/fcn.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 134, - "startColumn": 41, - "charOffset": 5769, - "charLength": 8, + "startLine": 97, + "startColumn": 30, + "charOffset": 4620, + "charLength": 15, "snippet": { - "text": "\"params\"" + "text": "\"32\", \"16\", \"8\"" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 132, + "startLine": 95, "startColumn": 1, - "charOffset": 5660, - "charLength": 198, + "charOffset": 4554, + "charLength": 108, "snippet": { - "text": " dataset_class: Callable[..., GeoDataset],\n root: str,\n subdataset_params: Dict[Literal[\"params\"], Dict[str, Any]],\n _transformations: Optional[Any],\n ) -> GeoDataset:" + "text": "\n backbone_name: str = \"ResNet18\"\n decoder_variant: Literal[\"32\", \"16\", \"8\"] = \"32\"\n\n def __init__(" }, "sourceLanguage": "Python" } @@ -22679,9 +22455,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "cafe7885930cf65d6ac51d77d9620295c32ccaf8f87c71f5f32667d6989a2fa4" + "equalIndicator/v1": "2ed1d866d5dc3cc75fe869d8c8ea49dff49475d2a419726cad763c145bf34970" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { "ideaSeverity": "WARNING", "qodanaSeverity": "High", @@ -22691,37 +22467,37 @@ } }, { - "ruleId": "PyUnboundLocalVariableInspection", + "ruleId": "PyTypeHintsInspection", "kind": "fail", "level": "warning", "message": { - "text": "Local variable 'exit_code' might be referenced before assignment", - "markdown": "Local variable 'exit_code' might be referenced before assignment" + "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", + "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "scripts/MinervaPipe.py", + "uri": "minerva/models/fcn.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 70, - "startColumn": 22, - "charOffset": 2859, - "charLength": 9, + "startLine": 205, + "startColumn": 31, + "charOffset": 9905, + "charLength": 15, "snippet": { - "text": "exit_code" + "text": "\"32\", \"16\", \"8\"" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 68, + "startLine": 203, "startColumn": 1, - "charOffset": 2758, - "charLength": 143, + "charOffset": 9805, + "charLength": 170, "snippet": { - "text": " print(err)\n print(f\"Error in {key} experiment -> ABORT\")\n sys.exit(exit_code) # type: ignore\n\n print(" + "text": " ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)\n self.variant: Literal[\"32\", \"16\", \"8\"] = variant\n\n assert type(self.n_classes) is int" }, "sourceLanguage": "Python" } @@ -22735,7 +22511,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "59d72ba075e94cd3afb2368d96297a36606c76a4537d2a5da1e1385e0efeb9fa" + "equalIndicator/v1": "52dbedae57240155661b7fedbef3b3e41329c899cf5cc6acdc8f005e9b6ba49e" }, "baselineState": "unchanged", "properties": { @@ -22747,37 +22523,37 @@ } }, { - "ruleId": "PyUnusedLocalInspection", + "ruleId": "PyTypeHintsInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" + "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", + "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/models/fcn.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 423, - "startColumn": 5, - "charOffset": 14911, - "charLength": 12, + "startLine": 202, + "startColumn": 26, + "charOffset": 9780, + "charLength": 15, "snippet": { - "text": "package: str" + "text": "\"32\", \"16\", \"8\"" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 421, + "startLine": 200, "startColumn": 1, - "charOffset": 14885, - "charLength": 92, + "charOffset": 9695, + "charLength": 179, "snippet": { - "text": " *,\n name: str,\n package: str,\n) -> Callable[..., Any]:\n ... # pragma: no cover" + "text": " in_channel: int = 512,\n n_classes: int = 21,\n variant: Literal[\"32\", \"16\", \"8\"] = \"32\",\n ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)" }, "sourceLanguage": "Python" } @@ -22791,49 +22567,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "08897f3b549a7430b604b04ef801a48adb9d505f2603dc4ae35e11dcfecc19e1" + "equalIndicator/v1": "5b5e41b16a5159a0fe9b280d34b360c02051b9d096ba831c6b6f961a4e2a0b17" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] } }, { - "ruleId": "PyUnusedLocalInspection", + "ruleId": "PyTypeHintsInspection", "kind": "fail", - "level": "note", + "level": "warning", "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" + "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", + "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/transforms.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 675, - "startColumn": 5, - "charOffset": 21982, - "charLength": 20, + "startLine": 704, + "startColumn": 53, + "charOffset": 24978, + "charLength": 5, "snippet": { - "text": "new_crs: CRS = WGS84" + "text": "False" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 673, + "startLine": 702, "startColumn": 1, - "charOffset": 21936, - "charLength": 141, + "charOffset": 24899, + "charLength": 217, "snippet": { - "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" + "text": "\ndef make_transformations(\n transform_params: Union[Dict[str, Any], Literal[False]], key: Optional[str] = None\n) -> Optional[Any]:\n \"\"\"Constructs a transform or series of transforms based on parameters provided." }, "sourceLanguage": "Python" } @@ -22847,49 +22623,49 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "12345e5bb40db54040ccc0fafcbdea7a40113ad62ad85c8b8bc4e0d6ae03cdf9" + "equalIndicator/v1": "5c14208f93acb01973367275b33371a643e9a93d4e4c6df1f18a4cd57d9443fb" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] } }, { - "ruleId": "PyUnusedLocalInspection", + "ruleId": "PyUnboundLocalVariableInspection", "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" + "level": "warning", + "message": { + "text": "Local variable 'exit_code' might be referenced before assignment", + "markdown": "Local variable 'exit_code' might be referenced before assignment" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "scripts/MinervaPipe.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 461, - "startColumn": 5, - "charOffset": 15449, - "charLength": 12, + "startLine": 70, + "startColumn": 22, + "charOffset": 2859, + "charLength": 9, "snippet": { - "text": "package: str" + "text": "exit_code" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 459, + "startLine": 68, "startColumn": 1, - "charOffset": 15421, - "charLength": 86, + "charOffset": 2758, + "charLength": 143, "snippet": { - "text": " module: str,\n *,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" + "text": " print(err)\n print(f\"Error in {key} experiment -> ABORT\")\n sys.exit(exit_code) # type: ignore\n\n print(" }, "sourceLanguage": "Python" } @@ -22903,12 +22679,12 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "169db06317df3b142d6db176f741bd955038b1fc284434a53840974cbc7d9bdf" + "equalIndicator/v1": "59d72ba075e94cd3afb2368d96297a36606c76a4537d2a5da1e1385e0efeb9fa" }, "baselineState": "unchanged", "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", + "ideaSeverity": "WARNING", + "qodanaSeverity": "High", "tags": [ "Python" ] @@ -22919,8 +22695,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" + "text": "Parameter 'package' value is not used", + "markdown": "Parameter 'package' value is not used" }, "locations": [ { @@ -22930,22 +22706,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 694, + "startLine": 463, "startColumn": 5, - "charOffset": 22354, + "charOffset": 15506, "charLength": 12, "snippet": { - "text": "src_crs: CRS" + "text": "package: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 692, + "startLine": 461, "startColumn": 1, - "charOffset": 22312, - "charLength": 127, + "charOffset": 15478, + "charLength": 86, "snippet": { - "text": " x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" + "text": " module: str,\n *,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -22959,7 +22735,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "177ace0b4eeb8bc971a3f3b7db20d7ad7ad4aa5c02a0863738d8add19601ab69" + "equalIndicator/v1": "0ccb2b1ad737ad1a758e57d541cc964c386f300d3cb018304f0051e581f3a63d" }, "baselineState": "unchanged", "properties": { @@ -22986,9 +22762,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 702, + "startLine": 704, "startColumn": 15, - "charOffset": 22521, + "charOffset": 22594, "charLength": 8, "snippet": { "text": "y: float" @@ -22996,9 +22772,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 700, + "startLine": 702, "startColumn": 1, - "charOffset": 22470, + "charOffset": 22543, "charLength": 149, "snippet": { "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" @@ -23015,7 +22791,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "1964fbcc1e92a75f85e6b8edac24198b02594bf8d14f36c0def06c8d5700725a" + "equalIndicator/v1": "0e6d691a6fcc89de66729c329c83c134a5693f62dddd79e565952d51bb9c6c52" }, "baselineState": "unchanged", "properties": { @@ -23031,8 +22807,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -23042,22 +22818,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 442, + "startLine": 412, "startColumn": 5, - "charOffset": 15178, - "charLength": 9, + "charOffset": 14792, + "charLength": 11, "snippet": { - "text": "name: str" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 440, + "startLine": 410, "startColumn": 1, - "charOffset": 15150, - "charLength": 82, + "charOffset": 14756, + "charLength": 71, "snippet": { - "text": " module: str,\n *,\n name: str,\n package: None,\n) -> Callable[..., Any]:" + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," }, "sourceLanguage": "Python" } @@ -23071,7 +22847,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "1a1eb72170f4297e67fb4e2aeaece20bbd50c6a056c3cd21572dc50d2bd83b50" + "equalIndicator/v1": "25f9601039ddbd9925e1890f8f020fa9da57541f24df7424645dfd44944fb3a6" }, "baselineState": "unchanged", "properties": { @@ -23087,8 +22863,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Parameter 'matrix' value is not used", + "markdown": "Parameter 'matrix' value is not used" }, "locations": [ { @@ -23098,22 +22874,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 410, - "startColumn": 5, - "charOffset": 14735, - "charLength": 11, + "startLine": 1133, + "startColumn": 31, + "charOffset": 38350, + "charLength": 22, "snippet": { - "text": "module: str" + "text": "matrix: Dict[int, int]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 408, + "startLine": 1131, "startColumn": 1, - "charOffset": 14699, - "charLength": 71, + "charOffset": 38290, + "charLength": 134, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," + "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23127,7 +22903,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "28f2ef7f3044326550316ffc24ed35478947235a63c0f248b1f28d2b1e222aae" + "equalIndicator/v1": "2c0301eb97cfa9d99d4574a6dd2bac6f52e5ace5f2f4ade1fdfe86ac64ed16ff" }, "baselineState": "unchanged", "properties": { @@ -23143,33 +22919,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" + "text": "Parameter 'signum' value is not used", + "markdown": "Parameter 'signum' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/utils/runner.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 702, - "startColumn": 39, - "charOffset": 22545, - "charLength": 20, + "startLine": 335, + "startColumn": 21, + "charOffset": 10550, + "charLength": 6, "snippet": { - "text": "new_crs: CRS = WGS84" + "text": "signum" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 700, + "startLine": 333, "startColumn": 1, - "charOffset": 22470, - "charLength": 149, + "charOffset": 10528, + "charLength": 75, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" + "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" }, "sourceLanguage": "Python" } @@ -23183,7 +22959,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "29137c77de8686f0e61553686c3dcae3cfe8dd01aaaaa96c3c839e4b9f0655dd" + "equalIndicator/v1": "32baad8869101a640b5894c953f3344efbcd7fa51518461329717f9aa28d02bb" }, "baselineState": "unchanged", "properties": { @@ -23199,33 +22975,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'params' value is not used", - "markdown": "Parameter 'params' value is not used" + "text": "Parameter 'y' value is not used", + "markdown": "Parameter 'y' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/metrics.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 191, - "startColumn": 9, - "charOffset": 7384, - "charLength": 8, + "startLine": 675, + "startColumn": 5, + "charOffset": 22013, + "charLength": 18, "snippet": { - "text": "**params" + "text": "y: Sequence[float]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 189, + "startLine": 673, "startColumn": 1, - "charOffset": 7293, - "charLength": 156, + "charOffset": 21958, + "charLength": 118, "snippet": { - "text": " data_size: Tuple[int, int, int],\n model_type: str = \"segmentation\",\n **params,\n ) -> None:\n super(SPMetrics, self).__init__(" + "text": "def transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," }, "sourceLanguage": "Python" } @@ -23239,7 +23015,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "2a1e59ff49e63d2d131fc81d22bb52f6fe686f1ce63f874539ece41d93f9e30e" + "equalIndicator/v1": "378efc50864fec16c13df7d0a2f9a5ccdd6bdb21750ed5b75b843ad371926c31" }, "baselineState": "unchanged", "properties": { @@ -23255,33 +23031,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Parameter 'dataset' value is not used", + "markdown": "Parameter 'dataset' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/datasets/paired.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 430, - "startColumn": 5, - "charOffset": 15016, - "charLength": 11, + "startLine": 88, + "startColumn": 24, + "charOffset": 3748, + "charLength": 34, "snippet": { - "text": "module: str" + "text": "dataset: Callable[..., GeoDataset]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 428, + "startLine": 86, "startColumn": 1, - "charOffset": 14980, - "charLength": 71, + "charOffset": 3710, + "charLength": 132, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," + "text": "\n @overload\n def __init__(self, dataset: Callable[..., GeoDataset], *args, **kwargs) -> None:\n ... # pragma: no cover\n" }, "sourceLanguage": "Python" } @@ -23295,7 +23071,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "2a540184ef5f0fca66fe0bf388e2962335826445040d8b8cfddea5bcfc900019" + "equalIndicator/v1": "47bc364dfb4accd24c034021659be26811e1262ebfd7c2a6b1956455712c66f5" }, "baselineState": "unchanged", "properties": { @@ -23311,33 +23087,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Local variable 'auto_norm' value is not used", + "markdown": "Local variable 'auto_norm' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/datasets/factory.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 440, - "startColumn": 5, - "charOffset": 15154, - "charLength": 11, + "startLine": 247, + "startColumn": 21, + "charOffset": 10517, + "charLength": 9, "snippet": { - "text": "module: str" + "text": "auto_norm" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 438, + "startLine": 245, "startColumn": 1, - "charOffset": 15118, - "charLength": 70, + "charOffset": 10454, + "charLength": 158, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," + "text": "\n # Reset back to None.\n auto_norm = None\n else:\n raise TypeError( # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23351,7 +23127,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "2f7675b2b4a00bfa2d385511e0d4bb74b9ee13d8954407ac20485c9e94f58c2f" + "equalIndicator/v1": "4840abd8e2d0d74c9efcab96a0ae80a1ff7baefc5e3c1a965c3422a9fff1e534" }, "baselineState": "unchanged", "properties": { @@ -23367,33 +23143,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'signum' value is not used", - "markdown": "Parameter 'signum' value is not used" + "text": "Parameter 'kwargs' value is not used", + "markdown": "Parameter 'kwargs' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/runner.py", + "uri": "minerva/logger/steplog.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 335, - "startColumn": 21, - "charOffset": 10550, - "charLength": 6, + "startLine": 309, + "startColumn": 9, + "charOffset": 11940, + "charLength": 8, "snippet": { - "text": "signum" + "text": "**kwargs" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 333, + "startLine": 307, "startColumn": 1, - "charOffset": 10528, - "charLength": 75, + "charOffset": 11861, + "charLength": 158, "snippet": { - "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" + "text": " model_type: str = \"\",\n n_classes: Optional[int] = None,\n **kwargs,\n ) -> None:\n super(SupervisedGeoStepLogger, self).__init__(" }, "sourceLanguage": "Python" } @@ -23407,9 +23183,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "32baad8869101a640b5894c953f3344efbcd7fa51518461329717f9aa28d02bb" + "equalIndicator/v1": "48c4e289e3b9406f5eb0bd9991c5f4a1a9e8e8253ac16ce7d4097513fa0a102e" }, - "baselineState": "unchanged", + "baselineState": "new", "properties": { "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate", @@ -23423,33 +23199,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" + "text": "Parameter 'dataset' value is not used", + "markdown": "Parameter 'dataset' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/datasets/paired.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 672, - "startColumn": 5, - "charOffset": 21916, - "charLength": 18, + "startLine": 92, + "startColumn": 24, + "charOffset": 3880, + "charLength": 19, "snippet": { - "text": "x: Sequence[float]" + "text": "dataset: GeoDataset" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 670, + "startLine": 90, "startColumn": 1, - "charOffset": 21875, - "charLength": 102, + "charOffset": 3842, + "charLength": 117, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS," + "text": "\n @overload\n def __init__(self, dataset: GeoDataset, *args, **kwargs) -> None:\n ... # pragma: no cover\n" }, "sourceLanguage": "Python" } @@ -23463,7 +23239,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "41807cef224cfcd757c04dbd2e6d63515b92c877c3662c50a96d10d4e69836cb" + "equalIndicator/v1": "4dbb7b4295b76445852c21652ba823b131eef4603a391deda0c1ce06b14efc54" }, "baselineState": "unchanged", "properties": { @@ -23479,33 +23255,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'dataset' value is not used", - "markdown": "Parameter 'dataset' value is not used" + "text": "Parameter 'kwargs' value is not used", + "markdown": "Parameter 'kwargs' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/paired.py", + "uri": "minerva/modelio.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 88, - "startColumn": 24, - "charOffset": 3748, - "charLength": 34, + "startLine": 191, + "startColumn": 5, + "charOffset": 7713, + "charLength": 8, "snippet": { - "text": "dataset: Callable[..., GeoDataset]" + "text": "**kwargs" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 86, + "startLine": 189, "startColumn": 1, - "charOffset": 3710, - "charLength": 132, + "charOffset": 7636, + "charLength": 271, "snippet": { - "text": "\n @overload\n def __init__(self, dataset: Callable[..., GeoDataset], *args, **kwargs) -> None:\n ... # pragma: no cover\n" + "text": " device: torch.device, # type: ignore[name-defined]\n train: bool,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], None, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a self-supervised Siamese model using :mod:`torchgeo` datasets." }, "sourceLanguage": "Python" } @@ -23519,7 +23295,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "47bc364dfb4accd24c034021659be26811e1262ebfd7c2a6b1956455712c66f5" + "equalIndicator/v1": "4f2f60dbc5f54eec99c2a5c005b0a83bd5dbfea5de68c38aa9830e3ec5a2cfd8" }, "baselineState": "unchanged", "properties": { @@ -23535,8 +23311,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -23546,22 +23322,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 683, + "startLine": 452, "startColumn": 5, - "charOffset": 22145, - "charLength": 8, + "charOffset": 15356, + "charLength": 11, "snippet": { - "text": "y: float" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 681, + "startLine": 450, "startColumn": 1, - "charOffset": 22090, - "charLength": 108, + "charOffset": 15320, + "charLength": 70, "snippet": { - "text": "def transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84," + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," }, "sourceLanguage": "Python" } @@ -23575,7 +23351,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "49e750d84f2299f1739f37bc5508054d7b0b13c583dbf14ed992b9121dd400b7" + "equalIndicator/v1": "5aba4ff84f223fa54030174f2039f4279ea51e6dfa9107ea49c9b1e94178d3bc" }, "baselineState": "unchanged", "properties": { @@ -23591,33 +23367,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" + "text": "Parameter 'frame' value is not used", + "markdown": "Parameter 'frame' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/utils/runner.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 682, - "startColumn": 5, - "charOffset": 22121, - "charLength": 18, + "startLine": 327, + "startColumn": 29, + "charOffset": 10349, + "charLength": 5, "snippet": { - "text": "x: Sequence[float]" + "text": "frame" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 680, + "startLine": 325, "startColumn": 1, - "charOffset": 22080, - "charLength": 92, + "charOffset": 10139, + "charLength": 351, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS," + "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," }, "sourceLanguage": "Python" } @@ -23631,7 +23407,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "4d2c411319f3bca43e3bff5b39bd038b1fc845b88757cd973755cfaaf546e4a4" + "equalIndicator/v1": "5c7339871121f24a4922b8c5b4e3ff15d2357395d48ccd376e5b072b5a637912" }, "baselineState": "unchanged", "properties": { @@ -23647,33 +23423,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'dataset' value is not used", - "markdown": "Parameter 'dataset' value is not used" + "text": "Parameter 'package' value is not used", + "markdown": "Parameter 'package' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/paired.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 92, - "startColumn": 24, - "charOffset": 3880, - "charLength": 19, + "startLine": 435, + "startColumn": 5, + "charOffset": 15113, + "charLength": 13, "snippet": { - "text": "dataset: GeoDataset" + "text": "package: None" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 90, + "startLine": 433, "startColumn": 1, - "charOffset": 3842, - "charLength": 117, + "charOffset": 15086, + "charLength": 86, "snippet": { - "text": "\n @overload\n def __init__(self, dataset: GeoDataset, *args, **kwargs) -> None:\n ... # pragma: no cover\n" + "text": " *,\n name: None,\n package: None,\n) -> ModuleType:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23687,7 +23463,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "4dbb7b4295b76445852c21652ba823b131eef4603a391deda0c1ce06b14efc54" + "equalIndicator/v1": "64e64ee08f93e1d6dc03ae32174accc103bd1a6d8bc834280d08781d1c5844d6" }, "baselineState": "unchanged", "properties": { @@ -23703,8 +23479,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" + "text": "Parameter 'src_crs' value is not used", + "markdown": "Parameter 'src_crs' value is not used" }, "locations": [ { @@ -23714,22 +23490,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 673, + "startLine": 696, "startColumn": 5, - "charOffset": 21940, - "charLength": 18, + "charOffset": 22427, + "charLength": 12, "snippet": { - "text": "y: Sequence[float]" + "text": "src_crs: CRS" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 671, + "startLine": 694, "startColumn": 1, - "charOffset": 21885, - "charLength": 118, + "charOffset": 22385, + "charLength": 127, "snippet": { - "text": "def transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," + "text": " x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" }, "sourceLanguage": "Python" } @@ -23743,7 +23519,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "50f0e3cecc42f0fa8f5146f91f28009cde9004647be7c99a51d13992c7029e9c" + "equalIndicator/v1": "6a4ccae8c4b809a248742941055f326415e5b9091f2ec35d539946359b8d1583" }, "baselineState": "unchanged", "properties": { @@ -23759,33 +23535,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'out_shape' value is not used", - "markdown": "Parameter 'out_shape' value is not used" + "text": "Parameter 'x' value is not used", + "markdown": "Parameter 'x' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/logger.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 578, - "startColumn": 9, - "charOffset": 21577, - "charLength": 43, + "startLine": 694, + "startColumn": 5, + "charOffset": 22389, + "charLength": 8, "snippet": { - "text": "out_shape: Optional[Tuple[int, ...]] = None" + "text": "x: float" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 576, + "startLine": 692, "startColumn": 1, - "charOffset": 21520, - "charLength": 175, + "charOffset": 22348, + "charLength": 92, "snippet": { - "text": " batch_size: int,\n n_samples: int,\n out_shape: Optional[Tuple[int, ...]] = None,\n n_classes: Optional[int] = None,\n record_int: bool = True," + "text": "@overload\ndef transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS," }, "sourceLanguage": "Python" } @@ -23799,7 +23575,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "579bbe583cc35b5ecfc7b527ec95c982d949694c89b58a20f738d1bce084f199" + "equalIndicator/v1": "6bb85e879cb7d60a2ab29a04efbd6c09120fcc354cbe3806eff5db51587b5805" }, "baselineState": "unchanged", "properties": { @@ -23815,33 +23591,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'frame' value is not used", - "markdown": "Parameter 'frame' value is not used" + "text": "Parameter 'new_crs' value is not used", + "markdown": "Parameter 'new_crs' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/runner.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 327, - "startColumn": 29, - "charOffset": 10349, - "charLength": 5, + "startLine": 677, + "startColumn": 5, + "charOffset": 22055, + "charLength": 20, "snippet": { - "text": "frame" + "text": "new_crs: CRS = WGS84" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 325, + "startLine": 675, "startColumn": 1, - "charOffset": 10139, - "charLength": 351, + "charOffset": 22009, + "charLength": 141, "snippet": { - "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," + "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23855,7 +23631,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "5c7339871121f24a4922b8c5b4e3ff15d2357395d48ccd376e5b072b5a637912" + "equalIndicator/v1": "6d5f1aafce9ce228179668bc91ba7209fe1876a8e6ff85defe0262939f2ea8fc" }, "baselineState": "unchanged", "properties": { @@ -23871,8 +23647,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'matrix' value is not used", - "markdown": "Parameter 'matrix' value is not used" + "text": "Parameter 'new_crs' value is not used", + "markdown": "Parameter 'new_crs' value is not used" }, "locations": [ { @@ -23882,22 +23658,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1137, + "startLine": 704, "startColumn": 39, - "charOffset": 38402, - "charLength": 22, + "charOffset": 22618, + "charLength": 20, "snippet": { - "text": "matrix: Dict[int, int]" + "text": "new_crs: CRS = WGS84" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1135, + "startLine": 702, "startColumn": 1, - "charOffset": 38353, - "charLength": 116, + "charOffset": 22543, + "charLength": 149, "snippet": { - "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" + "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23911,7 +23687,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "60393490cf6d01fc23bc1fa780104309fcdcc0cd5e2158d7aa1d4da31e7fb9ac" + "equalIndicator/v1": "786127917f20d41dcba824f94644007d75294845ce04d30ec72a139f746583b1" }, "baselineState": "unchanged", "properties": { @@ -23927,33 +23703,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'n_classes' value is not used", - "markdown": "Parameter 'n_classes' value is not used" + "text": "Parameter 'package' value is not used", + "markdown": "Parameter 'package' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/logger.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 579, - "startColumn": 9, - "charOffset": 21630, - "charLength": 31, + "startLine": 425, + "startColumn": 5, + "charOffset": 14968, + "charLength": 12, "snippet": { - "text": "n_classes: Optional[int] = None" + "text": "package: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 577, + "startLine": 423, "startColumn": 1, - "charOffset": 21545, - "charLength": 186, + "charOffset": 14942, + "charLength": 92, "snippet": { - "text": " n_samples: int,\n out_shape: Optional[Tuple[int, ...]] = None,\n n_classes: Optional[int] = None,\n record_int: bool = True,\n record_float: bool = False," + "text": " *,\n name: str,\n package: str,\n) -> Callable[..., Any]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -23967,7 +23743,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "609a2e6e067a490100796650665caccb040abb9544bdbdf613d6d312d08d6b40" + "equalIndicator/v1": "7cab6aa90bcc70bffd0fbc103039845e944e948b238656f65792d6666ee38fa0" }, "baselineState": "unchanged", "properties": { @@ -23983,8 +23759,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -23994,22 +23770,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 693, + "startLine": 461, "startColumn": 5, - "charOffset": 22330, - "charLength": 18, + "charOffset": 15482, + "charLength": 11, "snippet": { - "text": "y: Sequence[float]" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 691, + "startLine": 459, "startColumn": 1, - "charOffset": 22285, - "charLength": 108, + "charOffset": 15446, + "charLength": 73, "snippet": { - "text": "def transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n package: str," }, "sourceLanguage": "Python" } @@ -24023,7 +23799,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "662cfcf7d8fc299207fb143d40552d472ff8fbbdd2c07b868118fbbd6310332a" + "equalIndicator/v1": "7e08346269a9a6f80d28500b3907d0c8c1f42af9ea787557d4554e7ae9aa7a22" }, "baselineState": "unchanged", "properties": { @@ -24039,8 +23815,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -24050,22 +23826,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 695, + "startLine": 432, "startColumn": 5, - "charOffset": 22372, - "charLength": 20, + "charOffset": 15073, + "charLength": 11, "snippet": { - "text": "new_crs: CRS = WGS84" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 693, + "startLine": 430, "startColumn": 1, - "charOffset": 22326, - "charLength": 141, + "charOffset": 15037, + "charLength": 71, "snippet": { - "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," }, "sourceLanguage": "Python" } @@ -24079,7 +23855,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "694a68ccc02b6e12182a111406bc67dfa95067c13caddf289d9a228ee13cc72f" + "equalIndicator/v1": "7ecf619bafd6e12ee257c28bfceb77e07d3124647dec0022081b57262419975b" }, "baselineState": "unchanged", "properties": { @@ -24095,8 +23871,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" + "text": "Parameter 'name' value is not used", + "markdown": "Parameter 'name' value is not used" }, "locations": [ { @@ -24106,22 +23882,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 413, + "startLine": 434, "startColumn": 5, - "charOffset": 14775, - "charLength": 12, + "charOffset": 15097, + "charLength": 10, "snippet": { - "text": "package: str" + "text": "name: None" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 411, + "startLine": 432, "startColumn": 1, - "charOffset": 14748, - "charLength": 85, + "charOffset": 15069, + "charLength": 75, "snippet": { - "text": " *,\n name: None,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" + "text": " module: str,\n *,\n name: None,\n package: None,\n) -> ModuleType:" }, "sourceLanguage": "Python" } @@ -24135,7 +23911,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6bf602e814f4cf9db879530d46f003212e139f4f1193cf2d76d986b4930504d6" + "equalIndicator/v1": "85cb9a5f41c2c05067d30c19294bb17c22a4ce96cc3f9221ae0fe0b16fa2a0cc" }, "baselineState": "unchanged", "properties": { @@ -24151,8 +23927,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -24162,22 +23938,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 674, + "startLine": 422, "startColumn": 5, - "charOffset": 21964, - "charLength": 12, + "charOffset": 14929, + "charLength": 11, "snippet": { - "text": "src_crs: CRS" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 672, + "startLine": 420, "startColumn": 1, - "charOffset": 21912, - "charLength": 137, + "charOffset": 14893, + "charLength": 70, "snippet": { - "text": " x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," }, "sourceLanguage": "Python" } @@ -24191,7 +23967,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6d53523e58e964dad3ef7eda320861a9255602bda287c485016e487361b4d89d" + "equalIndicator/v1": "8a686852cb451c1739e933ccc39d7c61a5c1da48ef83544d116dc9574e999033" }, "baselineState": "unchanged", "properties": { @@ -24207,33 +23983,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Parameter 'signum' value is not used", + "markdown": "Parameter 'signum' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/utils/runner.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 420, - "startColumn": 5, - "charOffset": 14872, - "charLength": 11, + "startLine": 327, + "startColumn": 21, + "charOffset": 10341, + "charLength": 6, "snippet": { - "text": "module: str" + "text": "signum" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 418, + "startLine": 325, "startColumn": 1, - "charOffset": 14836, - "charLength": 70, + "charOffset": 10139, + "charLength": 351, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," + "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," }, "sourceLanguage": "Python" } @@ -24247,7 +24023,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6d788da92648a1d3a532700c27260a52c4cc22781a588e70ae51e24cf1444849" + "equalIndicator/v1": "8add16ba65f135bd2af3a910af293b125373b67d97709a4db09b45bb17a9efce" }, "baselineState": "unchanged", "properties": { @@ -24263,33 +24039,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'kwargs' value is not used", - "markdown": "Parameter 'kwargs' value is not used" + "text": "Local variable 'weights' value is not used", + "markdown": "Local variable 'weights' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/modelio.py", + "uri": "minerva/models/core.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 201, + "startLine": 410, "startColumn": 5, - "charOffset": 7865, - "charLength": 8, + "charOffset": 15448, + "charLength": 7, "snippet": { - "text": "**kwargs" + "text": "weights" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 199, + "startLine": 408, "startColumn": 1, - "charOffset": 7790, - "charLength": 269, + "charOffset": 15317, + "charLength": 261, "snippet": { - "text": " device: torch.device, # type: ignore[name-defined]\n mode: str,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], None, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a self-supervised Siamese model using :mod:`torchgeo` datasets." + "text": " :meth:`~torchvision.models._api.WeightsEnum.get_state_dict` to download the weights (if not already in cache).\n \"\"\"\n weights: Optional[WeightsEnum] = None\n try:\n weights = torch.hub.load(\"pytorch/vision\", \"get_weight\", name=weights_name)" }, "sourceLanguage": "Python" } @@ -24303,7 +24079,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6f64be3164ef33853170ef48c3dc2920a182113862d9184a41b47070107614af" + "equalIndicator/v1": "9e026761be74f2e19e5bc01b1b687b5e85b4c6764f9bed0c686eb9df81c080e6" }, "baselineState": "unchanged", "properties": { @@ -24319,33 +24095,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Local variable 'weights' value is not used", - "markdown": "Local variable 'weights' value is not used" + "text": "Parameter 'kwargs' value is not used", + "markdown": "Parameter 'kwargs' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/core.py", + "uri": "minerva/modelio.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 401, + "startLine": 61, "startColumn": 5, - "charOffset": 15168, - "charLength": 7, + "charOffset": 2784, + "charLength": 8, "snippet": { - "text": "weights" + "text": "**kwargs" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 399, + "startLine": 59, "startColumn": 1, - "charOffset": 15037, - "charLength": 261, + "charOffset": 2707, + "charLength": 260, "snippet": { - "text": " :meth:`~torchvision.models._api.WeightsEnum.get_state_dict` to download the weights (if not already in cache).\n \"\"\"\n weights: Optional[WeightsEnum] = None\n try:\n weights = torch.hub.load(\"pytorch/vision\", \"get_weight\", name=weights_name)" + "text": " device: torch.device, # type: ignore[name-defined]\n train: bool,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], Tensor, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a supervised model using :mod:`torchgeo` datasets." }, "sourceLanguage": "Python" } @@ -24359,7 +24135,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6ffe476c63ecd80ead735039841b639a2b95ab65eec89b59d2f3589e7e375f9c" + "equalIndicator/v1": "a0c91bcdf4f3702bccef1c710b61a66f3ee5375d230aff5117e4d8e97a25a84a" }, "baselineState": "unchanged", "properties": { @@ -24386,9 +24162,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 452, + "startLine": 454, "startColumn": 5, - "charOffset": 15323, + "charOffset": 15380, "charLength": 9, "snippet": { "text": "name: str" @@ -24396,9 +24172,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 450, + "startLine": 452, "startColumn": 1, - "charOffset": 15295, + "charOffset": 15352, "charLength": 91, "snippet": { "text": " module: str,\n *,\n name: str,\n) -> Callable[..., Any]:\n ... # pragma: no cover" @@ -24415,7 +24191,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "73007e3d0e1ccd730c81edc048ccc048e7ebf710eaaac2c187582160cc46d52a" + "equalIndicator/v1": "a548ae33426bea46235ff7f5a73418dbc2c9284d10ce4de5509d4efdd757ddd3" }, "baselineState": "unchanged", "properties": { @@ -24431,8 +24207,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" + "text": "Parameter 'name' value is not used", + "markdown": "Parameter 'name' value is not used" }, "locations": [ { @@ -24442,22 +24218,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 685, + "startLine": 444, "startColumn": 5, - "charOffset": 22177, - "charLength": 20, + "charOffset": 15235, + "charLength": 9, "snippet": { - "text": "new_crs: CRS = WGS84" + "text": "name: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 683, + "startLine": 442, "startColumn": 1, - "charOffset": 22141, - "charLength": 131, + "charOffset": 15207, + "charLength": 82, "snippet": { - "text": " y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" + "text": " module: str,\n *,\n name: str,\n package: None,\n) -> Callable[..., Any]:" }, "sourceLanguage": "Python" } @@ -24471,7 +24247,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "79b89d0ac18d10275a875af00922265d5c0c969757a828de7ca5e3981c82e265" + "equalIndicator/v1": "a83b11a3bab18108d41eab9010628a01f46a4845c006af930bdf803b5743a9d8" }, "baselineState": "unchanged", "properties": { @@ -24498,9 +24274,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 702, - "startColumn": 25, - "charOffset": 22531, + "startLine": 686, + "startColumn": 5, + "charOffset": 22232, "charLength": 12, "snippet": { "text": "src_crs: CRS" @@ -24508,12 +24284,12 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 700, + "startLine": 684, "startColumn": 1, - "charOffset": 22470, - "charLength": 149, + "charOffset": 22190, + "charLength": 127, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" + "text": " x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" }, "sourceLanguage": "Python" } @@ -24527,7 +24303,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "7e77d4199c85a1cdc08a93e247fb3b593b33f73d3e6b6b90e129e87a166c43d8" + "equalIndicator/v1": "aa450f73f32b590538897e881ae65fb2cca39a91f2d0bf197ff975eddfb2c919" }, "baselineState": "unchanged", "properties": { @@ -24543,33 +24319,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" + "text": "Parameter 'frame' value is not used", + "markdown": "Parameter 'frame' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/utils.py", + "uri": "minerva/utils/runner.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 702, - "startColumn": 5, - "charOffset": 22511, - "charLength": 8, + "startLine": 335, + "startColumn": 29, + "charOffset": 10558, + "charLength": 5, "snippet": { - "text": "x: float" + "text": "frame" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 700, + "startLine": 333, "startColumn": 1, - "charOffset": 22470, - "charLength": 149, + "charOffset": 10528, + "charLength": 75, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" + "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" }, "sourceLanguage": "Python" } @@ -24583,7 +24359,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "80cef2bce48d56630ad58749c7e129b28a77d0adc747f5801c90dc91a5515d42" + "equalIndicator/v1": "aac2d2995f82d30eceaaf4fdc987bcf42180f54116528d862084b4b6e065026c" }, "baselineState": "unchanged", "properties": { @@ -24599,33 +24375,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'signum' value is not used", - "markdown": "Parameter 'signum' value is not used" + "text": "Parameter 'y' value is not used", + "markdown": "Parameter 'y' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/runner.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 327, - "startColumn": 21, - "charOffset": 10341, - "charLength": 6, + "startLine": 695, + "startColumn": 5, + "charOffset": 22403, + "charLength": 18, "snippet": { - "text": "signum" + "text": "y: Sequence[float]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 325, + "startLine": 693, "startColumn": 1, - "charOffset": 10139, - "charLength": 351, + "charOffset": 22358, + "charLength": 108, "snippet": { - "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," + "text": "def transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," }, "sourceLanguage": "Python" } @@ -24639,7 +24415,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "8add16ba65f135bd2af3a910af293b125373b67d97709a4db09b45bb17a9efce" + "equalIndicator/v1": "af0e634ac1edfffe767615c2dd7397f4860f73adb7173e6992aa3cc89b33e635" }, "baselineState": "unchanged", "properties": { @@ -24655,33 +24431,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'params' value is not used", - "markdown": "Parameter 'params' value is not used" + "text": "Parameter 'y' value is not used", + "markdown": "Parameter 'y' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/metrics.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 287, - "startColumn": 9, - "charOffset": 10877, + "startLine": 685, + "startColumn": 5, + "charOffset": 22218, "charLength": 8, "snippet": { - "text": "**params" + "text": "y: float" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 285, + "startLine": 683, "startColumn": 1, - "charOffset": 10791, - "charLength": 152, + "charOffset": 22163, + "charLength": 108, "snippet": { - "text": " model_type: str = \"segmentation\",\n sample_pairs: bool = False,\n **params,\n ) -> None:\n super(SSLMetrics, self).__init__(" + "text": "def transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84," }, "sourceLanguage": "Python" } @@ -24695,7 +24471,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "9a146f37a59a5277080fdad354108fc52056a950c87e69e7fd06625acacf6e91" + "equalIndicator/v1": "b118ec1d809147828b5577498d5200f9457b7148502a603aa5b6f32b721bb7f2" }, "baselineState": "unchanged", "properties": { @@ -24711,8 +24487,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Parameter 'new_crs' value is not used", + "markdown": "Parameter 'new_crs' value is not used" }, "locations": [ { @@ -24722,22 +24498,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 450, + "startLine": 687, "startColumn": 5, - "charOffset": 15299, - "charLength": 11, + "charOffset": 22250, + "charLength": 20, "snippet": { - "text": "module: str" + "text": "new_crs: CRS = WGS84" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 448, + "startLine": 685, "startColumn": 1, - "charOffset": 15263, - "charLength": 70, + "charOffset": 22214, + "charLength": 131, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," + "text": " y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -24751,7 +24527,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "9a649544c05610b6e5e8d69473154d4f209472049f1f19f4aff8307a4e22b3cc" + "equalIndicator/v1": "b26014ed1202aeb4cb4c62f63adc833bc07058f9547863429b4c19ce8f28d9dd" }, "baselineState": "unchanged", "properties": { @@ -24767,8 +24543,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" + "text": "Parameter 'src_crs' value is not used", + "markdown": "Parameter 'src_crs' value is not used" }, "locations": [ { @@ -24778,22 +24554,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 422, + "startLine": 676, "startColumn": 5, - "charOffset": 14896, - "charLength": 9, + "charOffset": 22037, + "charLength": 12, "snippet": { - "text": "name: str" + "text": "src_crs: CRS" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 420, + "startLine": 674, "startColumn": 1, - "charOffset": 14868, - "charLength": 81, + "charOffset": 21985, + "charLength": 137, "snippet": { - "text": " module: str,\n *,\n name: str,\n package: str,\n) -> Callable[..., Any]:" + "text": " x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" }, "sourceLanguage": "Python" } @@ -24807,7 +24583,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "a659d8c2b94e47465b57135e636980024cdca4153faf387defa4359de0bd4626" + "equalIndicator/v1": "b577bce01690db5f522ed23e521b31264aa8ce1b7017842fb92a5d6d69187309" }, "baselineState": "unchanged", "properties": { @@ -24823,33 +24599,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'frame' value is not used", - "markdown": "Parameter 'frame' value is not used" + "text": "Parameter 'matrix' value is not used", + "markdown": "Parameter 'matrix' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/runner.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 335, - "startColumn": 29, - "charOffset": 10558, - "charLength": 5, + "startLine": 1139, + "startColumn": 39, + "charOffset": 38475, + "charLength": 22, "snippet": { - "text": "frame" + "text": "matrix: Dict[int, int]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 333, + "startLine": 1137, "startColumn": 1, - "charOffset": 10528, - "charLength": 75, + "charOffset": 38426, + "charLength": 116, "snippet": { - "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" + "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" }, "sourceLanguage": "Python" } @@ -24863,7 +24639,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "aac2d2995f82d30eceaaf4fdc987bcf42180f54116528d862084b4b6e065026c" + "equalIndicator/v1": "b86ca79c588e33e10834bcabf19dad1d48702078ec339d918fa72f67054b9b00" }, "baselineState": "unchanged", "properties": { @@ -24879,8 +24655,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" + "text": "Parameter 'module' value is not used", + "markdown": "Parameter 'module' value is not used" }, "locations": [ { @@ -24890,22 +24666,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 692, + "startLine": 442, "startColumn": 5, - "charOffset": 22316, - "charLength": 8, + "charOffset": 15211, + "charLength": 11, "snippet": { - "text": "x: float" + "text": "module: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 690, + "startLine": 440, "startColumn": 1, - "charOffset": 22275, - "charLength": 92, + "charOffset": 15175, + "charLength": 70, "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS," + "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," }, "sourceLanguage": "Python" } @@ -24919,7 +24695,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ab35331e62db5cda26d2a43c10efcd94b5097118b39db292ae6e963a9e259d8c" + "equalIndicator/v1": "b8c0735d7a73f2f52fb58c58561c19d7bedcc10bc205009f8560f27522edbed6" }, "baselineState": "unchanged", "properties": { @@ -24935,8 +24711,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" + "text": "Parameter 'name' value is not used", + "markdown": "Parameter 'name' value is not used" }, "locations": [ { @@ -24946,22 +24722,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 684, + "startLine": 424, "startColumn": 5, - "charOffset": 22159, - "charLength": 12, + "charOffset": 14953, + "charLength": 9, "snippet": { - "text": "src_crs: CRS" + "text": "name: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 682, + "startLine": 422, "startColumn": 1, - "charOffset": 22117, - "charLength": 127, + "charOffset": 14925, + "charLength": 81, "snippet": { - "text": " x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" + "text": " module: str,\n *,\n name: str,\n package: str,\n) -> Callable[..., Any]:" }, "sourceLanguage": "Python" } @@ -24975,7 +24751,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "b3bddd4f6fd48c2af5a39d0afcf0e6ce30717d2ed97ba3e552d65135703bce1e" + "equalIndicator/v1": "c3c9bca9d8a2a236385bce82494a4d9ececc296c46a83681e867653e0fa2d2d3" }, "baselineState": "unchanged", "properties": { @@ -24991,33 +24767,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Local variable 'auto_norm' value is not used", - "markdown": "Local variable 'auto_norm' value is not used" + "text": "Parameter 'new_crs' value is not used", + "markdown": "Parameter 'new_crs' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/factory.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 245, - "startColumn": 21, - "charOffset": 10484, - "charLength": 9, + "startLine": 697, + "startColumn": 5, + "charOffset": 22445, + "charLength": 20, "snippet": { - "text": "auto_norm" + "text": "new_crs: CRS = WGS84" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 243, + "startLine": 695, "startColumn": 1, - "charOffset": 10421, - "charLength": 158, + "charOffset": 22399, + "charLength": 141, "snippet": { - "text": "\n # Reset back to None.\n auto_norm = None\n else:\n raise TypeError( # pragma: no cover" + "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25031,9 +24807,9 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "b52fdcf3026983bc5183d48fc6dedd39a73c0af9ea7dd83a1d4a8e0525b64cec" + "equalIndicator/v1": "dd749fc39b4e3f4355f3b0b3e77e7dbf05735bb21a0d1b6fc102220760c5a6c9" }, - "baselineState": "new", + "baselineState": "unchanged", "properties": { "ideaSeverity": "WEAK WARNING", "qodanaSeverity": "Moderate", @@ -25047,8 +24823,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" + "text": "Parameter 'name' value is not used", + "markdown": "Parameter 'name' value is not used" }, "locations": [ { @@ -25058,22 +24834,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 433, + "startLine": 414, "startColumn": 5, - "charOffset": 15056, - "charLength": 13, + "charOffset": 14816, + "charLength": 10, "snippet": { - "text": "package: None" + "text": "name: None" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 431, + "startLine": 412, "startColumn": 1, - "charOffset": 15029, - "charLength": 86, + "charOffset": 14788, + "charLength": 74, "snippet": { - "text": " *,\n name: None,\n package: None,\n) -> ModuleType:\n ... # pragma: no cover" + "text": " module: str,\n *,\n name: None,\n package: str,\n) -> ModuleType:" }, "sourceLanguage": "Python" } @@ -25087,7 +24863,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "cbd6b524381e14f028d4f9da50e232cf048cdfdf35fa1e90d1ddfca4884b1808" + "equalIndicator/v1": "df2541a088a6fbc804c8254ef2696dcbba28bb4ccd938552c25289fe6c8f825a" }, "baselineState": "unchanged", "properties": { @@ -25103,8 +24879,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'matrix' value is not used", - "markdown": "Parameter 'matrix' value is not used" + "text": "Parameter 'src_crs' value is not used", + "markdown": "Parameter 'src_crs' value is not used" }, "locations": [ { @@ -25114,22 +24890,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1131, - "startColumn": 31, - "charOffset": 38277, - "charLength": 22, + "startLine": 704, + "startColumn": 25, + "charOffset": 22604, + "charLength": 12, "snippet": { - "text": "matrix: Dict[int, int]" + "text": "src_crs: CRS" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1129, + "startLine": 702, "startColumn": 1, - "charOffset": 38217, - "charLength": 134, + "charOffset": 22543, + "charLength": 149, "snippet": { - "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" + "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25143,7 +24919,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ce505d52473aa630478758857431f435946e3cf57cf8f278ff17fa3524e380f9" + "equalIndicator/v1": "e4bc34f0ae2bf9fe1a5a2b83bbab61fd3c30dbe93397efd612fdde9299b609d8" }, "baselineState": "unchanged", "properties": { @@ -25159,8 +24935,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'array' value is not used", - "markdown": "Parameter 'array' value is not used" + "text": "Parameter 'package' value is not used", + "markdown": "Parameter 'package' value is not used" }, "locations": [ { @@ -25170,22 +24946,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1131, + "startLine": 445, "startColumn": 5, - "charOffset": 38251, - "charLength": 24, + "charOffset": 15250, + "charLength": 13, "snippet": { - "text": "array: NDArray[Any, Int]" + "text": "package: None" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1129, + "startLine": 443, "startColumn": 1, - "charOffset": 38217, - "charLength": 134, + "charOffset": 15224, + "charLength": 93, "snippet": { - "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" + "text": " *,\n name: str,\n package: None,\n) -> Callable[..., Any]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25199,7 +24975,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "cf35c4f0a60b78cca8b6434c9b3b4e73a6c625bc275c572237da143b1188b9a6" + "equalIndicator/v1": "e732c0177eb72bea99131b565c9d4cad8309cc57ede7e421db666e551eb62d13" }, "baselineState": "unchanged", "properties": { @@ -25215,8 +24991,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" + "text": "Parameter 'array' value is not used", + "markdown": "Parameter 'array' value is not used" }, "locations": [ { @@ -25226,22 +25002,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 412, - "startColumn": 5, - "charOffset": 14759, - "charLength": 10, + "startLine": 1139, + "startColumn": 20, + "charOffset": 38456, + "charLength": 17, "snippet": { - "text": "name: None" + "text": "array: LongTensor" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 410, + "startLine": 1137, "startColumn": 1, - "charOffset": 14731, - "charLength": 74, + "charOffset": 38426, + "charLength": 116, "snippet": { - "text": " module: str,\n *,\n name: None,\n package: str,\n) -> ModuleType:" + "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" }, "sourceLanguage": "Python" } @@ -25255,7 +25031,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "d62608e64a953a5a8ce65c40b9c506666eda359d7a18ae916dc8aef56d6832c8" + "equalIndicator/v1": "e7b5cecf2d3557712dbe2b5787dc4c9520d2860c143458550263a68cfe27f3c7" }, "baselineState": "unchanged", "properties": { @@ -25271,33 +25047,33 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'kwargs' value is not used", - "markdown": "Parameter 'kwargs' value is not used" + "text": "Parameter 'x' value is not used", + "markdown": "Parameter 'x' value is not used" }, "locations": [ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/modelio.py", + "uri": "minerva/utils/utils.py", "uriBaseId": "SRCROOT" }, "region": { - "startLine": 61, + "startLine": 704, "startColumn": 5, - "charOffset": 2782, + "charOffset": 22584, "charLength": 8, "snippet": { - "text": "**kwargs" + "text": "x: float" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 59, + "startLine": 702, "startColumn": 1, - "charOffset": 2707, - "charLength": 258, + "charOffset": 22543, + "charLength": 149, "snippet": { - "text": " device: torch.device, # type: ignore[name-defined]\n mode: str,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], Tensor, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a supervised model using :mod:`torchgeo` datasets." + "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25311,7 +25087,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "df52fbc1d0954e470ffec6689e3cf29b24767bd1b4212aa40a4734005d539cae" + "equalIndicator/v1": "ed2df92b1da501c28d0aace7fadd5d3c3a6593d93977e6333ce6c377545bbc87" }, "baselineState": "unchanged", "properties": { @@ -25327,8 +25103,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" + "text": "Parameter 'array' value is not used", + "markdown": "Parameter 'array' value is not used" }, "locations": [ { @@ -25338,22 +25114,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 443, + "startLine": 1133, "startColumn": 5, - "charOffset": 15193, - "charLength": 13, + "charOffset": 38324, + "charLength": 24, "snippet": { - "text": "package: None" + "text": "array: NDArray[Any, Int]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 441, + "startLine": 1131, "startColumn": 1, - "charOffset": 15167, - "charLength": 93, + "charOffset": 38290, + "charLength": 134, "snippet": { - "text": " *,\n name: str,\n package: None,\n) -> Callable[..., Any]:\n ... # pragma: no cover" + "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25367,7 +25143,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "e1e0cd4c4ddd2c06f506f0436e1d19d1b01342995ae0f5d597fcabcb059e4a03" + "equalIndicator/v1": "efa3c5fd8da16b2c8b794c8033ebb3602585732758cd8f67c42f2e90a826708c" }, "baselineState": "unchanged", "properties": { @@ -25383,8 +25159,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" + "text": "Parameter 'package' value is not used", + "markdown": "Parameter 'package' value is not used" }, "locations": [ { @@ -25394,22 +25170,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 432, + "startLine": 415, "startColumn": 5, - "charOffset": 15040, - "charLength": 10, + "charOffset": 14832, + "charLength": 12, "snippet": { - "text": "name: None" + "text": "package: str" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 430, + "startLine": 413, "startColumn": 1, - "charOffset": 15012, - "charLength": 75, + "charOffset": 14805, + "charLength": 85, "snippet": { - "text": " module: str,\n *,\n name: None,\n package: None,\n) -> ModuleType:" + "text": " *,\n name: None,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" }, "sourceLanguage": "Python" } @@ -25423,7 +25199,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ec912aec7e48142ae5dee57f34eb546b857eb1e54e52a4bd2412e9e12c339eaf" + "equalIndicator/v1": "f7d794e4a4f3e2d8cd92c3ca2137781714e71604d396464db16d7dfc0843690f" }, "baselineState": "unchanged", "properties": { @@ -25439,8 +25215,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" + "text": "Parameter 'x' value is not used", + "markdown": "Parameter 'x' value is not used" }, "locations": [ { @@ -25450,22 +25226,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 459, + "startLine": 684, "startColumn": 5, - "charOffset": 15425, - "charLength": 11, + "charOffset": 22194, + "charLength": 18, "snippet": { - "text": "module: str" + "text": "x: Sequence[float]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 457, + "startLine": 682, "startColumn": 1, - "charOffset": 15389, - "charLength": 73, + "charOffset": 22153, + "charLength": 92, "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n package: str," + "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS," }, "sourceLanguage": "Python" } @@ -25479,7 +25255,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "fefbb316ee2a47b8507c4ea452e8b44c33d275692a4987ec9c16e2b4fbe85c7d" + "equalIndicator/v1": "f83215cf4705664e835d8d9fde8ae1284013127cfebaef1990341b6fed675bb4" }, "baselineState": "unchanged", "properties": { @@ -25495,8 +25271,8 @@ "kind": "fail", "level": "note", "message": { - "text": "Parameter 'array' value is not used", - "markdown": "Parameter 'array' value is not used" + "text": "Parameter 'x' value is not used", + "markdown": "Parameter 'x' value is not used" }, "locations": [ { @@ -25506,22 +25282,22 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1137, - "startColumn": 20, - "charOffset": 38383, - "charLength": 17, + "startLine": 674, + "startColumn": 5, + "charOffset": 21989, + "charLength": 18, "snippet": { - "text": "array: LongTensor" + "text": "x: Sequence[float]" }, "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1135, + "startLine": 672, "startColumn": 1, - "charOffset": 38353, - "charLength": 116, + "charOffset": 21948, + "charLength": 102, "snippet": { - "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" + "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS," }, "sourceLanguage": "Python" } @@ -25535,7 +25311,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ff40646ba7f92fa771bd73cf020a02f83fd8062daecadec23c35fc5cdb5b28f4" + "equalIndicator/v1": "f9a05a4244e1f0d968ad07f3fb3e2c2fd2d73392a80bf588249185bd133e879d" }, "baselineState": "unchanged", "properties": { @@ -25548,8 +25324,8 @@ } ], "automationDetails": { - "id": "project/qodana/2023-09-07", - "guid": "13a1380d-4823-4b73-9ace-ff74068ba5aa", + "id": "project/qodana/2023-10-15", + "guid": "8bb680b6-435c-4c0d-8314-313e1ae2ab67", "properties": { "jobUrl": "" } @@ -25572,16 +25348,68 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/samplers.py", + "uri": "notebooks/Torchgeo_FCN_Demo.ipynb", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 17, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "{\n \"cells\": [\n {" + }, + "sourceLanguage": "JupyterPython" + }, + "contextRegion": { + "startLine": 1, + "startColumn": 1, + "charOffset": 0, + "charLength": 67, + "snippet": { + "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," + }, + "sourceLanguage": "Jupyter" + } + }, + "logicalLocations": [ + { + "fullyQualifiedName": "project", + "kind": "module" + } + ] + } + ], + "partialFingerprints": { + "equalIndicator/v1": "042d0651789556a4ea7954680e6f2953e047138ee0cd895e14a63ebd2306efc5" + }, + "properties": { + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" + } + }, + { + "ruleId": "PyInterpreterInspection", + "kind": "fail", + "level": "warning", + "message": { + "text": "No Python interpreter configured for the project", + "markdown": "No Python interpreter configured for the project" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "scripts/TorchWeightDownloader.py", + "uriBaseId": "SRCROOT" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "charOffset": 0, + "charLength": 78, + "snippet": { + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -25589,9 +25417,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -25605,7 +25433,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "21a8dfca3a662b90fc821d542fdfa1717fd334d9857bf32942b5e8bddf58ef0a" + "equalIndicator/v1": "0a3de853e0b5c7ff5bc742bb39b847b3f81db91742115c1cd17a7f7f06668232" }, "properties": { "ideaSeverity": "WARNING", @@ -25624,16 +25452,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/__depreciated.py", + "uri": "scripts/RunTensorBoard.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 78, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -25641,9 +25469,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -25657,7 +25485,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "2c14dddaa90c405bb8f79b5496b28864da5661f78649df81d2fb105baada4e21" + "equalIndicator/v1": "275a608e61e946495fd6a91fac263e8fb5ab62b79bb09ceab7753567f758c08e" }, "properties": { "ideaSeverity": "WARNING", @@ -25676,16 +25504,68 @@ { "physicalLocation": { "artifactLocation": { - "uri": "docs/conf.py", + "uri": "notebooks/Visualise_Siamese_Pair.ipynb", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 84, + "charLength": 17, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#" + "text": "{\n \"cells\": [\n {" + }, + "sourceLanguage": "JupyterPython" + }, + "contextRegion": { + "startLine": 1, + "startColumn": 1, + "charOffset": 0, + "charLength": 67, + "snippet": { + "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," + }, + "sourceLanguage": "Jupyter" + } + }, + "logicalLocations": [ + { + "fullyQualifiedName": "project", + "kind": "module" + } + ] + } + ], + "partialFingerprints": { + "equalIndicator/v1": "2ae4fb3229bfe29d8f9ca86cf390e91e296eaafbd8b0d50dd49e0d5c34afcf44" + }, + "properties": { + "ideaSeverity": "WARNING", + "qodanaSeverity": "High" + } + }, + { + "ruleId": "PyInterpreterInspection", + "kind": "fail", + "level": "warning", + "message": { + "text": "No Python interpreter configured for the project", + "markdown": "No Python interpreter configured for the project" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "scripts/ManifestMake.py", + "uriBaseId": "SRCROOT" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "charOffset": 0, + "charLength": 78, + "snippet": { + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -25693,9 +25573,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 191, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -25709,7 +25589,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "4c9a5c329324331f237c44237a2a87856dcefc34a00a7ad7152d3c2995c37219" + "equalIndicator/v1": "3ae834c0f52337350db07c7a74ad5da1d5b21891dbb86af7b4e8f24d10e7b3ba" }, "properties": { "ideaSeverity": "WARNING", @@ -25728,16 +25608,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "setup.py", + "uri": "docs/conf.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 53, + "charLength": 84, "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n" + "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#" }, "sourceLanguage": "Python" }, @@ -25745,9 +25625,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 92, + "charLength": 191, "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n\nif __name__ == \"__main__\":\n setup()" + "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:" }, "sourceLanguage": "Python" } @@ -25761,7 +25641,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "532128b27875bd9e13d222179b2cc5ba0d2e7c00d65e3993dbff3dd845d66acd" + "equalIndicator/v1": "4c9a5c329324331f237c44237a2a87856dcefc34a00a7ad7152d3c2995c37219" }, "properties": { "ideaSeverity": "WARNING", @@ -25780,16 +25660,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/runner.py", + "uri": "setup.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 61, + "charLength": 53, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK\n# MIT License" + "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n" }, "sourceLanguage": "Python" }, @@ -25797,9 +25677,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 95, + "charLength": 92, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK\n# MIT License\n\n# Copyright (c) 2023 Harry Baker" + "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n\nif __name__ == \"__main__\":\n setup()" }, "sourceLanguage": "Python" } @@ -25813,7 +25693,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "6653938c0fef6b11aa6eec10598d918a31e9e37a3ddf9d7ab07717aa7b7a4605" + "equalIndicator/v1": "532128b27875bd9e13d222179b2cc5ba0d2e7c00d65e3993dbff3dd845d66acd" }, "properties": { "ideaSeverity": "WARNING", @@ -25988,28 +25868,28 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/pytorchtools.py", + "uri": "notebooks/SSL4EO-S12_Demo.ipynb", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 39, + "charLength": 17, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#" + "text": "{\n \"cells\": [\n {" }, - "sourceLanguage": "Python" + "sourceLanguage": "JupyterPython" }, "contextRegion": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 81, + "charLength": 67, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#\n# Copyright (c) 2018 Bjarte Mehus Sunde\n#" + "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," }, - "sourceLanguage": "Python" + "sourceLanguage": "Jupyter" } }, "logicalLocations": [ @@ -26021,7 +25901,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "93c6dddb1802b35907705fd939a3882bfbd0df1d59574f856753c7fabd95adc8" + "equalIndicator/v1": "91720f3562a83119f396cd420ad41fe69fcb6764c4491a09d2ccf33d686654d8" }, "properties": { "ideaSeverity": "WARNING", @@ -26040,16 +25920,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/factory.py", + "uri": "minerva/pytorchtools.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 39, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "# -*- coding: utf-8 -*-\n# MIT License\n#" }, "sourceLanguage": "Python" }, @@ -26057,9 +25937,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 81, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "# -*- coding: utf-8 -*-\n# MIT License\n#\n# Copyright (c) 2018 Bjarte Mehus Sunde\n#" }, "sourceLanguage": "Python" } @@ -26073,7 +25953,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "95509029289675caa1dc8c93178b9c69e0d1e7d1cbe4ff7ca8bf0780daa847a3" + "equalIndicator/v1": "93c6dddb1802b35907705fd939a3882bfbd0df1d59574f856753c7fabd95adc8" }, "properties": { "ideaSeverity": "WARNING", @@ -26092,28 +25972,28 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/__init__.py", + "uri": "notebooks/Torchgeo_FCN_Full.ipynb", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 58, + "charLength": 17, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#" + "text": "{\n \"cells\": [\n {" }, - "sourceLanguage": "Python" + "sourceLanguage": "JupyterPython" }, "contextRegion": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 207, + "charLength": 67, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by" + "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," }, - "sourceLanguage": "Python" + "sourceLanguage": "Jupyter" } }, "logicalLocations": [ @@ -26125,7 +26005,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "a86c36d3707e420ba84dfb38ea35c8895859297d4539216a10698d11b48c82fc" + "equalIndicator/v1": "a2bda517bc615db1d93069b7d2262eb029e6650b9255bc2510f45773bd4b649e" }, "properties": { "ideaSeverity": "WARNING", @@ -26144,28 +26024,28 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/modelio.py", + "uri": "notebooks/Torchgeo_FCN_Small.ipynb", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 17, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "{\n \"cells\": [\n {" }, - "sourceLanguage": "Python" + "sourceLanguage": "JupyterPython" }, "contextRegion": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 67, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," }, - "sourceLanguage": "Python" + "sourceLanguage": "Jupyter" } }, "logicalLocations": [ @@ -26177,7 +26057,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "b55c874b3a0c1de1318842d131dfe67f77ae4edd4113c9e56f4831f58e9cb214" + "equalIndicator/v1": "a35f92fcab4e87a6115924ef87387c657cf8a527096c85f3a01b2553b3f8358e" }, "properties": { "ideaSeverity": "WARNING", @@ -26196,16 +26076,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/__init__.py", + "uri": "minerva/__init__.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 58, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#" }, "sourceLanguage": "Python" }, @@ -26213,9 +26093,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 207, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by" }, "sourceLanguage": "Python" } @@ -26229,7 +26109,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "b63a7f23434063cf31df35f36e1a5f936e2ecc9a7e40f1501c9d333e85ad00d6" + "equalIndicator/v1": "a86c36d3707e420ba84dfb38ea35c8895859297d4539216a10698d11b48c82fc" }, "properties": { "ideaSeverity": "WARNING", @@ -26248,7 +26128,7 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/__init__.py", + "uri": "minerva/utils/__init__.py", "uriBaseId": "SRCROOT" }, "region": { @@ -26281,7 +26161,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ba6b058b5f2efdab64de212ecf163255f812d4e70344a49b19d81d1f04c899d3" + "equalIndicator/v1": "b63a7f23434063cf31df35f36e1a5f936e2ecc9a7e40f1501c9d333e85ad00d6" }, "properties": { "ideaSeverity": "WARNING", @@ -26300,7 +26180,7 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/naip.py", + "uri": "minerva/datasets/__init__.py", "uriBaseId": "SRCROOT" }, "region": { @@ -26333,7 +26213,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "bcf537e802048819675f876b2873c91c01a50358a619720d70d9a7475656e963" + "equalIndicator/v1": "ba6b058b5f2efdab64de212ecf163255f812d4e70344a49b19d81d1f04c899d3" }, "properties": { "ideaSeverity": "WARNING", @@ -26352,16 +26232,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/models/__init__.py", + "uri": "minerva/datasets/naip.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 58, + "charLength": 38, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License" + "text": "# -*- coding: utf-8 -*-\n# MIT License\n" }, "sourceLanguage": "Python" }, @@ -26369,9 +26249,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 92, + "charLength": 72, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License\n\n# Copyright (c) 2023 Harry Baker" + "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" }, "sourceLanguage": "Python" } @@ -26385,7 +26265,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "c3450498e9c4c0c21cdaf8b368061f090414e65a54abd9cb664548176ab80ed5" + "equalIndicator/v1": "bcf537e802048819675f876b2873c91c01a50358a619720d70d9a7475656e963" }, "properties": { "ideaSeverity": "WARNING", @@ -26404,16 +26284,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/optimisers.py", + "uri": "minerva/models/__init__.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 39, + "charLength": 58, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#" + "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License" }, "sourceLanguage": "Python" }, @@ -26421,9 +26301,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 75, + "charLength": 92, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#\n# Copyright (c) 2018 Noah Golmant\n#" + "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License\n\n# Copyright (c) 2023 Harry Baker" }, "sourceLanguage": "Python" } @@ -26437,7 +26317,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "cff37df1d81e0a73435a82c6845b999632c73655c7562b047c4e2d9155b5568c" + "equalIndicator/v1": "c3450498e9c4c0c21cdaf8b368061f090414e65a54abd9cb664548176ab80ed5" }, "properties": { "ideaSeverity": "WARNING", @@ -26456,16 +26336,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/utils/config_load.py", + "uri": "scripts/MinervaClusterVis.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 78, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -26473,9 +26353,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -26489,7 +26369,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "d2f7f4464dd6b8a593e436f83a243acb73b83d9f0f9487445b2132c9d2033257" + "equalIndicator/v1": "c67085784466323080e7db9beb01a6febb849bf5f17e4d7d936ea0843417c844" }, "properties": { "ideaSeverity": "WARNING", @@ -26508,16 +26388,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/collators.py", + "uri": "scripts/MinervaExp.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 69, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK" }, "sourceLanguage": "Python" }, @@ -26525,9 +26405,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 104, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK\n# Copyright (C) 2023 Harry Baker\n#" }, "sourceLanguage": "Python" } @@ -26541,7 +26421,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "d6853b942787181db7e74c95139dc4f9f7710979e7d7e6dc06f7761d5149e28c" + "equalIndicator/v1": "e7021da7e88face1abf929abb6d68772cb18a9187ad786891cac1dcfba950ba0" }, "properties": { "ideaSeverity": "WARNING", @@ -26560,16 +26440,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/metrics.py", + "uri": "scripts/Torch_to_ONNX.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 38, + "charLength": 78, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -26577,9 +26457,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 72, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -26593,7 +26473,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "f48495ce36b2ddf551aa4536cefd96fcf7ed420279e00575869068fb712d9c2f" + "equalIndicator/v1": "e806b5be98f83b1cfc62b6344f0234545c7220ecafec96e4508ea9b234f34a3f" }, "properties": { "ideaSeverity": "WARNING", @@ -26664,16 +26544,16 @@ { "physicalLocation": { "artifactLocation": { - "uri": "minerva/datasets/dfc.py", + "uri": "scripts/MinervaPipe.py", "uriBaseId": "SRCROOT" }, "region": { "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 59, + "charLength": 78, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" }, "sourceLanguage": "Python" }, @@ -26681,9 +26561,9 @@ "startLine": 1, "startColumn": 1, "charOffset": 0, - "charLength": 201, + "charLength": 151, "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by" + "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" }, "sourceLanguage": "Python" } @@ -26697,7 +26577,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "fd7ab2e5d0e2a3c1ee07fa827b6d4ea624023ff983fedf77dd0921a8bc677ccf" + "equalIndicator/v1": "ff77cc71e33e8107b09b009c8082ed560773ce32f8bee6920e7baa7fb4685d7c" }, "properties": { "ideaSeverity": "WARNING", @@ -27344,9 +27224,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 812, + "startLine": 814, "startColumn": 52, - "charOffset": 26507, + "charOffset": 26580, "charLength": 1, "snippet": { "text": "\"" @@ -27354,9 +27234,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 810, + "startLine": 812, "startColumn": 1, - "charOffset": 26442, + "charOffset": 26515, "charLength": 130, "snippet": { "text": "\ndef dec2deg(\n dec_co: Union[Sequence[float], NDArray[Shape[\"*\"], Float]], # noqa: F722\n axis: str = \"lat\",\n) -> List[str]:" @@ -27373,7 +27253,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "34eb8e26831add120298b7a42e12a22cdd6dcab7092186c015d81bd416e9e08c" + "equalIndicator/v1": "6d46cca07310dce9ac011497d3c5c8a3e436ca3a687aa5cc1778202518c2cd6e" }, "properties": { "ideaSeverity": "ERROR", @@ -27396,9 +27276,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1515, - "startColumn": 22, - "charOffset": 52002, + "startLine": 814, + "startColumn": 52, + "charOffset": 26580, "charLength": 1, "snippet": { "text": "\"" @@ -27406,12 +27286,12 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1513, + "startLine": 812, "startColumn": 1, - "charOffset": 51919, - "charLength": 162, + "charOffset": 26515, + "charLength": 130, "snippet": { - "text": "def batch_flatten(\n x: Union[NDArray[Any, Any], ArrayLike]\n) -> NDArray[Shape[\"*\"], Any]: # noqa: F722\n \"\"\"Flattens the supplied array with :func:`numpy`.\n" + "text": "\ndef dec2deg(\n dec_co: Union[Sequence[float], NDArray[Shape[\"*\"], Float]], # noqa: F722\n axis: str = \"lat\",\n) -> List[str]:" }, "sourceLanguage": "Python" } @@ -27425,7 +27305,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "ad46d634b17bf64d78a263fd9e3671e651028a75496ded23c989a869dbee02cb" + "equalIndicator/v1": "761fcc5ea04ad71ea6b166762d2ffe3344f30fa99d8a376d72b806815434c18b" }, "properties": { "ideaSeverity": "ERROR", @@ -27437,8 +27317,8 @@ "kind": "fail", "level": "error", "message": { - "text": "Statement expected, found Py:MULT", - "markdown": "Statement expected, found Py:MULT" + "text": "Expression expected", + "markdown": "Expression expected" }, "locations": [ { @@ -27448,9 +27328,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 812, - "startColumn": 52, - "charOffset": 26507, + "startLine": 1517, + "startColumn": 22, + "charOffset": 52075, "charLength": 1, "snippet": { "text": "\"" @@ -27458,12 +27338,12 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 810, + "startLine": 1515, "startColumn": 1, - "charOffset": 26442, - "charLength": 130, + "charOffset": 51992, + "charLength": 162, "snippet": { - "text": "\ndef dec2deg(\n dec_co: Union[Sequence[float], NDArray[Shape[\"*\"], Float]], # noqa: F722\n axis: str = \"lat\",\n) -> List[str]:" + "text": "def batch_flatten(\n x: Union[NDArray[Any, Any], ArrayLike]\n) -> NDArray[Shape[\"*\"], Any]: # noqa: F722\n \"\"\"Flattens the supplied array with :func:`numpy`.\n" }, "sourceLanguage": "Python" } @@ -27477,7 +27357,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "c140f73149ebb4797a9b9a5acb5995a944fe7257ab14678e5837599791822df2" + "equalIndicator/v1": "79698a3050691a6a73104160fac2b6a73d5afa38b25ab8d34a6157eed482186f" }, "properties": { "ideaSeverity": "ERROR", @@ -27489,8 +27369,8 @@ "kind": "fail", "level": "error", "message": { - "text": "Expression expected", - "markdown": "Expression expected" + "text": "Statement expected, found Py:MULT", + "markdown": "Statement expected, found Py:MULT" }, "locations": [ { @@ -27500,9 +27380,9 @@ "uriBaseId": "SRCROOT" }, "region": { - "startLine": 1515, + "startLine": 1517, "startColumn": 22, - "charOffset": 52002, + "charOffset": 52075, "charLength": 1, "snippet": { "text": "\"" @@ -27510,9 +27390,9 @@ "sourceLanguage": "Python" }, "contextRegion": { - "startLine": 1513, + "startLine": 1515, "startColumn": 1, - "charOffset": 51919, + "charOffset": 51992, "charLength": 162, "snippet": { "text": "def batch_flatten(\n x: Union[NDArray[Any, Any], ArrayLike]\n) -> NDArray[Shape[\"*\"], Any]: # noqa: F722\n \"\"\"Flattens the supplied array with :func:`numpy`.\n" @@ -27529,7 +27409,7 @@ } ], "partialFingerprints": { - "equalIndicator/v1": "c5234dcb27adddbdabcf138551dd9ac049859f4d63d9319007d49d1ac5540e65" + "equalIndicator/v1": "8ba55c5a2d3af846d67abc6bd7cee1883a83e0d753fca74ab2599ffb5a13970a" }, "properties": { "ideaSeverity": "ERROR", From e23f10ca0d74da61b119315ea129c4d88283b48d Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 16 Oct 2023 02:18:19 +0100 Subject: [PATCH 113/136] Move backbone extraction to `TSNEVis` --- minerva/tasks/tsne.py | 7 ++++++- tests/test_trainer.py | 2 -- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 679f3be03..2e3b5fa3b 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -75,9 +75,14 @@ def __init__( record_float: bool = False, **params, ) -> None: + backbone = model.get_backbone() # type: ignore[assignment, operator] + + # Set dummy optimiser. It won't be used as this is a test. + backbone.set_optimser(torch.optim.SGD(backbone.parameters(), lr=1.0e-3)) + super().__init__( name, - model, + backbone, device, exp_fn, gpu, diff --git a/tests/test_trainer.py b/tests/test_trainer.py index be9ebe2fe..934c7c633 100644 --- a/tests/test_trainer.py +++ b/tests/test_trainer.py @@ -181,8 +181,6 @@ def test_trainer_4( trainer.fit() if kwargs.get("tsne_cluster"): - trainer.model = trainer.model.get_backbone() # type: ignore[assignment, operator] - trainer.tsne_cluster("test-test") if kwargs.get("test"): From 09f43f1da83489db9598d1664823cdf281fe3a53 Mon Sep 17 00:00:00 2001 From: Harry Baker Date: Mon, 16 Oct 2023 02:38:35 +0100 Subject: [PATCH 114/136] Correct syntax error --- minerva/tasks/tsne.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index 2e3b5fa3b..f54fc99e6 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -78,7 +78,7 @@ def __init__( backbone = model.get_backbone() # type: ignore[assignment, operator] # Set dummy optimiser. It won't be used as this is a test. - backbone.set_optimser(torch.optim.SGD(backbone.parameters(), lr=1.0e-3)) + backbone.set_optimiser(torch.optim.SGD(backbone.parameters(), lr=1.0e-3)) super().__init__( name, From f42ccd3c44ac70034662ac18b17692f5189fbb7c Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 16 Oct 2023 18:56:45 +0100 Subject: [PATCH 115/136] Use `forward` rather than `step` --- minerva/tasks/tsne.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minerva/tasks/tsne.py b/minerva/tasks/tsne.py index f54fc99e6..47d572529 100644 --- a/minerva/tasks/tsne.py +++ b/minerva/tasks/tsne.py @@ -107,7 +107,7 @@ def step(self) -> None: self.model.eval() # Pass the batch of data through the model to get the embeddings. - embeddings: Tensor = self.model.step(data["image"].to(self.device))[0] + embeddings: Tensor = self.model.forward(data["image"].to(self.device))[0] # Flatten embeddings. embeddings = embeddings.flatten(start_dim=1) From 9d5f65bf50d5708766a308028c361d93e81177e2 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 23 Oct 2023 17:48:56 +0100 Subject: [PATCH 116/136] Remove duplicate calls to `calc_metrics` --- minerva/tasks/epoch.py | 3 --- minerva/tasks/knn.py | 3 --- 2 files changed, 6 deletions(-) diff --git a/minerva/tasks/epoch.py b/minerva/tasks/epoch.py index db0ccaba9..0e6198db6 100644 --- a/minerva/tasks/epoch.py +++ b/minerva/tasks/epoch.py @@ -95,9 +95,6 @@ def step(self) -> None: if self.gpu == 0: bar() # type: ignore - # Updates metrics with epoch results. - self.logger.calc_metrics() - # If configured to do so, calculates the grad norms. if self.params.get("calc_norm", False): _ = utils.calc_grad(self.model) diff --git a/minerva/tasks/knn.py b/minerva/tasks/knn.py index 942a7846b..cb2cea5ed 100644 --- a/minerva/tasks/knn.py +++ b/minerva/tasks/knn.py @@ -304,6 +304,3 @@ def step(self) -> None: # Update global step number for this mode of model fitting. self.step_num += 1 - - # Updates metrics with epoch results. - self.logger.calc_metrics() From 69c91c2c17de221bfffc93bcb6f4eabb93a5ada6 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 23 Oct 2023 17:49:35 +0100 Subject: [PATCH 117/136] Added `log_null` so that val logs same length as train --- minerva/logger/tasklog.py | 9 +++++++++ minerva/tasks/core.py | 12 ++++++++++++ minerva/trainer.py | 1 + 3 files changed, 22 insertions(+) diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index cc100ee76..8da116c24 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -249,6 +249,15 @@ def get_results(self) -> Dict[str, Any]: """ return self.step_logger.get_results + def log_null(self) -> None: + """Log :attr:`numpy.NAN` for this epoch. + + Useful for logging null when a validation epoch was skipped so that + the length of the logs remains the same as the training logs. + """ + for metric in self.metrics.keys(): + self.metrics[metric]["y"].append(np.NAN) + def get_sub_metrics( self, pattern: Tuple[str, ...] = ("train", "val") ) -> Dict[str, Any]: diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 66d332f54..ee2adf166 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -358,6 +358,18 @@ def get_logs(self) -> Dict[str, Any]: def get_metrics(self) -> Dict[str, Any]: return self.logger.get_metrics + def log_null(self, epoch_no: int) -> None: + """Log :attr:`numpy.NAN` for this epoch. + + Useful for logging null when a validation epoch was skipped so that + the length of the logs remains the same as the training logs. + + Args: + epoch_no (int): Epoch number. + """ + self.logger.log_null() + self.logger.log_epoch_number(epoch_no) + def print_epoch_results(self, epoch_no: int) -> None: self.logger.print_epoch_results(epoch_no) diff --git a/minerva/trainer.py b/minerva/trainer.py index 5b4a4694a..67c030f83 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -550,6 +550,7 @@ def fit(self) -> None: utils.check_substrings_in_string(mode, "val") and (epoch + 1) % self.val_freq != 0 ): + tasks[mode].log_null(epoch) break if tasks[mode].train: From 92b2b68c2b0c8ad738f67fe02efaf34abb3d83a9 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 23 Oct 2023 18:33:21 +0100 Subject: [PATCH 118/136] `log_epoch_number` no longer abstract --- minerva/logger/tasklog.py | 28 ++-------------------------- minerva/trainer.py | 6 +++--- tests/test_logging.py | 16 ++++++++-------- 3 files changed, 13 insertions(+), 37 deletions(-) diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index 8da116c24..1e1fef825 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -209,14 +209,14 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: """ pass # pragma: no cover - @abc.abstractmethod def log_epoch_number(self, epoch_no: int) -> None: """Logs the epoch number to ``metrics``. Args: epoch_no (int): Epoch number to log. """ - pass # pragma: no cover + for metric in self.metrics.keys(): + self.metrics[metric]["x"].append(epoch_no) @property def get_metrics(self) -> Dict[str, Any]: @@ -363,16 +363,6 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: logs["total_correct"] / self.n_samples ) - def log_epoch_number(self, epoch_no: int) -> None: - """Logs the epoch number to ``metrics``. - - Args: - epoch_no (int): Epoch number to log. - """ - self.metrics[f"{self.task_name}_loss"]["x"].append(epoch_no + 1) - self.metrics[f"{self.task_name}_acc"]["x"].append(epoch_no + 1) - self.metrics[f"{self.task_name}_miou"]["x"].append(epoch_no + 1) - def print_epoch_results(self, epoch_no: int) -> None: """Prints the results from an epoch to ``stdout``. @@ -491,20 +481,6 @@ def _calc_metrics(self, logs: Dict[str, Any]) -> None: logs["euc_dist"] / self.n_batches ) - def log_epoch_number(self, epoch_no: int) -> None: - """Logs the epoch number to ``metrics``. - - Args: - epoch_no (int): Epoch number to log. - """ - self.metrics[f"{self.task_name}_loss"]["x"].append(epoch_no + 1) - self.metrics[f"{self.task_name}_acc"]["x"].append(epoch_no + 1) - self.metrics[f"{self.task_name}_top5_acc"]["x"].append(epoch_no + 1) - - if self.sample_pairs: - self.metrics[f"{self.task_name}_collapse_level"]["x"].append(epoch_no + 1) - self.metrics[f"{self.task_name}_euc_dist"]["x"].append(epoch_no + 1) - def print_epoch_results(self, epoch_no: int) -> None: """Prints the results from an epoch to ``stdout``. diff --git a/minerva/trainer.py b/minerva/trainer.py index 67c030f83..741ac3622 100644 --- a/minerva/trainer.py +++ b/minerva/trainer.py @@ -645,13 +645,13 @@ def test(self, save: bool = True, show: bool = False) -> None: # Runs test epoch on model, returning the predicted labels, ground truth labels supplied # and the IDs of the samples supplied. - results = task(1) + results = task(0) assert results is not None if self.gpu == 0: # Print epoch results. - task.print_epoch_results(1) + task.print_epoch_results(0) # Creates a classification report from the results of the task. if "z" in results and "y" in results: @@ -729,7 +729,7 @@ def tsne_cluster(self, task_name: str = "TSNEVis") -> None: **self.params, ) - task(1) + task(0) def close(self) -> None: """Closes the experiment, saving experiment parameters and model to file.""" diff --git a/tests/test_logging.py b/tests/test_logging.py index a9c9532e9..27b8b4ec4 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -175,10 +175,10 @@ def test_SupervisedGeoStepLogger( assert_array_equal(results["y"], y) - correct_loss["x"].append(epoch_no + 1) + correct_loss["x"].append(epoch_no) correct_loss["y"].append(logs["total_loss"] / std_n_batches) - correct_acc["x"].append(epoch_no + 1) + correct_acc["x"].append(epoch_no) if utils.check_substrings_in_string(model_type, "segmentation"): correct_acc["y"].append( logs["total_correct"] @@ -190,7 +190,7 @@ def test_SupervisedGeoStepLogger( ) if utils.check_substrings_in_string(model_type, "segmentation"): - correct_miou["x"].append(epoch_no + 1) + correct_miou["x"].append(epoch_no) correct_miou["y"].append( logs["total_miou"] / (std_n_batches * std_batch_size) ) @@ -300,9 +300,9 @@ def test_SSLStepLogger( results = logger.get_results assert results == {} - correct_loss["x"].append(epoch_no + 1) - correct_acc["x"].append(epoch_no + 1) - correct_top5["x"].append(epoch_no + 1) + correct_loss["x"].append(epoch_no) + correct_acc["x"].append(epoch_no) + correct_top5["x"].append(epoch_no) correct_loss["y"].append(logs["total_loss"] / std_n_batches) @@ -325,8 +325,8 @@ def test_SSLStepLogger( ) if extra_metrics: - correct_collapse_level["x"].append(epoch_no + 1) - correct_euc_dist["x"].append(epoch_no + 1) + correct_collapse_level["x"].append(epoch_no) + correct_euc_dist["x"].append(epoch_no) correct_collapse_level["y"].append(logs["collapse_level"]) correct_euc_dist["y"].append(logs["euc_dist"] / std_n_batches) From 591997b8450c90ec9b9631785948b50bbdda132f Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 23 Oct 2023 19:11:19 +0100 Subject: [PATCH 119/136] Move logging epoch number into `calc_metrics` --- minerva/logger/tasklog.py | 9 +++++++-- minerva/tasks/core.py | 5 +---- tests/test_logging.py | 6 ++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/minerva/logger/tasklog.py b/minerva/logger/tasklog.py index 1e1fef825..dc5804e01 100644 --- a/minerva/logger/tasklog.py +++ b/minerva/logger/tasklog.py @@ -194,9 +194,14 @@ def step( **kwargs, ) - def calc_metrics(self) -> None: - """Updates metrics with epoch results.""" + def calc_metrics(self, epoch_no: int) -> None: + """Updates metrics with epoch results. + + Args: + epoch_no (int): Epoch number to log. + """ self._calc_metrics(self.step_logger.get_logs) + self.log_epoch_number(epoch_no) @abc.abstractmethod def _calc_metrics(self, logs: Dict[str, Any]) -> None: diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index ee2adf166..663fbb807 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -333,10 +333,7 @@ def _generic_step(self, epoch_no: int) -> Optional[Dict[str, Any]]: self.step() # Send the logs to the metric logger. - self.logger.calc_metrics() - - # Add epoch number to metrics. - self.logger.log_epoch_number(epoch_no) + self.logger.calc_metrics(epoch_no) if self.record_int or self.record_float: results = self.logger.get_results diff --git a/tests/test_logging.py b/tests/test_logging.py index 27b8b4ec4..af4f3ad6c 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -195,8 +195,7 @@ def test_SupervisedGeoStepLogger( logs["total_miou"] / (std_n_batches * std_batch_size) ) - logger.calc_metrics() - logger.log_epoch_number(epoch_no) + logger.calc_metrics(epoch_no) logger.print_epoch_results(epoch_no) metrics = logger.get_metrics @@ -330,8 +329,7 @@ def test_SSLStepLogger( correct_collapse_level["y"].append(logs["collapse_level"]) correct_euc_dist["y"].append(logs["euc_dist"] / std_n_batches) - logger.calc_metrics() - logger.log_epoch_number(epoch_no) + logger.calc_metrics(epoch_no) logger.print_epoch_results(epoch_no) metrics = logger.get_metrics From 0e2b03bda234e86d9987748275f859330d0e9184 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 24 Oct 2023 15:24:38 +0100 Subject: [PATCH 120/136] Update requirements --- requirements/requirements.txt | 18 +++++++++--------- requirements/requirements_dev.txt | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 0f002a2dd..079df3631 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,29 +1,29 @@ alive_progress==3.1.4 -argcomplete==3.1.1 +argcomplete==3.1.2 catalyst==22.4 fastapi>=0.101.0 fiona>=1.9.1 geopy==2.4.0 GitPython>=3.1.35 -imageio==2.31.3 +imageio==2.31.6 inputimeout==1.0.4 ipykernel==6.25.2 lightly==1.4.21 matplotlib==3.7.2 -mlflow==2.6.0 +mlflow==2.7.1 nptyping==2.5.0 numba>=0.57.0 # not directly required but pinned to ensure Python 3.11 compatibility. -numpy==1.24.3 +numpy==1.26.1 onnx==1.14.1 -onnx2torch==1.5.11 +onnx2torch==1.5.12 overload==1.1 pandas==2.1.1 protobuf>=3.19.5 # not directly required, pinned by Snyk to avoid a vulnerability. -psutil==5.9.5 +psutil==5.9.6 pyyaml==6.0.1 rasterio>=1.3.6 requests==2.31.0 -scikit-learn==1.3.1 +scikit-learn==1.3.2 segmentation-models-pytorch==0.3.3 setuptools==68.2.2 starlette==0.31.1 # not directly required, pinned by Dependabot to avoid a vulnerability. @@ -34,8 +34,8 @@ torchgeo==0.5.0 torchinfo==1.8.0 tornado>=6.3.3 tqdm==4.66.1 -types-PyYAML==6.0.12.11 -types-requests==2.31.0.8 +types-PyYAML==6.0.12.12 +types-requests==2.31.0.10 types-tabulate==0.9.0.3 wandb==0.15.10 Werkzeug>=2.2.3 # Patches a potential security vulnerability. diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index 3cbc6630b..ba4db62eb 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -1,5 +1,5 @@ alive_progress==3.1.4 -argcomplete==3.1.1 +argcomplete==3.1.2 catalyst==22.4 certifi>=2022.12.7 # not directly required, pinned by Snyk to avoid a vulnerability. fastapi>=0.101.0 @@ -7,25 +7,25 @@ fiona>=1.9.1 flake8==6.1.0 geopy==2.4.0 GitPython>=3.1.35 -imageio==2.31.3 +imageio==2.31.6 inputimeout==1.0.4 internet-sabotage3==0.1.6 ipykernel==6.25.2 lightly==1.4.21 matplotlib==3.7.2 -mlflow==2.6.0 +mlflow==2.7.1 mypy==1.5.1 myst_parser==2.0.0 nptyping==2.5.0 numba>=0.57.0 # not directly required but pinned to ensure Python 3.11 compatibility. -numpy==1.24.3 +numpy==1.26.1 onnx==1.14.1 -onnx2torch==1.5.11 +onnx2torch==1.5.12 overload==1.1 pandas==2.1.1 -pre-commit==3.4.0 +pre-commit==3.5.0 protobuf>=3.19.5 # not directly required, pinned by Snyk to avoid a vulnerability. -psutil==5.9.5 +psutil==5.9.6 pygments>=2.7.4 # not directly required, pinned by Snyk to avoid a vulnerability. pytest==7.4.2 pytest-cov==4.1.0 @@ -33,7 +33,7 @@ pytest-lazy-fixture==0.6.3 pyyaml==6.0.1 rasterio>=1.3.6 requests==2.31.0 -scikit-learn==1.3.1 +scikit-learn==1.3.2 segmentation-models-pytorch==0.3.3 setuptools==68.2.2 sphinx==7.2.6 @@ -47,8 +47,8 @@ torchinfo==1.8.0 tornado>=6.3.3 tox==4.11.3 tqdm==4.66.1 -types-PyYAML==6.0.12.11 -types-requests==2.31.0.8 +types-PyYAML==6.0.12.12 +types-requests==2.31.0.10 types-tabulate==0.9.0.3 wandb==0.15.10 Werkzeug>=2.2.3 # Patches a potential security vulnerability. From 051fee42a3389eb0a04680a5f9f22a1e00415044 Mon Sep 17 00:00:00 2001 From: Harry Date: Tue, 24 Oct 2023 19:25:02 +0100 Subject: [PATCH 121/136] Updated documentation --- minerva/tasks/core.py | 56 ++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 663fbb807..857ffe1e9 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -69,16 +69,15 @@ class MinervaTask(ABC): """An abstract definition of a task to fit or evalulate a model within :mod:`minerva`. Attributes: + name (str): The name of the task. params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be constructed, trained and evaluated. These should be defined via config ``YAML`` files. model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. - batch_size (int): Size of each batch of samples supplied to the model. loaders (dict[str, ~torch.utils.data.DataLoader]): :class:`dict` containing :class:`~torch.utils.data.DataLoader` (s) for each dataset. n_batches (dict[str, int]): Dictionary of the number of batches to supply to the model for train, validation and testing. - metrics (dict[str, ~typing.Any]): Dictionary to hold the loss and accuracy results from training, - validation and testing. + batch_size (int): Number of samples in each batch. device: The CUDA device on which to fit the model. verbose (bool): Provides more prints to stdout if ``True``. class_dist (~typing.Any): Distribution of classes within the data. @@ -86,29 +85,39 @@ class MinervaTask(ABC): modes (tuple[str, ...]): The different *modes* of fitting in this experiment specified by the config. writer (~torch.utils.tensorboard.writer.SummaryWriter | ~wandb.sdk.wandb_run.Run | None): The *writer* to perform logging for this experiment. For use with either :mod:`tensorboard` or :mod:`wandb`. - stopper (~pytorchtools.EarlyStopping | None): Early stopping function. - early_stop (bool): Whether early stopping has been triggered. Will end model training if ``True``. n_samples (dict[str, int]): Number of samples in each mode of model fitting. - metric_logger (~logger.MinervaLogger): Object to calculate and log metrics to track the performance + logger (~logger.MinervaTaskLogger): Object to calculate and log metrics to track the performance of the model. modelio_func (~typing.Callable[..., ~typing.Any]): Function to handle the input/ output to the model. - steps (dict[str, int]): :class:`dict` to hold the global step number for each mode of model fitting. + step_num (int): Holds the step number for this task. model_type (str): Type of the model that determines how to handle IO, metric calculations etc. + record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. + record_float (bool): Store the floating point results of each epoch in memory + such as the raw predicted probabilities. Args: + name (str): The name of the task. Should match the key for the task + in the ``tasks`` dictionary of the experiment params. model (MinervaModel): Model to be fitted of a class contained within :mod:`~minerva.models`. - batch_size (int): Number of samples in each batch. device: The CUDA device on which to fit the model. + exp_fn (~pathlib.Path): The path to the parent directory for the results of the experiment. + gpu (int): Optional; CUDA GPU device number. For use in distributed computing. Defaults to ``0``. rank (int): Optional; The rank of this process across all devices in the distributed run. world_size (int): Optional; The total number of processes across the distributed run. writer (~wandb.sdk.wandb_run.Run | RunDisabled): Optional; Run object for Weights and Biases. params (dict[str, ~typing.Any]): Dictionary describing all the parameters that define how the model will be constructed, trained and evaluated. These should be defined via config ``YAML`` files. + record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. + record_float (bool): Store the floating point results of each epoch in memory + such as the raw predicted probabilities. Keyword Args: elim (bool): Will eliminate classes that have no samples in and reorder the class labels so they still run from ``0`` to ``n-1`` classes where ``n`` is the reduced number of classes. :mod:`minerva` ensures that labels are converted between the old and new schemes seamlessly. + balance (bool): Activates class balancing. For ``model_type="scene classifer"`` or ``model_type="mlp"``, + over and under sampling will be used. For ``model_type="segmentation"``, class weighting will be + used on the loss function. model_type (str): Defines the type of the model. If ``siamese``, ensures inappropiate functionality is not used. dataset_params (dict[str, ~typing.Any]): Parameters to construct each dataset. See documentation on structure of these. @@ -116,10 +125,6 @@ class MinervaTask(ABC): Contains the ``module`` key to define the import path and the ``name`` key for name of the collation function. sample_pairs (bool): Activates paired sampling for Siamese models. Only used for ``train`` datasets. - stopping (dict[str, ~typing.Any]): Dictionary to hold the parameters defining the early stopping functionality. - If no dictionary is given, it is assumed that there will be no early stopping. - pre_train_name (str): Name of the pre-trained model to use. - reload (bool): Reloads the weights in the cache matching ``pre_train_name`` to continue model fitting. loss_func (str): Name of the loss function to use. optim_func (str): Name of the optimiser function to use. lr (float): Learning rate of optimiser. @@ -129,21 +134,16 @@ class MinervaTask(ABC): loss_params (dict[str, ~typing.Any]): :class:`dict` to hold any additional parameters for the loss function in the ``params`` key. If using a non-torch loss function, you need to specify the import path with the ``module`` key. - balance (bool): Activates class balancing. For ``model_type="scene classifer"`` or ``model_type="mlp"``, - over and under sampling will be used. For ``model_type="segmentation"``, class weighting will be - used on the loss function. patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. Should align with the values given for ``patch_size``. - metrics (str): Specify the metric logger to use. Must be the name of a :class:`~metrics.MinervaMetric` class - within :mod:`metrics`. - logger (str): Specify the logger to use. Must be the name of a :class:`~logger.MinervaLogger` class - within :mod:`logger`. + tasklogger (str): Specify the task logger to use. Must be the name of a :class:`~logger.tasklog.MinervaTaskLogger` class + within :mod:`~logger.tasklog`. + steplogger (str): Specify the step logger to use. Must be the name of a :class:`~logger.steplog.MinervaStepLogger` class + within :mod:`~logger.steplog`. modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name of a function within :mod:`modelio`. - record_int (bool): Store the integer results of each epoch in memory such the predictions, ground truth etc. - record_float (bool): Store the floating point results of each epoch in memory - such as the raw predicted probabilities. + .. versionadded:: 0.27 """ @@ -181,7 +181,10 @@ def __init__( global_params["tasks"][name] = new_params + # ``global_params`` is the whole experiment parameters. self.global_params = global_params + + # ``params`` is the parameters for just this task. self.params = new_params # Modify `exp_fn` with a sub-directory for this task. @@ -197,9 +200,8 @@ def __init__( self.loaders = loaders self.class_dist = class_dist - self.batch_size = fallback_params( - "batch_size", self.global_params["tasks"][name], self.params - ) + # Try to find parameters first in the task params then fall back to the global level params. + self.batch_size = fallback_params("batch_size", self.params, self.global_params) # Corrects the batch size if this is a distributed job to account for batches being split across devices. if dist.is_available() and dist.is_initialized(): # type: ignore[attr-defined] # pragma: no cover @@ -221,6 +223,7 @@ def __init__( "record_float", self.params, self.global_params, record_float ) + # Ensure the model IO function is treated as static not a class method. self.modelio = staticmethod(self.get_io_func()).__func__ self.loaders = loaders @@ -228,10 +231,13 @@ def __init__( self.writer = writer self.step_num = 0 + # Initialise the Weights and Biases metrics for this task. self.init_wandb_metrics() + # Update the loss function of the model. self.model.set_criterion(self.make_criterion()) + # Make the logger for this task. self.logger: MinervaTaskLogger = self.make_logger() def init_wandb_metrics(self) -> None: From 8936ce0c6ead8c7daf671bd0eb41178e3bc9f64b Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 27 Oct 2023 16:42:31 +0100 Subject: [PATCH 122/136] Remove and replace broken fudge --- minerva/datasets/paired.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/minerva/datasets/paired.py b/minerva/datasets/paired.py index 40ec8e60e..5a90c6e17 100644 --- a/minerva/datasets/paired.py +++ b/minerva/datasets/paired.py @@ -109,10 +109,10 @@ def __init__( key.name: kwargs[key.name] for key in super_sig if key.name in kwargs } - if issubclass(dataset, RasterDataset): # type: ignore[arg-type] - # This is very sketchy but an unavoidable workaround due to TorchGeo's behaviour. - RasterDataset.filename_glob = dataset.filename_glob # type: ignore[attr-defined] - RasterDataset.filename_regex = dataset.filename_regex # type: ignore[attr-defined] + # Make sure PairedDataset has access to the `all_bands` attribute of the dataset. + # Needed for a subset of the bands to be selected if so desired. + if hasattr(dataset, "all_bands"): + self.all_bands = dataset.all_bands super().__init__(*args, **super_kwargs) self.dataset = dataset(*args, **kwargs) From 2512a41bb25fac0ec7a8164d600dfdc295bb1459 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 27 Oct 2023 16:43:05 +0100 Subject: [PATCH 123/136] Use `SSL4E0-S12` data for training in example --- minerva/inbuilt_cfgs/example_GeoSimConvNet.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml index 9373ba982..cbccb4b27 100644 --- a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml +++ b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml @@ -136,18 +136,11 @@ tasks: module: torchvision.transforms kernel_size: 25 - image1: - module: minerva.datasets.__testing - name: TstImgDataset - paths: NAIP - params: - res: 1.0 - image2: - module: minerva.datasets.__testing - name: TstImgDataset - paths: NAIP - params: - res: 1.0 + module: minerva.datasets + name: SSL4EOS12Sentinel2 + paths: SSL4EO-S12 + params: + res: 10.0 fit-val: type: WeightedKNN From 23c345b753837d1934b6af49d851e69ff7073f35 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 27 Oct 2023 17:47:29 +0100 Subject: [PATCH 124/136] New test for the `SSL4E0S12Sentinel2` dataset class --- tests/test_datasets/test_ssl4eo_s12.py | 72 ++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/test_datasets/test_ssl4eo_s12.py diff --git a/tests/test_datasets/test_ssl4eo_s12.py b/tests/test_datasets/test_ssl4eo_s12.py new file mode 100644 index 000000000..69e787875 --- /dev/null +++ b/tests/test_datasets/test_ssl4eo_s12.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# MIT License + +# Copyright (c) 2023 Harry Baker + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# @org: University of Southampton +# Created under a project funded by the Ordnance Survey Ltd. +r"""Tests for :mod:`minerva.datasets.ssl4eo_s12`. +""" +# ===================================================================================================================== +# METADATA +# ===================================================================================================================== +__author__ = "Harry Baker" +__contact__ = "hjb1d20@soton.ac.uk" +__license__ = "MIT License" +__copyright__ = "Copyright (C) 2023 Harry Baker" + +# ===================================================================================================================== +# IMPORTS +# ===================================================================================================================== +from pathlib import Path + +import pytest +from rasterio.crs import CRS + +from minerva.datasets import PairedDataset, SSL4EOS12Sentinel2 +from minerva.utils import CONFIG + + +# ===================================================================================================================== +# TESTS +# ===================================================================================================================== +def test_ssl4eos12sentinel2() -> None: + path = str(Path(CONFIG["dir"]["data"]) / "SSL4EO-S12") + bands = ["B1", "B2", "B3", "B8A"] + crs = CRS.from_epsg(25832) + res = 10.0 + + all_bands_dataset = SSL4EOS12Sentinel2(paths=path, res=res, crs=crs) + + assert isinstance(all_bands_dataset, SSL4EOS12Sentinel2) + + rgbi_dataset = SSL4EOS12Sentinel2(paths=path, bands=bands, res=res, crs=crs) + assert isinstance(rgbi_dataset, SSL4EOS12Sentinel2) + + paired_dataset = PairedDataset(rgbi_dataset) + + assert isinstance(paired_dataset, PairedDataset) + + init_as_paired = PairedDataset( + SSL4EOS12Sentinel2, paths=path, bands=bands, res=res, crs=crs + ) + + assert isinstance(init_as_paired, PairedDataset) From 36c0831c73ef25e72c175dd443790d0b3ae36754 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 27 Oct 2023 17:48:32 +0100 Subject: [PATCH 125/136] Fixced test with `crs` and `bands` args --- minerva/inbuilt_cfgs/example_GeoSimConvNet.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml index cbccb4b27..593abae0b 100644 --- a/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml +++ b/minerva/inbuilt_cfgs/example_GeoSimConvNet.yml @@ -45,9 +45,9 @@ optim_func: SGD # Name of the optimiser function. # ---+ SSL/ Siamese Options +-------------------------------------------------- sample_pairs: true # Activates Siamese paired sampling. -max_r: &max_r 56 # Max distance between patches within a Siamese pair. -knn_k: 5 # Top-k most similar images used to predict image for KNN val -val_freq: 2 # Validation epoch every ``val_freq`` training epochs. +max_r: &max_r 320 # Max distance between patches within a pair. +knn_k: 5 # Top-k most similar images to predict image for KNN val +val_freq: 2 # Validation epoch every ``val_freq`` training epochs. # ---+ Model Parameters +------------------------------------------------------ model_params: @@ -76,11 +76,6 @@ project: pytest # Define the project name for wandb. wandb_dir: *wandb_dir # === MODEL IO & LOGGING ====================================================== -# ---+ Minerva Inbuilt Logging Functions +------------------------------------- -# task_logger: SSLLogger -# metrics: SSLMetrics -# model_io: ssl_pair_tg - record_int: true # Store integer results in memory. record_float: false # Store floating point results too. Beware memory overload! @@ -141,6 +136,8 @@ tasks: paths: SSL4EO-S12 params: res: 10.0 + crs: 25832 + bands: [B1, B2, B3, B8A] fit-val: type: WeightedKNN From 2d57793771ad421148f7ee78f9a3b849a87a11a3 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 27 Oct 2023 18:11:53 +0100 Subject: [PATCH 126/136] `flake8` fixes --- minerva/tasks/core.py | 8 ++++---- tests/test_datasets/test_ssl4eo_s12.py | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 857ffe1e9..28c36ab65 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -137,10 +137,10 @@ class MinervaTask(ABC): patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. Should align with the values given for ``patch_size``. - tasklogger (str): Specify the task logger to use. Must be the name of a :class:`~logger.tasklog.MinervaTaskLogger` class - within :mod:`~logger.tasklog`. - steplogger (str): Specify the step logger to use. Must be the name of a :class:`~logger.steplog.MinervaStepLogger` class - within :mod:`~logger.steplog`. + tasklogger (str): Specify the task logger to use. Must be the name of a :class:`~logger.tasklog.MinervaTaskLogger` + class within :mod:`~logger.tasklog`. + steplogger (str): Specify the step logger to use. Must be the name of a :class:`~logger.steplog.MinervaStepLogger` + class within :mod:`~logger.steplog`. modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name of a function within :mod:`modelio`. diff --git a/tests/test_datasets/test_ssl4eo_s12.py b/tests/test_datasets/test_ssl4eo_s12.py index 69e787875..c2bf98b8a 100644 --- a/tests/test_datasets/test_ssl4eo_s12.py +++ b/tests/test_datasets/test_ssl4eo_s12.py @@ -38,7 +38,6 @@ # ===================================================================================================================== from pathlib import Path -import pytest from rasterio.crs import CRS from minerva.datasets import PairedDataset, SSL4EOS12Sentinel2 From ebb50ba47073b08b21e498adaaff4a35507e9fb9 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 30 Oct 2023 16:16:48 +0000 Subject: [PATCH 127/136] Added `compile_dataset_paths` --- minerva/datasets/factory.py | 7 +++---- minerva/utils/utils.py | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index a480adb17..fc4ae6ede 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -121,12 +121,11 @@ def get_subdataset( ) # Construct the path to the sub-dataset's files. - sub_dataset_path: Path = ( - universal_path(data_directory) / sub_dataset_params["paths"] + sub_dataset_paths = utils.compile_dataset_paths( + data_directory, sub_dataset_params["paths"] ) - sub_dataset_path = sub_dataset_path.absolute() - return _sub_dataset, str(sub_dataset_path) + return _sub_dataset, sub_dataset_paths def create_subdataset( dataset_class: Callable[..., GeoDataset], diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 825532cb6..13d566fee 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -107,6 +107,7 @@ "tsne_cluster", "calc_norm_euc_dist", "fallback_params", + "compile_dataset_paths", ] # ===================================================================================================================== @@ -1955,3 +1956,25 @@ def fallback_params( return params_b[key] else: return fallback + + +def compile_dataset_paths( + data_dir: Union[Path, str], + in_paths: Union[List[Union[Path, str]], Union[Path, str]], +) -> List[str]: + """Ensures that a list of paths is returned with the data directory prepended, even if a single string is supplied + + Args: + data_dir (~pathlib.Path | str): The parent data directory for all paths. + in_paths (list[~pathlib.Path | str] | [~pathlib.Path | str]): Paths to the data to be compilied. + + Returns: + list[str]: Compilied paths to the data. + """ + if isinstance(in_paths, list): + out_paths = [universal_path(data_dir) / path for path in in_paths] + else: + out_paths = [universal_path(data_dir) / in_paths] + + # For each path, get the absolute path, convert to string and return. + return [str(path.absolute()) for path in out_paths] From f966cda9781c12fa03f6b7f125bbec6845b65937 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 30 Oct 2023 17:25:36 +0000 Subject: [PATCH 128/136] Added glob compilation --- minerva/utils/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 13d566fee..4b6568f3a 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -116,6 +116,7 @@ # ---+ Inbuilt +------------------------------------------------------------------------------------------------------- import cmath import functools +import glob import importlib import inspect import math @@ -1976,5 +1977,9 @@ def compile_dataset_paths( else: out_paths = [universal_path(data_dir) / in_paths] + compiled_paths = [] + for path in out_paths: + compiled_paths.extend(glob.glob(path, recursive=True)) + # For each path, get the absolute path, convert to string and return. return [str(path.absolute()) for path in out_paths] From cb74421bd63823084b492ce87dfd0dc02a4cc291 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 30 Oct 2023 17:31:55 +0000 Subject: [PATCH 129/136] Fixed `TypeError` --- minerva/utils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 4b6568f3a..87baf8d12 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -1979,7 +1979,7 @@ def compile_dataset_paths( compiled_paths = [] for path in out_paths: - compiled_paths.extend(glob.glob(path, recursive=True)) + compiled_paths.extend(glob.glob(str(path), recursive=True)) # For each path, get the absolute path, convert to string and return. - return [str(path.absolute()) for path in out_paths] + return [str(Path(path).absolute()) for path in out_paths] From 27b7f78a38b2931aad6cc1393e07f3eb49153ea8 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 30 Oct 2023 17:42:07 +0000 Subject: [PATCH 130/136] Debug --- minerva/utils/utils.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 87baf8d12..60c6a5c5c 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -1979,7 +1979,12 @@ def compile_dataset_paths( compiled_paths = [] for path in out_paths: - compiled_paths.extend(glob.glob(str(path), recursive=True)) + glob_paths = glob.glob(str(path), recursive=True) + compiled_paths.extend(glob_paths) + + print(glob_paths) + + print(compiled_paths) # For each path, get the absolute path, convert to string and return. return [str(Path(path).absolute()) for path in out_paths] From 54ada8302a037f580c2af3588d1aa3e9eb54bd7f Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 30 Oct 2023 17:45:25 +0000 Subject: [PATCH 131/136] Fixed bug --- minerva/utils/utils.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/minerva/utils/utils.py b/minerva/utils/utils.py index 60c6a5c5c..120383c6b 100644 --- a/minerva/utils/utils.py +++ b/minerva/utils/utils.py @@ -1979,12 +1979,7 @@ def compile_dataset_paths( compiled_paths = [] for path in out_paths: - glob_paths = glob.glob(str(path), recursive=True) - compiled_paths.extend(glob_paths) - - print(glob_paths) - - print(compiled_paths) + compiled_paths.extend(glob.glob(str(path), recursive=True)) # For each path, get the absolute path, convert to string and return. - return [str(Path(path).absolute()) for path in out_paths] + return [str(Path(path).absolute()) for path in compiled_paths] From f3b638ba9f8d3d4f5f30b48e5537e257192977ad Mon Sep 17 00:00:00 2001 From: Harry Date: Wed, 1 Nov 2023 15:00:02 +0000 Subject: [PATCH 132/136] `mypy` and `flake8` fixes --- minerva/datasets/factory.py | 4 ++-- minerva/tasks/core.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/minerva/datasets/factory.py b/minerva/datasets/factory.py index fc4ae6ede..543b019a7 100644 --- a/minerva/datasets/factory.py +++ b/minerva/datasets/factory.py @@ -111,7 +111,7 @@ def make_dataset( def get_subdataset( this_dataset_params: Dict[str, Any], key: str - ) -> Tuple[Callable[..., GeoDataset], str]: + ) -> Tuple[Callable[..., GeoDataset], List[str]]: # Get the params for this sub-dataset. sub_dataset_params = this_dataset_params[key] @@ -122,7 +122,7 @@ def get_subdataset( # Construct the path to the sub-dataset's files. sub_dataset_paths = utils.compile_dataset_paths( - data_directory, sub_dataset_params["paths"] + universal_path(data_directory), sub_dataset_params["paths"] ) return _sub_dataset, sub_dataset_paths diff --git a/minerva/tasks/core.py b/minerva/tasks/core.py index 28c36ab65..a53adc7ba 100644 --- a/minerva/tasks/core.py +++ b/minerva/tasks/core.py @@ -137,10 +137,10 @@ class MinervaTask(ABC): patch_size (tuple[float, float]): Defines the shape of the patches in the dataset. input_size (tuple[int, ...]): Shape of the input to the model. Typically in CxHxW format. Should align with the values given for ``patch_size``. - tasklogger (str): Specify the task logger to use. Must be the name of a :class:`~logger.tasklog.MinervaTaskLogger` - class within :mod:`~logger.tasklog`. - steplogger (str): Specify the step logger to use. Must be the name of a :class:`~logger.steplog.MinervaStepLogger` - class within :mod:`~logger.steplog`. + tasklogger (str): Specify the task logger to use. Must be the name of a + :class:`~logger.tasklog.MinervaTaskLogger` class within :mod:`~logger.tasklog`. + steplogger (str): Specify the step logger to use. Must be the name of a + :class:`~logger.steplog.MinervaStepLogger` class within :mod:`~logger.steplog`. modelio (str): Specify the IO function to use to handle IO for the model during fitting. Must be the name of a function within :mod:`modelio`. From 6ae8a71d661fcb7e0a5517046f86c1af21150bac Mon Sep 17 00:00:00 2001 From: Harry Date: Thu, 2 Nov 2023 16:43:46 +0000 Subject: [PATCH 133/136] Update requirements --- requirements/requirements.txt | 10 +++++----- requirements/requirements_dev.txt | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 079df3631..f263d76c3 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -7,17 +7,17 @@ geopy==2.4.0 GitPython>=3.1.35 imageio==2.31.6 inputimeout==1.0.4 -ipykernel==6.25.2 +ipykernel==6.26.0 lightly==1.4.21 matplotlib==3.7.2 -mlflow==2.7.1 +mlflow==2.8.0 nptyping==2.5.0 numba>=0.57.0 # not directly required but pinned to ensure Python 3.11 compatibility. numpy==1.26.1 onnx==1.14.1 -onnx2torch==1.5.12 +onnx2torch==1.5.13 overload==1.1 -pandas==2.1.1 +pandas==2.1.2 protobuf>=3.19.5 # not directly required, pinned by Snyk to avoid a vulnerability. psutil==5.9.6 pyyaml==6.0.1 @@ -37,6 +37,6 @@ tqdm==4.66.1 types-PyYAML==6.0.12.12 types-requests==2.31.0.10 types-tabulate==0.9.0.3 -wandb==0.15.10 +wandb==0.15.12 Werkzeug>=2.2.3 # Patches a potential security vulnerability. wheel>=0.38.0 # not directly required, pinned by Snyk to avoid a vulnerability. diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index ba4db62eb..d26257cb0 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -10,24 +10,24 @@ GitPython>=3.1.35 imageio==2.31.6 inputimeout==1.0.4 internet-sabotage3==0.1.6 -ipykernel==6.25.2 +ipykernel==6.26.0 lightly==1.4.21 matplotlib==3.7.2 -mlflow==2.7.1 -mypy==1.5.1 +mlflow==2.8.0 +mypy==1.6.1 myst_parser==2.0.0 nptyping==2.5.0 numba>=0.57.0 # not directly required but pinned to ensure Python 3.11 compatibility. numpy==1.26.1 onnx==1.14.1 -onnx2torch==1.5.12 +onnx2torch==1.5.13 overload==1.1 -pandas==2.1.1 +pandas==2.1.2 pre-commit==3.5.0 protobuf>=3.19.5 # not directly required, pinned by Snyk to avoid a vulnerability. psutil==5.9.6 pygments>=2.7.4 # not directly required, pinned by Snyk to avoid a vulnerability. -pytest==7.4.2 +pytest==7.4.3 pytest-cov==4.1.0 pytest-lazy-fixture==0.6.3 pyyaml==6.0.1 @@ -50,6 +50,6 @@ tqdm==4.66.1 types-PyYAML==6.0.12.12 types-requests==2.31.0.10 types-tabulate==0.9.0.3 -wandb==0.15.10 +wandb==0.15.12 Werkzeug>=2.2.3 # Patches a potential security vulnerability. wheel>=0.38.0 # not directly required, pinned by Snyk to avoid a vulnerability. From 9c986e4deac142ffdf75ee9cb4e28f7d87898995 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 10 Nov 2023 18:30:04 +0000 Subject: [PATCH 134/136] Use `torchmetrics` for cosine similarity --- minerva/logger/steplog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/minerva/logger/steplog.py b/minerva/logger/steplog.py index 11a41cbbf..c3d81db30 100644 --- a/minerva/logger/steplog.py +++ b/minerva/logger/steplog.py @@ -64,6 +64,7 @@ import torch.distributed as dist from sklearn.metrics import jaccard_score from torch import Tensor +from torchmetrics.regression import CosineSimilarity if TYPE_CHECKING: # pragma: no cover from torch.utils.tensorboard.writer import SummaryWriter @@ -671,7 +672,8 @@ def log( self.logs["total_loss"] += ls # Compute the TOP1 and TOP5 accuracies. - sim_argsort = utils.calc_contrastive_acc(z) + cosine_sim = CosineSimilarity(reduction=None) + sim_argsort = cosine_sim(*torch.split(z, int(0.5 * len(z)), 0)) correct = float((sim_argsort == 0).float().mean().cpu().numpy()) top5 = float((sim_argsort < 5).float().mean().cpu().numpy()) From 0ca17889dbd168bd64e86ec57de1802fbc136220 Mon Sep 17 00:00:00 2001 From: Harry Date: Fri, 10 Nov 2023 18:30:17 +0000 Subject: [PATCH 135/136] `torchgeo` -->`0.5.1` --- requirements/requirements.txt | 2 +- requirements/requirements_dev.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index f263d76c3..98c8a5144 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -30,7 +30,7 @@ starlette==0.31.1 # not directly required, pinned by Dependabot to avoid a vulne tabulate==0.9.0 tensorflow==2.14.0 timm==0.9.2 -torchgeo==0.5.0 +torchgeo==0.5.1 torchinfo==1.8.0 tornado>=6.3.3 tqdm==4.66.1 diff --git a/requirements/requirements_dev.txt b/requirements/requirements_dev.txt index d26257cb0..5b887bb55 100644 --- a/requirements/requirements_dev.txt +++ b/requirements/requirements_dev.txt @@ -42,7 +42,7 @@ starlette>=0.25.0 # not directly required, pinned by Dependabot to avoid a vulne tabulate==0.9.0 tensorflow==2.14.0 timm==0.9.2 -torchgeo==0.5.0 +torchgeo==0.5.1 torchinfo==1.8.0 tornado>=6.3.3 tox==4.11.3 From 4ae439868f308a105b74040cd8cd9221441f9810 Mon Sep 17 00:00:00 2001 From: Harry Date: Mon, 13 Nov 2023 15:55:15 +0000 Subject: [PATCH 136/136] Remove Qodana --- .github/workflows/code_quality.yml | 24 - README.md | 2 +- docs/docs_readme.md | 2 +- qodana.sarif.json | 27425 --------------------------- qodana.yaml | 6 - 5 files changed, 2 insertions(+), 27457 deletions(-) delete mode 100644 .github/workflows/code_quality.yml delete mode 100644 qodana.sarif.json delete mode 100644 qodana.yaml diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml deleted file mode 100644 index f4205bf8c..000000000 --- a/.github/workflows/code_quality.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- -name: Qodana 🔭 -on: - workflow_dispatch: - pull_request: - push: - branches: - - main - -jobs: - qodana: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - name: Qodana Scan 🔭 - uses: JetBrains/qodana-action@v2023.2.8 - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} - with: - args: --baseline,qodana.sarif.json - upload-result: true diff --git a/README.md b/README.md index fda08d119..72bdb5e6d 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/minerva) ![GitHub contributors](https://img.shields.io/github/contributors/Pale-Blue-Dot-97/Minerva?) [![CodeFactor](https://www.codefactor.io/repository/github/pale-blue-dot-97/minerva/badge)](https://www.codefactor.io/repository/github/pale-blue-dot-97/minerva) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/f961aed541494e4db7317bead5f84fef)](https://app.codacy.com/gh/Pale-Blue-Dot-97/Minerva/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) ![tests](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/tests.yml/badge.svg) [![Read the Docs](https://img.shields.io/readthedocs/smp?)](https://pale-blue-dot-97.github.io/Minerva/) -[![Qodana](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/code_quality.yml/badge.svg)](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/code_quality.yml) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/Pale-Blue-Dot-97/Minerva/main.svg)](https://results.pre-commit.ci/latest/github/Pale-Blue-Dot-97/Minerva/main) diff --git a/docs/docs_readme.md b/docs/docs_readme.md index fda08d119..72bdb5e6d 100644 --- a/docs/docs_readme.md +++ b/docs/docs_readme.md @@ -5,9 +5,9 @@ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/minerva) ![GitHub contributors](https://img.shields.io/github/contributors/Pale-Blue-Dot-97/Minerva?) [![CodeFactor](https://www.codefactor.io/repository/github/pale-blue-dot-97/minerva/badge)](https://www.codefactor.io/repository/github/pale-blue-dot-97/minerva) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/f961aed541494e4db7317bead5f84fef)](https://app.codacy.com/gh/Pale-Blue-Dot-97/Minerva/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) ![tests](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/tests.yml/badge.svg) [![Read the Docs](https://img.shields.io/readthedocs/smp?)](https://pale-blue-dot-97.github.io/Minerva/) -[![Qodana](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/code_quality.yml/badge.svg)](https://github.com/Pale-Blue-Dot-97/Minerva/actions/workflows/code_quality.yml) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![security: bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/Pale-Blue-Dot-97/Minerva/main.svg)](https://results.pre-commit.ci/latest/github/Pale-Blue-Dot-97/Minerva/main) diff --git a/qodana.sarif.json b/qodana.sarif.json deleted file mode 100644 index 364e7fe66..000000000 --- a/qodana.sarif.json +++ /dev/null @@ -1,27425 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/schemastore/schemastore/master/src/schemas/json/sarif-2.1.0-rtm.5.json", - "version": "2.1.0", - "runs": [ - { - "tool": { - "driver": { - "name": "QDPY", - "fullName": "Qodana for Python", - "version": "232.9876.134", - "rules": [], - "taxa": [ - { - "id": "EditorConfig", - "name": "EditorConfig" - }, - { - "id": "Python", - "name": "Python" - }, - { - "id": "JavaScript and TypeScript", - "name": "JavaScript and TypeScript" - }, - { - "id": "JavaScript and TypeScript/Control flow issues", - "name": "Control flow issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Google App Engine (Python)", - "name": "Google App Engine (Python)" - }, - { - "id": "PostCSS", - "name": "PostCSS" - }, - { - "id": "Sass/SCSS", - "name": "Sass/SCSS" - }, - { - "id": "Shell script", - "name": "Shell script" - }, - { - "id": "JavaScript and TypeScript/Unit testing", - "name": "Unit testing", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSON and JSON5", - "name": "JSON and JSON5" - }, - { - "id": "MongoJS", - "name": "MongoJS" - }, - { - "id": "JavaScript and TypeScript/General", - "name": "General", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Code style issues", - "name": "Code style issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MySQL", - "name": "MySQL" - }, - { - "id": "Properties files", - "name": "Properties files" - }, - { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "name": "Potentially undesirable code constructs", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Flow type checker", - "name": "Flow type checker", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Probable bugs", - "name": "Probable bugs", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HTML", - "name": "HTML" - }, - { - "id": "JavaScript and TypeScript/Unused symbols", - "name": "Unused symbols", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Data flow", - "name": "Data flow", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Django", - "name": "Django" - }, - { - "id": "JavaScript and TypeScript/Bitwise operation issues", - "name": "Bitwise operation issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "name": "ES2015 migration aids", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "General", - "name": "General" - }, - { - "id": "HTML/Accessibility", - "name": "Accessibility", - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/React", - "name": "React", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/TypeScript", - "name": "TypeScript", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Validity issues", - "name": "Validity issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "name": "Potentially confusing code constructs", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CSS", - "name": "CSS" - }, - { - "id": "CSS/Invalid elements", - "name": "Invalid elements", - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SQL", - "name": "SQL" - }, - { - "id": "JavaScript and TypeScript/Try statement issues", - "name": "Try statement issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Structural search", - "name": "Structural search" - }, - { - "id": "JavaScript and TypeScript/Function metrics", - "name": "Function metrics", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Dependency analysis", - "name": "Dependency analysis" - }, - { - "id": "YAML", - "name": "YAML" - }, - { - "id": "XML", - "name": "XML" - }, - { - "id": "JavaScript and TypeScript/Assignment issues", - "name": "Assignment issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Security", - "name": "Security" - }, - { - "id": "CSS/Code style issues", - "name": "Code style issues", - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Less", - "name": "Less" - }, - { - "id": "RegExp", - "name": "RegExp" - }, - { - "id": "Vue", - "name": "Vue" - }, - { - "id": "JavaScript and TypeScript/Node.js", - "name": "Node.js", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Ini files", - "name": "Ini files" - }, - { - "id": "JavaScript and TypeScript/Imports and dependencies", - "name": "Imports and dependencies", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RELAX NG", - "name": "RELAX NG" - }, - { - "id": "CSS/Probable bugs", - "name": "Probable bugs", - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Naming conventions", - "name": "Naming conventions", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Switch statement issues", - "name": "Switch statement issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/DOM issues", - "name": "DOM issues", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Async code and promises", - "name": "Async code and promises", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JavaScript and TypeScript/Code quality tools", - "name": "Code quality tools", - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript", - "index": 2, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Code Coverage", - "name": "Code Coverage" - }, - { - "id": "Proofreading", - "name": "Proofreading" - }, - { - "id": "CSS/Code quality tools", - "name": "Code quality tools", - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Jupyter", - "name": "Jupyter" - }, - { - "id": "PostgreSQL", - "name": "PostgreSQL" - }, - { - "id": "SQL server", - "name": "SQL server" - }, - { - "id": "Qodana", - "name": "Qodana" - }, - { - "id": "Pyramid", - "name": "Pyramid" - }, - { - "id": "Oracle", - "name": "Oracle" - }, - { - "id": "Internationalization", - "name": "Internationalization" - }, - { - "id": "Version control", - "name": "Version control" - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - "extensions": [ - { - "name": "org.editorconfig.editorconfigjetbrains", - "version": "232.9876", - "rules": [ - { - "id": "EditorConfigCharClassRedundancy", - "shortDescription": { - "text": "Unnecessary character class" - }, - "fullDescription": { - "text": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example '[a]'→'a'.", - "markdown": "Reports character classes that consist of a single character. Such classes can be simplified to a character, for example `[a]`→`a`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigCharClassRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigRootDeclarationUniqueness", - "shortDescription": { - "text": "Extra top-level declaration" - }, - "fullDescription": { - "text": "Reports multiple top-level declarations. There can be only one optional “root=true” top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed.", - "markdown": "Reports multiple top-level declarations. There can be only one optional \"root=true\" top-level declaration in the EditorConfig file. Using multiple top-level declarations is not allowed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigRootDeclarationUniqueness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigNumerousWildcards", - "shortDescription": { - "text": "Too many wildcards" - }, - "fullDescription": { - "text": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues.", - "markdown": "Reports sections that contain too many wildcards. Using a lot of wildcards may lead to performance issues." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "EditorConfigNumerousWildcards", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigPartialOverride", - "shortDescription": { - "text": "Overlapping sections" - }, - "fullDescription": { - "text": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: '[{foo,bar}]' and '[{foo,bas}]' both contain “foo”.", - "markdown": "Reports subsets of files specified in the current section that overlap with other subsets in other sections. For example: `[{foo,bar}]` and `[{foo,bas}]` both contain \"foo\"." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "EditorConfigPartialOverride", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigEmptySection", - "shortDescription": { - "text": "Empty section" - }, - "fullDescription": { - "text": "Reports sections that do not contain any EditorConfig properties.", - "markdown": "Reports sections that do not contain any EditorConfig properties." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigEmptySection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigShadowingOption", - "shortDescription": { - "text": "Overriding property" - }, - "fullDescription": { - "text": "Reports properties that override the same properties defined earlier in the file. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes the same files as '[*.java]' but also sets indent_size to value 2. Thus the first declaration 'indent_size=4'will be ignored.", - "markdown": "Reports properties that override the same properties defined earlier in the file.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes the same files as `[*.java]` but also sets indent_size to value 2. Thus the first declaration `indent_size=4`will be ignored." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigShadowingOption", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigListAcceptability", - "shortDescription": { - "text": "Unexpected value list" - }, - "fullDescription": { - "text": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified.", - "markdown": "Reports lists of values that are used in properties in which lists are not supported. In this case, only a single value can be specified." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigListAcceptability", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigKeyCorrectness", - "shortDescription": { - "text": "Unknown property" - }, - "fullDescription": { - "text": "Reports properties that are not supported by the IDE. Note: some “ij” domain properties may require specific language plugins.", - "markdown": "Reports properties that are not supported by the IDE. Note: some \"ij\" domain properties may require specific language plugins." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigKeyCorrectness", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigPatternEnumerationRedundancy", - "shortDescription": { - "text": "Unnecessary braces" - }, - "fullDescription": { - "text": "Reports pattern lists that are either empty '{}' or contain just one pattern, for example '{foo}' in contrast to a list containing multiple patterns, for example '{foo,bar}'. In this case braces are handled as a part of the name. For example, the pattern '*.{a}' will match the file 'my.{a}' but not 'my.a'.", - "markdown": "Reports pattern lists that are either empty `{}` or contain just one pattern, for example `{foo}` in contrast to a list containing multiple patterns, for example `{foo,bar}`. In this case braces are handled as a part of the name. For example, the pattern `*.{a}` will match the file `my.{a}` but not `my.a`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigPatternEnumerationRedundancy", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigEncoding", - "shortDescription": { - "text": "File encoding doesn't match EditorConfig charset" - }, - "fullDescription": { - "text": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file.", - "markdown": "Checks that current file encoding matches the encoding defined in \"charset\" property of .editorconfig file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigEncoding", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigRootDeclarationCorrectness", - "shortDescription": { - "text": "Unexpected top-level declaration" - }, - "fullDescription": { - "text": "Reports unexpected top-level declarations. Top-level declarations other than “root=true” are not allowed in the EditorConfig file.", - "markdown": "Reports unexpected top-level declarations. Top-level declarations other than \"root=true\" are not allowed in the EditorConfig file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigRootDeclarationCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigReferenceCorrectness", - "shortDescription": { - "text": "Invalid reference" - }, - "fullDescription": { - "text": "Reports identifiers that are either unknown or have a wrong type.", - "markdown": "Reports identifiers that are either unknown or have a wrong type." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigReferenceCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigPairAcceptability", - "shortDescription": { - "text": "Unexpected key-value pair" - }, - "fullDescription": { - "text": "Reports key-value pairs that are not allowed in the current context.", - "markdown": "Reports key-value pairs that are not allowed in the current context." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigPairAcceptability", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigPatternRedundancy", - "shortDescription": { - "text": "Duplicate or redundant pattern" - }, - "fullDescription": { - "text": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in '[{*.java,*}]' the first '*.java' pattern defines a narrower scope compared to '*'. That is why it is redundant and can be removed.", - "markdown": "Reports file patterns that are redundant as there already are other patterns that define the same scope of files or even a broader one. For example, in `[{*.java,*}]` the first `*.java` pattern defines a narrower scope compared to `*`. That is why it is redundant and can be removed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigPatternRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigNoMatchingFiles", - "shortDescription": { - "text": "No matching files" - }, - "fullDescription": { - "text": "Reports sections with wildcard patterns that do not match any files under the directory in which the '.editorconfig' file is located.", - "markdown": "Reports sections with wildcard patterns that do not match any files under the directory in which the `.editorconfig` file is located." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigNoMatchingFiles", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigDeprecatedDescriptor", - "shortDescription": { - "text": "Deprecated property" - }, - "fullDescription": { - "text": "Reports EditorConfig properties that are no longer supported.", - "markdown": "Reports EditorConfig properties that are no longer supported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigDeprecatedDescriptor", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigWildcardRedundancy", - "shortDescription": { - "text": "Redundant wildcard" - }, - "fullDescription": { - "text": "Reports wildcards that become redundant when the “**” wildcard is used in the same section. The “**” wildcard defines a broader set of files than any other wildcard. That is why, any other wildcard used in the same section has no affect and can be removed.", - "markdown": "Reports wildcards that become redundant when the \"\\*\\*\" wildcard is used in the same section.\n\n\nThe \"\\*\\*\" wildcard defines a broader set of files than any other wildcard.\nThat is why, any other wildcard used in the same section has no affect and can be removed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigWildcardRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigHeaderUniqueness", - "shortDescription": { - "text": "EditorConfig section is not unique" - }, - "fullDescription": { - "text": "Reports sections that define the same file pattern as other sections.", - "markdown": "Reports sections that define the same file pattern as other sections." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigHeaderUniqueness", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigShadowedOption", - "shortDescription": { - "text": "Overridden property" - }, - "fullDescription": { - "text": "Reports properties that are already defined in other sections. For example: '[*.java]\nindent_size=4\n[{*.java,*.js}]\nindent_size=2' The second section includes all '*.java' files too but it also redefines indent_size. As a result the value 2 will be used for files matching '*.java'.", - "markdown": "Reports properties that are already defined in other sections.\n\nFor example:\n\n\n [*.java]\n indent_size=4\n [{*.java,*.js}]\n indent_size=2\n\nThe second section includes all `*.java` files too but it also redefines indent_size. As a result the value 2 will be used for files matching `*.java`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigShadowedOption", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigEmptyHeader", - "shortDescription": { - "text": "Empty header" - }, - "fullDescription": { - "text": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by 'gitignore'.", - "markdown": "Reports sections with an empty header. Section header must contain file path globs in the format similar to one supported by `gitignore`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigEmptyHeader", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigValueCorrectness", - "shortDescription": { - "text": "Invalid property value" - }, - "fullDescription": { - "text": "Reports property values that do not meet value restrictions. For example, some properties may be only “true” or “false”, others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them.", - "markdown": "Reports property values that do not meet value restrictions. For example, some properties may be only \"true\" or \"false\", others contain only integer numbers etc. If a value has a limited set of variants, use code completion to see all of them." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigValueCorrectness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigVerifyByCore", - "shortDescription": { - "text": "Invalid .editorconfig file" - }, - "fullDescription": { - "text": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied.", - "markdown": "Verifies the whole file using the backing EditorConfig core library and reports any failures. Any such failure would prevent EditorConfig properties from being correctly applied." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigVerifyByCore", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigValueUniqueness", - "shortDescription": { - "text": "Non-unique list value" - }, - "fullDescription": { - "text": "Reports duplicates in lists of values.", - "markdown": "Reports duplicates in lists of values." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigValueUniqueness", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigMissingRequiredDeclaration", - "shortDescription": { - "text": "Required declarations are missing" - }, - "fullDescription": { - "text": "Reports properties that miss the required declarations. Refer to the documentation for more information.", - "markdown": "Reports properties that miss the required declarations. Refer to the documentation for more information." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigMissingRequiredDeclaration", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigCharClassLetterRedundancy", - "shortDescription": { - "text": "Duplicate character class letter" - }, - "fullDescription": { - "text": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example '[aa]'.", - "markdown": "Reports wildcard patterns in the EditorConfig section that contain a duplicate character in the character class, for example `[aa]`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigCharClassLetterRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigSpaceInHeader", - "shortDescription": { - "text": "Space in file pattern" - }, - "fullDescription": { - "text": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed.", - "markdown": "Reports space characters in wildcard patterns that affect pattern matching. If these characters are not intentional, they should be removed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "EditorConfigSpaceInHeader", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigOptionRedundancy", - "shortDescription": { - "text": "Redundant property" - }, - "fullDescription": { - "text": "Reports properties that are redundant when another applicable section already contains the same property and value. For example: '[*]\nindent_size=4\n[*.java]\nindent_size=4' are both applicable to '*.java' files and define the same 'indent_size' value.", - "markdown": "Reports properties that are redundant when another applicable section already contains the same property and value.\n\n\nFor example:\n\n\n [*]\n indent_size=4\n [*.java]\n indent_size=4\n\nare both applicable to `*.java` files and define the same `indent_size` value." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigOptionRedundancy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigUnusedDeclaration", - "shortDescription": { - "text": "Unused declaration" - }, - "fullDescription": { - "text": "Reports unused declarations. Such declarations can be removed.", - "markdown": "Reports unused declarations. Such declarations can be removed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EditorConfigUnusedDeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EditorConfigUnexpectedComma", - "shortDescription": { - "text": "Unexpected comma" - }, - "fullDescription": { - "text": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists.", - "markdown": "Reports commas that cannot be used in the current context. Commas are allowed only as separators for values in lists." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "EditorConfigUnexpectedComma", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "EditorConfig", - "index": 0, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "Pythonid", - "version": "232.9876", - "rules": [ - { - "id": "PyPandasSeriesToListInspection", - "shortDescription": { - "text": "Method Series.to_list() is recommended" - }, - "fullDescription": { - "text": "Reports redundant 'list' in 'list(Series.values)' statement for pandas and polars libraries. Such 'Series' values extraction can be replaced with the 'to_list()' function call. Example: list(df['column'].values)\n When the quick-fix is applied, the code changes to: df['column'].to_list()", - "markdown": "Reports redundant `list` in `list(Series.values)` statement for pandas and polars libraries.\nSuch `Series` values extraction can be replaced with the `to_list()` function call.\n\n**Example:**\n\n```\nlist(df['column'].values)\n```\n\nWhen the quick-fix is applied, the code changes to:\n\n```\ndf['column'].to_list()\n```" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyPackages", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PySetFunctionToLiteralInspection", - "shortDescription": { - "text": "Function call can be replaced with set literal" - }, - "fullDescription": { - "text": "Reports calls to the 'set' function that can be replaced with the 'set' literal. Example: 'def do_mult(a, b):\n c = a * b\n return set([c, a, b])' When the quick-fix is applied, the code changes to: 'def do_mult(a, b):\n c = a * b\n return {c, a, b}'", - "markdown": "Reports calls to the `set` function that can be replaced with\nthe `set` literal.\n\n**Example:**\n\n\n def do_mult(a, b):\n c = a * b\n return set([c, a, b])\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_mult(a, b):\n c = a * b\n return {c, a, b}\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PySetFunctionToLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Query_index_required", - "shortDescription": { - "text": "Query does not have the required index" - }, - "fullDescription": { - "text": "Reports GQL queries for which an index is not defined in 'index.yaml'. Such queries will fail on the production server. The quick-fix allows you to add the necessary index definitions.", - "markdown": "Reports GQL queries for which an index is not defined in `index.yaml`.\nSuch queries will fail on the production server.\nThe quick-fix allows you to add the necessary index definitions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "Query_index_required", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyInitNewSignatureInspection", - "shortDescription": { - "text": "Incompatible signatures of __new__ and __init__" - }, - "fullDescription": { - "text": "Reports incompatible signatures of the '__new__' and '__init__' methods. Example: 'class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass' If the '__new__' and '__init__' have different arguments, then the 'MyClass' cannot be instantiated. As a fix, the IDE offers to apply the Change Signature refactoring.", - "markdown": "Reports incompatible signatures of the `__new__` and `__init__` methods.\n\n**Example:**\n\n\n class MyClass(object):\n def __new__(cls, arg1):\n return super().__new__(cls)\n\n def __init__(self):\n pass\n\nIf the `__new__` and `__init__` have different arguments, then the `MyClass`\ncannot be instantiated.\n\nAs a fix, the IDE offers to apply the Change Signature refactoring." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyInitNewSignature", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EndBlockNamesInspection", - "shortDescription": { - "text": "Django endblock name doesn't match the block name" - }, - "fullDescription": { - "text": "Reports incorrect names of the closing blocks. Example: '{% block my_block %}\n {% endblock not_correct %}'", - "markdown": "Reports incorrect names of the closing blocks.\n\n**Example:**\n\n\n {% block my_block %}\n {% endblock not_correct %}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EndBlockNamesInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMissingConstructorInspection", - "shortDescription": { - "text": "Missed call to '__init__' of the super class" - }, - "fullDescription": { - "text": "Reports cases when a call to the 'super' constructor in a class is missed. Example: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n pass' The 'Pear' class should have a 'super' call in the '__init__' method. When the quick-fix is applied, the code changes to: 'class Fruit:\n def __init__(self):\n pass\n\n\nclass Pear(Fruit):\n def __init__(self):\n super().__init__()'", - "markdown": "Reports cases when a call to the `super` constructor in a class is missed.\n\n**Example:**\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n pass\n\nThe `Pear` class should have a `super` call in the `__init__`\nmethod.\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Fruit:\n def __init__(self):\n pass\n\n\n class Pear(Fruit):\n def __init__(self):\n super().__init__()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyMissingConstructor", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PySimplifyBooleanCheckInspection", - "shortDescription": { - "text": "Redundant boolean variable check" - }, - "fullDescription": { - "text": "Reports equality comparison with a boolean literal. Example: 'def func(s):\n if s.isdigit() == True:\n return int(s)' With the quick-fix applied, the code fragment will be simplified to: 'def func(s):\n if s.isdigit():\n return int(s)'", - "markdown": "Reports equality comparison with a boolean literal.\n\n**Example:**\n\n\n def func(s):\n if s.isdigit() == True:\n return int(s)\n\nWith the quick-fix applied, the code fragment will be simplified to:\n\n\n def func(s):\n if s.isdigit():\n return int(s)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PySimplifyBooleanCheck", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyCallingNonCallableInspection", - "shortDescription": { - "text": "Attempt to call a non-callable object" - }, - "fullDescription": { - "text": "Reports a problem when you are trying to call objects that are not callable, like, for example, properties: Example: 'class Record:\n @property\n def as_json(self):\n\njson = Record().as_json()'", - "markdown": "Reports a problem when you are trying\nto call objects that are not callable, like, for example, properties:\n\n**Example:**\n\n\n class Record:\n @property\n def as_json(self):\n\n json = Record().as_json()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyCallingNonCallable", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyUnreachableCodeInspection", - "shortDescription": { - "text": "Unreachable code" - }, - "fullDescription": { - "text": "Reports code fragments that cannot be normally reached. Example: 'if True:\n print('Yes')\nelse:\n print('No')' As a fix, you might want to check and modify the algorithm to ensure it implements the expected logic.", - "markdown": "Reports code fragments that cannot be normally reached.\n\n**Example:**\n\n\n if True:\n print('Yes')\n else:\n print('No')\n\nAs a fix, you might want to check and modify the algorithm to ensure it implements\nthe expected logic." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyUnreachableCode", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyChainedComparisonsInspection", - "shortDescription": { - "text": "Too complex chained comparisons" - }, - "fullDescription": { - "text": "Reports chained comparisons that can be simplified. Example: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass' The IDE offers to simplify 'if x >= xmin and x <= xmax'. When the quick-fix is applied, the code changes to: 'def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass'", - "markdown": "Reports chained comparisons that can be simplified.\n\n**Example:**\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if x >= xmin and x <= xmax:\n pass\n\nThe IDE offers to simplify `if x >= xmin and x <= xmax`.\nWhen the quick-fix is applied, the code changes to:\n\n\n def do_comparison(x):\n xmin = 10\n xmax = 100\n if xmin <= x <= xmax:\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyChainedComparisons", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoBrokenLineCommentInspection", - "shortDescription": { - "text": "Broken line comment" - }, - "fullDescription": { - "text": "Reports '#}' line comment ends in Django templates that do not have a matching line comment start. Example: 'comment #}' The IDE highlights '#}' as it requires the corresponding '{#' token.", - "markdown": "Reports `#}` line comment ends in Django templates that do not have a\nmatching line comment start.\n\n**Example:**\n\n\n comment #}\n\nThe IDE highlights `#}` as it requires the corresponding `{#` token." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoBrokenLineCommentInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyCompatibilityInspection", - "shortDescription": { - "text": "Code is incompatible with specific Python versions" - }, - "fullDescription": { - "text": "Reports incompatibility with the specified versions of Python. Enable this inspection if you need your code to be compatible with a range of Python versions, for example, if you are building a library. To define the range of the inspected Python versions, select the corresponding checkboxes in the Options section. For more information about the Python versions supported by the IDE, see the web help.", - "markdown": "Reports incompatibility with the specified versions of Python.\nEnable this inspection if you need your code to be compatible with a range of Python versions, for example,\nif you are building a library.\n\nTo define the range of the inspected Python versions, select the corresponding checkboxes in the **Options**\nsection.\n\nFor more information about the Python versions supported by the IDE, see the\n[web help](https://www.jetbrains.com/help/pycharm/python.html#support)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyCompatibility", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyGlobalUndefinedInspection", - "shortDescription": { - "text": "Global variable is not defined at the module level" - }, - "fullDescription": { - "text": "Reports problems when a variable defined through the 'global' statement is not defined in the module scope. Example: 'def foo():\n global bar\n print(bar)\n\nfoo()' As a fix, you can move the global variable declaration: 'global bar\n\n\ndef foo():\n print(bar)'", - "markdown": "Reports problems when a variable defined through the `global`\nstatement is not defined in the module scope.\n\n**Example:**\n\n\n def foo():\n global bar\n print(bar)\n\n foo()\n\nAs a fix, you can move the global variable declaration:\n\n\n global bar\n\n\n def foo():\n print(bar)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyGlobalUndefined", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyProtocolInspection", - "shortDescription": { - "text": "Invalid protocol definitions and usages" - }, - "fullDescription": { - "text": "Reports invalid definitions and usages of protocols introduced in PEP-544. Example: 'from typing import Protocol\n\n\nclass MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\nclass MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\nclass MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass'", - "markdown": "Reports invalid definitions and usages of protocols introduced in\n[PEP-544](https://www.python.org/dev/peps/pep-0544/).\n\n**Example:**\n\n\n from typing import Protocol\n\n\n class MyProtocol(Protocol):\n def method(self, p: int) -> str:\n pass\n\n\n class MyClass(MyProtocol):\n def method(self, p: str) -> int: # Type of 'method' is not compatible with 'MyProtocol'\n pass\n\n\n class MyAnotherProtocol(MyClass, Protocol): # All bases of a protocol must be protocols\n pass\n\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyProtocol", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTypeHintsInspection", - "shortDescription": { - "text": "Invalid type hints definitions and usages" - }, - "fullDescription": { - "text": "Reports invalid usages of type hints. Example: 'from typing import TypeVar\n\nT0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\ndef b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\ndef c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass' Available quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown.", - "markdown": "Reports invalid usages of type hints.\n\n**Example:**\n\n\n from typing import TypeVar\n\n T0 = TypeVar('T1') # Argument of 'TypeVar' must be 'T0'\n\n\n def b(p: int) -> int: # Type specified both in a comment and annotation\n # type: (int) -> int\n pass\n\n\n def c(p1, p2): # Type signature has too many arguments\n # type: (int) -> int\n pass\n\nAvailable quick-fixes offer various actions. You can rename, remove, or move problematic elements. You can also manually modify type declarations to ensure no warning is shown." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTypeHints", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMethodMayBeStaticInspection", - "shortDescription": { - "text": "Method is not declared static" - }, - "fullDescription": { - "text": "Reports any methods that do not require a class instance creation and can be made static. Example: 'class MyClass(object):\n def my_method(self, x):\n print(x)' If a Make function from method quick-fix is applied, the code changes to: 'def my_method(x):\n print(x)\n\n\nclass MyClass(object):\n pass' If you select the Make method static quick-fix, the '@staticmethod' decorator is added: 'class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)'", - "markdown": "Reports any methods that do not require a class instance creation and can be\nmade static.\n\n**Example:**\n\n\n class MyClass(object):\n def my_method(self, x):\n print(x)\n\nIf a **Make function from method** quick-fix is applied, the code changes to:\n\n\n def my_method(x):\n print(x)\n\n\n class MyClass(object):\n pass\n\nIf you select the **Make method static** quick-fix, the `@staticmethod` decorator is added:\n\n\n class MyClass(object):\n @staticmethod\n def my_method(x):\n print(x)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyMethodMayBeStatic", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CythonUsageBeforeDeclarationInspection", - "shortDescription": { - "text": "Cython variable is used before its declaration" - }, - "fullDescription": { - "text": "Reports Cython variables being referenced before declaration. Example: 'cdef int c_x\n\nprint(c_x, c_y) # Variable 'c_y' is used before its declaration\n\ncdef int c_y = 0'", - "markdown": "Reports Cython variables being referenced before declaration.\n\n**Example:**\n\n\n cdef int c_x\n\n print(c_x, c_y) # Variable 'c_y' is used before its declaration\n\n cdef int c_y = 0\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "CythonUsageBeforeDeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDictCreationInspection", - "shortDescription": { - "text": "Dictionary creation can be rewritten by dictionary literal" - }, - "fullDescription": { - "text": "Reports situations when you can rewrite dictionary creation by using a dictionary literal. This approach brings performance improvements. Example: 'dic = {}\ndic['var'] = 1' When the quick-fix is applied, the code changes to: 'dic = {'var': 1}'", - "markdown": "Reports situations when you can rewrite dictionary creation\nby using a dictionary literal.\n\nThis approach brings performance improvements.\n\n**Example:**\n\n\n dic = {}\n dic['var'] = 1\n\nWhen the quick-fix is applied, the code changes to:\n\n\n dic = {'var': 1}\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyDictCreation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyStringFormatInspection", - "shortDescription": { - "text": "Errors in string formatting operations" - }, - "fullDescription": { - "text": "Reports errors in string formatting operations. Example 1: '\"Hello {1}\".format(\"people\")' Example 2: 'def bar():\n return 1\n\n\n\"%s %s\" % bar()' As a fix, you need to rewrite string formatting fragments to adhere to the formatting syntax.", - "markdown": "Reports errors in string formatting operations.\n\n**Example 1:**\n\n\n \"Hello {1}\".format(\"people\")\n\n**Example 2:**\n\n\n def bar():\n return 1\n\n\n \"%s %s\" % bar()\n\nAs a fix, you need to rewrite string formatting fragments to\nadhere to the [formatting syntax](https://docs.python.org/3/library/string.html#format-string-syntax)." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyStringFormat", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyExceptionInheritInspection", - "shortDescription": { - "text": "Exceptions do not inherit from standard 'Exception' class" - }, - "fullDescription": { - "text": "Reports cases when a custom exception class is raised but does not inherit from the builtin Exception class. Example: 'class A:\n pass\n\n\ndef me_exception():\n raise A()' The proposed quick-fix changes the code to: 'class A(Exception):\n pass\n\n\ndef me_exception():\n raise A()'", - "markdown": "Reports cases when a custom exception class is\nraised but does not inherit from the\n[builtin Exception class](https://docs.python.org/3/library/exceptions.html).\n\n**Example:**\n\n\n class A:\n pass\n\n\n def me_exception():\n raise A()\n\nThe proposed quick-fix changes the code to:\n\n\n class A(Exception):\n pass\n\n\n def me_exception():\n raise A()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyExceptionInherit", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyAssignmentToLoopOrWithParameterInspection", - "shortDescription": { - "text": "Assignments to 'for' loop or 'with' statement parameter" - }, - "fullDescription": { - "text": "Reports the cases when you rewrite a loop variable with an inner loop. Example: 'for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)' It also warns you if a variable declared in the 'with' statement is redeclared inside the statement body: 'with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:'", - "markdown": "Reports the cases when you rewrite a loop variable with an inner loop.\n\n**Example:**\n\n\n for i in range(5):\n for i in range(20, 25):\n print(\"Inner\", i)\n print(\"Outer\", i)\n \nIt also warns you if a variable declared in the `with` statement is redeclared inside the statement body:\n\n\n with open(\"file\") as f:\n f.read()\n with open(\"file\") as f:\n \n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyAssignmentToLoopOrWithParameter", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedFilterInspection", - "shortDescription": { - "text": "Unresolved filter" - }, - "fullDescription": { - "text": "Reports unresolved filters in Django templates. Example: '{{ my_value|cool_filter:\"arg\" }}'", - "markdown": "Reports unresolved filters in Django templates.\n\n**Example:**\n\n\n {{ my_value|cool_filter:\"arg\" }}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUnresolvedFilterInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "AppEngineThreadsafeCGIHandlerInspection", - "shortDescription": { - "text": "Threadsafe cannot be enabled with the CGI handler" - }, - "fullDescription": { - "text": "Reports cases when threadsafe is not enabled with the CGI handler.", - "markdown": "Reports cases when threadsafe is not enabled with the CGI handler." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "AppEngineThreadsafeCGIHandler", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedTagInspection", - "shortDescription": { - "text": "Unresolved tag" - }, - "fullDescription": { - "text": "Reports unresolved tags in Django templates. Example: '

{{ question.question_text }}

\n' The IDE highlights ''. You can either remove the tag or apply the quick-fix to add '' to custom HTML tags.", - "markdown": "Reports unresolved tags in Django templates.\n\n**Example:**\n\n\n

{{ question.question_text }}

\n \n\nThe IDE highlights ``. You can either remove the tag or apply the quick-fix to\nadd `` to custom HTML tags." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUnresolvedTagInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PySuperArgumentsInspection", - "shortDescription": { - "text": "Wrong arguments to call super" - }, - "fullDescription": { - "text": "Reports cases when any call to 'super(A, B)' does not meet the following requirements: 'B' is an instance of 'A' 'B' a subclass of 'A' Example: 'class Figure:\n def color(self):\n pass\n\n\nclass Rectangle(Figure):\n def color(self):\n pass\n\n\nclass Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle' As a fix, you can make the 'Square' an instance of the 'Rectangle' class.", - "markdown": "Reports cases when any call to `super(A, B)` does not meet the\nfollowing requirements:\n\n* `B` is an instance of `A`\n* `B` a subclass of `A`\n\n**Example:**\n\n\n class Figure:\n def color(self):\n pass\n\n\n class Rectangle(Figure):\n def color(self):\n pass\n\n\n class Square(Figure):\n def color(self):\n return super(Rectangle, self).color() # Square is not an instance or subclass of Rectangle\n\nAs a fix, you can make the `Square` an instance of the `Rectangle` class." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PySuperArguments", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoOrmInspection", - "shortDescription": { - "text": "Django ORM error" - }, - "fullDescription": { - "text": "Reports several methods that may not be called due to some ORM reasons. Example: 'class Choice:\n question = ForeignKey(Question, null=False)\n\n\nchoice_set = Question.objects.get(id=1).choice_set.remove()' The 'remove' function can not be called if the foreign key has 'null=False'.", - "markdown": "Reports several methods that may not be called due to some ORM reasons.\n\n**Example:**\n\n\n class Choice:\n question = ForeignKey(Question, null=False)\n\n\n choice_set = Question.objects.get(id=1).choice_set.remove()\n\nThe `remove` function can not be called if the foreign key has `null=False`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoOrm", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedTemplateReferenceInspection", - "shortDescription": { - "text": "Unresolved template reference" - }, - "fullDescription": { - "text": "Reports unresolved file references in string literals of 'extends'> and 'include'> Django tags. Example: '{% extends \"../DjangoApp/templatetags/base.html\"%}' In this example, the 'base.html' tag is highlighted, because it is not available in the specified location.", - "markdown": "Reports unresolved file references in string literals of\n`extends`\\> and `include`\\> Django tags.\n\n**Example:**\n\n\n {% extends \"../DjangoApp/templatetags/base.html\"%}\n\nIn this example, the `base.html` tag is highlighted, because it is not available in the\nspecified location." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUnresolvedTemplateReferenceInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyNonAsciiCharInspection", - "shortDescription": { - "text": "File contains non-ASCII character" - }, - "fullDescription": { - "text": "Reports cases in Python 2 when a file contains non-ASCII characters and does not have an encoding declaration at the top. Example: 'class A(object):\n# №5\n def __init__(self):\n pass' In this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding declaration. Apply the proposed quick-fix to add a missing encoding declaration: '# coding=utf-8\nclass A(object)\n# №5\n def __init__(self):\n pass'", - "markdown": "Reports cases in Python 2 when a file contains non-ASCII characters and does not\nhave an encoding declaration at the top.\n\n**Example:**\n\n\n class A(object):\n # №5\n def __init__(self):\n pass\n\nIn this example, the IDE reports a non-ASCII symbol in a comment and a lack of encoding\ndeclaration. Apply the proposed quick-fix to add a missing encoding declaration:\n\n\n # coding=utf-8\n class A(object)\n # №5\n def __init__(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyNonAsciiChar", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyOldStyleClassesInspection", - "shortDescription": { - "text": "Old-style class contains new-style class features" - }, - "fullDescription": { - "text": "Reports occurrences of new-style class features in old-style classes. The inspection highlights '__slots__', '__getattribute__', and 'super()' inside old-style classes.", - "markdown": "Reports occurrences of\n[new-style class features](https://www.python.org/doc/newstyle/)\nin old-style classes. The inspection highlights\n`__slots__`, `__getattribute__`, and `super()`\ninside old-style classes." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyOldStyleClasses", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyAbstractClassInspection", - "shortDescription": { - "text": "Class must implement all abstract methods" - }, - "fullDescription": { - "text": "Reports cases when not all abstract properties or methods are defined in a subclass. Example: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_triangle(self):\n pass' When the quick-fix is applied, the IDE implements an abstract method for the 'Triangle' class: 'from abc import abstractmethod, ABC\n\n\nclass Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\nclass Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass'", - "markdown": "Reports cases when not all abstract properties or methods are defined in\na subclass.\n\n**Example:**\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_triangle(self):\n pass\n\nWhen the quick-fix is applied, the IDE implements an abstract method for the `Triangle` class:\n\n\n from abc import abstractmethod, ABC\n\n\n class Figure(ABC):\n\n @abstractmethod\n def do_figure(self):\n pass\n\n\n class Triangle(Figure):\n def do_figure(self):\n pass\n\n def do_triangle(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyAbstractClass", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoIncompatibleInspection", - "shortDescription": { - "text": "Incompatible code in Django templates" - }, - "fullDescription": { - "text": "Reports features that are not available in the current Django version. Example: '{% if my_var is True %}\n{% endif %}' Available since 1.10. The IDE shows warning when discovered in the earlier versions.", - "markdown": "Reports features that are not available in the current Django version.\n\n**Example:**\n\n\n {% if my_var is True %}\n {% endif %}\n\nAvailable since 1.10. The IDE shows warning when discovered in the earlier versions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoIncompatibleInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Query_bound_parameters", - "shortDescription": { - "text": "Query does not have required bound parameters" - }, - "fullDescription": { - "text": "Reports GQL queries with bound parameters that don't have the necessary parameters passed to the query method call.", - "markdown": "Reports GQL queries with bound parameters that don't have the necessary\nparameters passed to the query method call." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "Query_bound_parameters", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyBroadExceptionInspection", - "shortDescription": { - "text": "Unclear exception clauses" - }, - "fullDescription": { - "text": "Reports exception clauses that do not provide specific information about the problem. Example: Clauses that do not specify an exception class Clauses that are specified as 'Exception'", - "markdown": "Reports exception clauses that do not provide specific information\nabout the problem.\n\n**Example:**\n\n* Clauses that do not specify an exception class\n* Clauses that are specified as `Exception`" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyBroadException", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTypeCheckerInspection", - "shortDescription": { - "text": "Incorrect type" - }, - "fullDescription": { - "text": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases. Types of function parameters can be specified in docstrings or in Python 3 function annotations. Example: 'def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\na: str\na = foo() # Expected str, got int' With the quick-fix, you can modify the problematic types: 'def foo() -> str:\n return \"abc\"\n\n\na: str\na = foo()'", - "markdown": "Reports type errors in function call expressions, targets, and return values. In a dynamically typed language, this is possible in a limited number of cases.\n\nTypes of function parameters can be specified in\ndocstrings or in Python 3 function annotations.\n\n**Example:**\n\n\n def foo() -> int:\n return \"abc\" # Expected int, got str\n\n\n a: str\n a = foo() # Expected str, got int\n\nWith the quick-fix, you can modify the problematic types:\n\n\n def foo() -> str:\n return \"abc\"\n\n\n a: str\n a = foo()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTypeChecker", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyByteLiteralInspection", - "shortDescription": { - "text": "A byte literal contains a non-ASCII character" - }, - "fullDescription": { - "text": "Reports characters in byte literals that are outside ASCII range. Example: 's = b'№5''", - "markdown": "Reports characters in byte literals that are outside ASCII range.\n\n**Example:**\n\n\n s = b'№5'\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyByteLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyAugmentAssignmentInspection", - "shortDescription": { - "text": "Assignment can be replaced with augmented assignment" - }, - "fullDescription": { - "text": "Reports assignments that can be replaced with augmented assignments. Example: 'a = 23\nb = 3\na = a + b' After the quick-fix is applied, the code changes to: 'a = 23\nb = 3\na += b'", - "markdown": "Reports assignments that can be replaced with augmented assignments.\n\n**Example:**\n\n\n a = 23\n b = 3\n a = a + b\n\nAfter the quick-fix is applied, the code changes to:\n\n\n a = 23\n b = 3\n a += b\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "PyAugmentAssignment", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDeprecationInspection", - "shortDescription": { - "text": "Deprecated function, class, or module" - }, - "fullDescription": { - "text": "Reports usages of Python functions, or methods that are marked as deprecated and raise the 'DeprecationWarning' or 'PendingDeprecationWarning' warning. Also, this inspection highlights usages of 'abc.abstractstaticmethod', 'abc.abstractproperty', and 'abc.abstractclassmethod' decorators. Example: 'class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\nfoo = Foo()\nprint(foo.bar)'", - "markdown": "Reports usages of Python functions, or methods that are marked as\ndeprecated and raise the `DeprecationWarning` or `PendingDeprecationWarning` warning.\n\nAlso, this inspection highlights usages of `abc.abstractstaticmethod`, `abc.abstractproperty`, and `abc.abstractclassmethod`\ndecorators.\n\n**Example:**\n\n\n class Foo:\n @property\n def bar(self):\n import warnings\n warnings.warn(\"this is deprecated\", DeprecationWarning, 2)\n return 5\n\n\n foo = Foo()\n print(foo.bar)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDeprecation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyUnnecessaryBackslashInspection", - "shortDescription": { - "text": "Unnecessary backslash" - }, - "fullDescription": { - "text": "Reports backslashes in places where line continuation is implicit inside '()', '[]', and '{}'. Example: 'a = ('first', \\\n 'second', 'third')' When the quick-fix is applied, the redundant backslash is deleted.", - "markdown": "Reports backslashes in places where line continuation is implicit inside `()`,\n`[]`, and `{}`.\n\n**Example:**\n\n\n a = ('first', \\\n 'second', 'third')\n\nWhen the quick-fix is applied, the redundant backslash is deleted." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyUnnecessaryBackslash", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyShadowingNamesInspection", - "shortDescription": { - "text": "Shadowing names from outer scopes" - }, - "fullDescription": { - "text": "Reports shadowing names defined in outer scopes. Example: 'def outer(p):\n def inner(p):\n pass' As a quick-fix, the IDE offers to remove a parameter or rename it.", - "markdown": "Reports shadowing names defined in outer scopes.\n\n**Example:**\n\n\n def outer(p):\n def inner(p):\n pass\n\nAs a quick-fix, the IDE offers to remove a parameter or rename it." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyShadowingNames", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyFinalInspection", - "shortDescription": { - "text": "Invalid usages of final classes, methods, and variables" - }, - "fullDescription": { - "text": "Reports invalid usages of final classes, methods and variables. Example: 'from typing import final\n\n\n@final\nclass A:\n def a_method(self):\n pass\n\n\nclass B(A):\n def a_method(self):\n pass'", - "markdown": "Reports invalid usages of final classes,\nmethods and variables.\n\n**Example:**\n\n\n from typing import final\n\n\n @final\n class A:\n def a_method(self):\n pass\n\n\n class B(A):\n def a_method(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyFinal", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoCloseTagInspection", - "shortDescription": { - "text": "Mismatched opening and closing tags" - }, - "fullDescription": { - "text": "Reports cases when opening tags in Django templates are not correctly matched by closing tags. Example: '{% if error_message %}

{{ error_message }}

{% endif %}' The IDE reports an error on the 'strong' tag not being closed.", - "markdown": "Reports cases when opening tags in Django templates are not correctly matched by closing tags.\n\n**Example:**\n\n\n {% if error_message %}

{{ error_message }}

{% endif %}\n\nThe IDE reports an error on the `strong` tag not being closed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoCloseTagInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PySingleQuotedDocstringInspection", - "shortDescription": { - "text": "Single quoted docstring" - }, - "fullDescription": { - "text": "Reports docstrings that do not adhere to the triple double-quoted string format. Example: 'def calc(self, balance=0):\n 'param: balance'\n self.balance = balance' When the quick-fix is applied, the code changes to: 'def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance'", - "markdown": "Reports docstrings that do not adhere to the triple double-quoted string format.\n\n**Example:**\n\n\n def calc(self, balance=0):\n 'param: balance'\n self.balance = balance\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def calc(self, balance=0):\n \"\"\"param: balance\"\"\"\n self.balance = balance\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PySingleQuotedDocstring", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyUnusedLocalInspection", - "shortDescription": { - "text": "Unused local symbols" - }, - "fullDescription": { - "text": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function.", - "markdown": "Reports local variables, parameters, and functions that are locally defined, but not used name in a function." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyUnusedLocal", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyReturnFromInitInspection", - "shortDescription": { - "text": "__init__ method that returns a value" - }, - "fullDescription": { - "text": "Reports occurrences of 'return' statements with a return value inside '__init__' methods of classes. Example: 'class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum' A constructor should not return any value. The '__init__' method should only initialize the values of instance members for news objects. As a quick-fix, the IDE offers to remove the 'return' statement.", - "markdown": "Reports occurrences of `return` statements with a return value inside\n`__init__` methods of classes.\n\n**Example:**\n\n\n class Sum:\n def __init__(self, a, b):\n self.a = a\n self.b = b\n self.sum = a + b\n return self.sum\n\nA constructor should not return any value. The `__init__` method should\nonly initialize the values of instance members for news objects.\n\nAs a quick-fix, the IDE offers to remove the `return` statement." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyReturnFromInit", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Query_restricted", - "shortDescription": { - "text": "Query does not comply with the query restrictions" - }, - "fullDescription": { - "text": "Reports GQL queries that do not comply with the restrictions for queries allowed on the Google App Engine server. See the App Engine documentation for more information.", - "markdown": "Reports GQL queries that do not comply with the restrictions for queries allowed\non the Google App Engine server.\nSee the [App Engine documentation](http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html#Restrictions_on_Queries) for more information." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "Query_restricted", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMissingOrEmptyDocstringInspection", - "shortDescription": { - "text": "Missing or empty docstring" - }, - "fullDescription": { - "text": "Reports missing and empty docstrings. Example of a missing docstring 'def demo(a):\n c = a ** 2' Example of an empty docstring 'def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2' When the quick-fix is applied, the code fragments change to: 'def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2' You need to provide some details about the parameter in the generated template.", - "markdown": "Reports missing and empty docstrings.\n\n**Example of a missing docstring**\n\n\n def demo(a):\n c = a ** 2\n\n**Example of an empty docstring**\n\n\n def demo(a):\n \"\"\"\n \"\"\"\n c = a ** 2\n\nWhen the quick-fix is applied, the code fragments change to:\n\n\n def demo(a):\n \"\"\"\n\n :param a:\n \"\"\"\n c = a ** 2\n\nYou need to provide some details about the parameter in the generated template." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "PyMissingOrEmptyDocstring", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyPep8NamingInspection", - "shortDescription": { - "text": "PEP 8 naming convention violation" - }, - "fullDescription": { - "text": "Reports violations of the PEP8 naming conventions. Example: 'class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")' In this code fragment, IDE offers to rename 'mammalia' to 'Mammalia'. When the quick-fix is applied, the code change to: 'class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")'", - "markdown": "Reports violations of the\n[PEP8](https://www.python.org/dev/peps/pep-0008/) naming conventions.\n\n**Example:**\n\n\n class mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n\nIn this code fragment, IDE offers to rename `mammalia` to `Mammalia`.\nWhen the quick-fix is applied, the code change to:\n\n\n class Mammalia(object):\n extremities = 4\n\n def feeds(self):\n print(\"milk\")\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyPep8Naming", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedLoadInspection", - "shortDescription": { - "text": "Unresolved library inspection" - }, - "fullDescription": { - "text": "Reports unresolved references in Django load tags. Example: '{% load something_nonexistent %}'", - "markdown": "Reports unresolved references in Django load tags.\n\n**Example:**\n\n\n {% load something_nonexistent %}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUnresolvedLoadInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDictDuplicateKeysInspection", - "shortDescription": { - "text": "Dictionary contains duplicate keys" - }, - "fullDescription": { - "text": "Reports using the same value as the dictionary key twice. Example: 'dic = {\"a\": [1, 2], \"a\": [3, 4]}'", - "markdown": "Reports using the same value as the dictionary key twice.\n\n**Example:**\n\n\n dic = {\"a\": [1, 2], \"a\": [3, 4]}\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDictDuplicateKeys", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyNoneFunctionAssignmentInspection", - "shortDescription": { - "text": "Assigning function calls that don't return anything" - }, - "fullDescription": { - "text": "Reports cases when an assignment is done on a function that does not return anything. This inspection is similar to pylint inspection E1111. Example: 'def just_print():\n print(\"Hello!\")\n\n\naction = just_print()' As a quick-fix, the IDE offers to remove the assignment.", - "markdown": "Reports cases when an assignment is done on a function that does not return anything.\nThis inspection is similar to [pylint inspection E1111](https://docs.pylint.org/en/1.6.0/features.html#id6).\n\n**Example:**\n\n\n def just_print():\n print(\"Hello!\")\n\n\n action = just_print()\n\nAs a quick-fix, the IDE offers to remove the assignment." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyNoneFunctionAssignment", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JupyterPackageInspection", - "shortDescription": { - "text": "The 'jupyter' package is not installed" - }, - "fullDescription": { - "text": "Reports cases when the 'jupyter' package is not installed for the selected Python interpreter. Without a properly installed 'jupyter' package, you cannot execute Jupyter notebooks. Click the corresponding link on the warning banner to install the missing package. You can also install the package in the Project Settings/Preferences or in the Python Packages tool window. See Installing Python package for more details.", - "markdown": "Reports cases when the `jupyter` package is not installed for the selected\nPython interpreter. Without a properly installed `jupyter` package, you cannot\nexecute Jupyter notebooks.\n\nClick the corresponding link on the warning banner to install the missing\npackage. You can also install the package in the Project **Settings/Preferences** or in the\n**Python Packages** tool window.\n\nSee [Installing Python package](https://www.jetbrains.com/help/pycharm/installing-uninstalling-and-upgrading-packages.html) for more details." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JupyterPackage", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Jupyter", - "index": 58, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyStatementEffectInspection", - "shortDescription": { - "text": "Statement has no effect" - }, - "fullDescription": { - "text": "Reports statements that have no effect. Example: 'class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n2 + 3 # has no effect' In this example, you can either add a field 'time' to the 'Car' class or introduce variables for the problematic statements.", - "markdown": "Reports statements that have no effect.\n\n**Example:**\n\n\n class Car:\n def __init__(self, speed=0):\n self.speed = speed\n self.time # has no effect\n\n 2 + 3 # has no effect\n\nIn this example, you can either add a field `time` to the `Car` class or\nintroduce variables for the problematic statements." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyStatementEffect", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMandatoryEncodingInspection", - "shortDescription": { - "text": "No encoding specified for file" - }, - "fullDescription": { - "text": "Reports a missing encoding comment in Python 2. Example: 'class Book(object):\n def __init__(self):\n pass' When the quick-fix is applied, the missing comment is added: '# coding=utf-8\nclass Book(object):\n def __init__(self):\n pass'", - "markdown": "Reports a missing encoding comment in Python 2.\n\n**Example:**\n\n\n class Book(object):\n def __init__(self):\n pass\n\nWhen the quick-fix is applied, the missing comment is added:\n\n\n # coding=utf-8\n class Book(object):\n def __init__(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyMandatoryEncoding", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyInconsistentIndentationInspection", - "shortDescription": { - "text": "Inconsistent indentation" - }, - "fullDescription": { - "text": "Reports inconsistent indentation in Python source files when, for example, you use a mixture of tabs and spaces in your code.", - "markdown": "Reports inconsistent indentation in Python source files when, for example,\nyou use a mixture of tabs and spaces in your code." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyInconsistentIndentation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyAttributeOutsideInitInspection", - "shortDescription": { - "text": "An instance attribute is defined outside `__init__`" - }, - "fullDescription": { - "text": "Reports a problem when instance attribute definition is outside '__init__' method. Example: 'class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'' When the quick-fix is applied, the code sample changes to: 'class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass'", - "markdown": "Reports a problem when instance attribute definition is outside `__init__` method.\n\n**Example:**\n\n\n class Book:\n def __init__(self):\n self.author = 'Mark Twain'\n\n def release(self):\n self.year = '1889'\n\n\nWhen the quick-fix is applied, the code sample changes to:\n\n\n class Book:\n def __init__(self):\n self.year = '1889'\n self.author = 'Mark Twain'\n\n def release(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyAttributeOutsideInit", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTypedDictInspection", - "shortDescription": { - "text": "Invalid TypedDict definition and usages" - }, - "fullDescription": { - "text": "Reports invalid definition and usage of TypedDict. Example: 'from typing import TypedDict\n\n\nclass Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\nm = Movie(name=\"name\", year=1000, rate=9)\nprint(m[\"director\"]) # There is no the 'director' key in 'Movie'\ndel m[\"name\"] # The 'name' key cannot be deleted\nm[\"year\"] = \"1001\" # Expected 'int', got 'str''", - "markdown": "Reports invalid definition and usage of\n[TypedDict](https://www.python.org/dev/peps/pep-0589/).\n\n**Example:**\n\n\n from typing import TypedDict\n\n\n class Movie(TypedDict):\n name: str\n year: int\n rate: int = 10 # Right-hand side values are not supported\n\n def method(self): # Invalid statement in TypedDict\n pass\n\n\n m = Movie(name=\"name\", year=1000, rate=9)\n print(m[\"director\"]) # There is no the 'director' key in 'Movie'\n del m[\"name\"] # The 'name' key cannot be deleted\n m[\"year\"] = \"1001\" # Expected 'int', got 'str'\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTypedDict", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyPep8Inspection", - "shortDescription": { - "text": "PEP 8 coding style violation" - }, - "fullDescription": { - "text": "Reports violations of the PEP 8 coding style guide by running the bundled pycodestyle.py tool.", - "markdown": "Reports violations of the [PEP 8 coding style guide](https://www.python.org/dev/peps/pep-0008/) by running the bundled [pycodestyle.py](https://github.com/PyCQA/pycodestyle) tool." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyPep8", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMissingTypeHintsInspection", - "shortDescription": { - "text": "Missing type hinting for function definition" - }, - "fullDescription": { - "text": "Reports missing type hints for function declaration in one of the two formats: parameter annotations or a type comment. Select the Only when types are known checkbox if you want the inspection check the types collected from runtime or inferred.", - "markdown": "Reports missing type hints for function declaration in\none of the two formats: parameter annotations or a type comment.\n\nSelect the **Only when types are known** checkbox if you want the inspection check\nthe types collected from runtime or inferred." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "PyMissingTypeHints", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTupleItemAssignmentInspection", - "shortDescription": { - "text": "Tuple item assignment is prohibited" - }, - "fullDescription": { - "text": "Reports assignments to a tuple item. Example: 't = ('red', 'blue', 'green', 'white')\nt[3] = 'black'' A quick-fix offers to replace the tuple with a list.", - "markdown": "Reports assignments to a tuple item.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n t[3] = 'black'\n\nA quick-fix offers to replace the tuple with a list." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTupleItemAssignment", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedUrlInspection", - "shortDescription": { - "text": "Django {% url %} tag arguments are unresolved" - }, - "fullDescription": { - "text": "Reports a missing url in the 'url' tag. Example: '{% url 'url_name' %}' The IDE shows a warning if 'url_name' is not defined in the 'urls' file.", - "markdown": "Reports a missing url in the `url` tag.\n\n**Example:**\n\n\n {% url 'url_name' %}\n\nThe IDE shows a warning if `url_name` is not defined in the `urls` file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "DjangoUnresolvedUrlInspection", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUnresolvedStaticReferenceInspection", - "shortDescription": { - "text": "Unresolved static reference" - }, - "fullDescription": { - "text": "Reports unresolved references to static resources. Example: '{% load staticfiles %}\n' In this example, 'style.css' is highlighted if there is no such a file in the 'static/poll' directory.", - "markdown": "Reports unresolved references to static resources.\n\n**Example:**\n\n\n {% load staticfiles %}\n \n\nIn this example, `style.css` is highlighted if there is no such a file in the `static/poll`\ndirectory." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUnresolvedStaticReferenceInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDunderSlotsInspection", - "shortDescription": { - "text": "Invalid usages of classes with '__slots__' definitions" - }, - "fullDescription": { - "text": "Reports invalid usages of a class with '__slots__' definitions. Example: 'class Foo:\n __slots__ = ['foo', 'bar']\n\n\nfoo = Foo()\nfoo.baz = 'spam''", - "markdown": "Reports invalid usages of a class with `__slots__` definitions.\n\n**Example:**\n\n\n class Foo:\n __slots__ = ['foo', 'bar']\n\n\n foo = Foo()\n foo.baz = 'spam'\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDunderSlots", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDefaultArgumentInspection", - "shortDescription": { - "text": "The default argument is mutable" - }, - "fullDescription": { - "text": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for an argument. Default argument values are evaluated only once at function definition time, which means that modifying the default value of the argument will affect all subsequent calls of that function. Example: 'def func(s, cache={}):\n cache[s] = None' When the quick-fix is applied, the code changes to: 'def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None'", - "markdown": "Reports a problem when a mutable value as a list or dictionary is detected in a default value for\nan argument. \n\nDefault argument values are evaluated only once at function definition time,\nwhich means that modifying the\ndefault value of the argument will affect all subsequent calls of that function.\n\n**Example:**\n\n\n def func(s, cache={}):\n cache[s] = None\n\nWhen the quick-fix is applied, the code changes to:\n\n\n def func(s, cache=None):\n if cache is None:\n cache = {}\n cache[s] = None\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDefaultArgument", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyShadowingBuiltinsInspection", - "shortDescription": { - "text": "Shadowing built-in names" - }, - "fullDescription": { - "text": "Reports shadowing built-in names, such as 'len' or 'list'. Example: 'def len(a, b, c):\n d = a + b + c\n return d' In this code fragment, the 'len' built-in name is used. The IDE offers to apply the Rename refactoring as a fix.", - "markdown": "Reports shadowing built-in names, such as `len` or `list`.\n\n**Example:**\n\n\n def len(a, b, c):\n d = a + b + c\n return d\n\nIn this code fragment, the `len` built-in name is used. The IDE offers to\napply the Rename refactoring as a fix." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyShadowingBuiltins", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMethodOverridingInspection", - "shortDescription": { - "text": "Method signature does not match signature of overridden method" - }, - "fullDescription": { - "text": "Reports inconsistencies in overriding method signatures. Example: 'class Book:\n def add_title(self):\n pass\n\n\nclass Novel(Book):\n def add_title(self, text):\n pass' Parameters of the 'add_title' method in the 'Novel' class do not match the method signature specified in the 'Book' class. As a fix, the IDE offers to apply the Change Signature refactoring.", - "markdown": "Reports inconsistencies in overriding method signatures.\n\n**Example:**\n\n\n class Book:\n def add_title(self):\n pass\n\n\n class Novel(Book):\n def add_title(self, text):\n pass\n\nParameters of the `add_title` method in the `Novel` class do not match the method\nsignature specified in the `Book` class. As a fix, the IDE offers to apply the Change Signature\nrefactoring." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyMethodOverriding", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTestParametrizedInspection", - "shortDescription": { - "text": "Incorrect arguments in @pytest.mark.parametrize" - }, - "fullDescription": { - "text": "Reports functions that are decorated with @pytest.mark.parametrize but do not have arguments to accept parameters of the decorator.", - "markdown": "Reports functions that are decorated with [@pytest.mark.parametrize](https://docs.pytest.org/en/stable/parametrize.html) but do not have arguments to accept\nparameters of the decorator." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTestParametrized", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDecoratorInspection", - "shortDescription": { - "text": "Class-specific decorator is used outside the class" - }, - "fullDescription": { - "text": "Reports usages of '@classmethod' or '@staticmethod' decorators in methods outside a class. Example: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n@classmethod\ndef change_state(self):\n pass' The 'change_state' method should not use the '@classmethod' decorator or it should be moved to the 'State' class declaration. If you apply the 'Remove decorator' action, the code changes to: 'class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\ndef change_state(self):\n pass'", - "markdown": "Reports usages of `@classmethod` or `@staticmethod` decorators\nin methods outside a class.\n\n**Example:**\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n @classmethod\n def change_state(self):\n pass\n\nThe `change_state` method should not use the `@classmethod` decorator or it should be\nmoved to the `State` class declaration.\n\nIf you apply the `Remove decorator` action, the code changes to:\n\n\n class State(object):\n\n @classmethod\n def my_state(cls, name):\n cls.name = name\n\n\n def change_state(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDecorator", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyAsyncCallInspection", - "shortDescription": { - "text": "Missing `await` syntax in coroutine calls" - }, - "fullDescription": { - "text": "Reports coroutines that were called without using the 'await' syntax. Example: 'async def bar():\n pass\n\n\nasync def foo():\n bar()' After the quick-fix is applied, the code changes to: 'async def bar():\n pass\n\n\nasync def foo():\n await bar()'", - "markdown": "Reports coroutines that were called\nwithout using the `await` syntax.\n\n**Example:**\n\n\n async def bar():\n pass\n\n\n async def foo():\n bar()\n\nAfter the quick-fix is applied, the code changes to:\n\n\n async def bar():\n pass\n\n\n async def foo():\n await bar()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyAsyncCall", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CommandLineInspection", - "shortDescription": { - "text": "Incorrect CLI syntax" - }, - "fullDescription": { - "text": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies that option names and arguments are correct. Do not disable the inspection if you are going to use command-line interfaces like manage.py in Django.", - "markdown": "Reports the problems if the arguments of the command you type in the console are not in the proper order. The inspection also verifies\nthat option names and arguments are correct.\n\nDo not disable the inspection if you are going to use command-line interfaces like [manage.py in Django](https://www.jetbrains.com/help/pycharm/running-manage-py.html)." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "CommandLineInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyComparisonWithNoneInspection", - "shortDescription": { - "text": "Using equality operators to compare with None" - }, - "fullDescription": { - "text": "Reports comparisons with 'None'. That type of comparisons should always be done with 'is' or 'is not', never the equality operators. Example: 'a = 2\n\n\nif a == None:\n print(\"Success\")' Once the quick-fix is applied, the code changes to: 'a = 2\n\n\nif a is None:\n print(\"Success\")'", - "markdown": "Reports comparisons with `None`. That type of comparisons\nshould always be done with `is` or `is not`, never\nthe equality operators.\n\n**Example:**\n\n\n a = 2\n\n\n if a == None:\n print(\"Success\")\n\nOnce the quick-fix is applied, the code changes to:\n\n\n a = 2\n\n\n if a is None:\n print(\"Success\")\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyComparisonWithNone", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMethodParametersInspection", - "shortDescription": { - "text": "Improper first parameter" - }, - "fullDescription": { - "text": "Reports methods that lack the first parameter that is usually named 'self'. Example: 'class Movie:\n\n def show():\n pass' When the quick-fix is applied, the code changes to: 'class Movie:\n\n def show(self):\n pass' The inspection also reports naming issues in class methods. Example: 'class Movie:\n @classmethod\n def show(abc):\n pass' Since the first parameter of a class method should be 'cls', the IDE provides a quick-fix to rename it.", - "markdown": "Reports methods that lack the first parameter that is usually\nnamed `self`.\n\n**Example:**\n\n\n class Movie:\n\n def show():\n pass\n\nWhen the quick-fix is applied, the code changes to:\n\n\n class Movie:\n\n def show(self):\n pass\n\nThe inspection also reports naming issues in class methods.\n\n**Example:**\n\n\n class Movie:\n @classmethod\n def show(abc):\n pass\n\nSince the first parameter of a class method should be `cls`, the IDE provides a quick-fix\nto rename it." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyMethodParameters", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDocstringTypesInspection", - "shortDescription": { - "text": "Type in docstring does not match inferred type" - }, - "fullDescription": { - "text": "Reports types in docstring that do not match dynamically inferred types.", - "markdown": "Reports types in docstring that do not match dynamically inferred types." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyDocstringTypes", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyMethodFirstArgAssignmentInspection", - "shortDescription": { - "text": "First argument of the method is reassigned" - }, - "fullDescription": { - "text": "Reports cases when the first parameter, such as 'self' or 'cls', is reassigned in a method. Because in most cases, there are no objectives in such reassignment, the IDE indicates an error. Example: 'class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self' As a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct, you can invoke intention actions for this code and opt to ignore the warning.", - "markdown": "Reports cases when the first parameter,\nsuch as `self` or `cls`, is reassigned in a method.\nBecause in most cases, there are no objectives in such reassignment, the\nIDE indicates an error.\n\n**Example:**\n\n\n class Account:\n def calc(self, balance):\n if balance == 0:\n self = balance\n return self\n\nAs a fix, you might want to check and modify the algorithm to ensure that reassignment is needed. If everything is correct,\nyou can invoke intention actions for this code and opt to ignore the warning." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyMethodFirstArgAssignment", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTupleAssignmentBalanceInspection", - "shortDescription": { - "text": "Tuple assignment balance is incorrect" - }, - "fullDescription": { - "text": "Reports cases when the number of expressions on the right-hand side and targets on the left-hand side are not the same. Example: 't = ('red', 'blue', 'green', 'white')\n(c1, c2, c3) = t' As a quick-fix, you can modify the highlighted code fragment to restore the tuple balance.", - "markdown": "Reports cases when the number of expressions on the right-hand side\nand targets on the left-hand side are not the same.\n\n**Example:**\n\n\n t = ('red', 'blue', 'green', 'white')\n (c1, c2, c3) = t\n\nAs a quick-fix, you can modify the highlighted code fragment to restore the tuple\nbalance." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTupleAssignmentBalance", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyClassHasNoInitInspection", - "shortDescription": { - "text": "Class has no `__init__` method" - }, - "fullDescription": { - "text": "Reports cases in Python 2 when a class has no '__init__' method, neither its parent classes. Example: 'class Book():\n pass' The quick-fix adds the '__init__' method: 'class Book():\n def __init__(self):\n pass'", - "markdown": "Reports cases in Python 2 when a class has no `__init__` method, neither its parent\nclasses.\n\n**Example:**\n\n\n class Book():\n pass\n\nThe quick-fix adds the `__init__` method:\n\n\n class Book():\n def __init__(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyClassHasNoInit", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyArgumentEqualDefaultInspection", - "shortDescription": { - "text": "The function argument is equal to the default parameter value" - }, - "fullDescription": { - "text": "Reports a problem when an argument passed to the function is equal to the default parameter value. This inspection is disabled by default to avoid performance degradation. Example: 'def my_function(a: int = 2):\n print(a)\n\n\nmy_function(2)'", - "markdown": "Reports a problem when an argument\npassed to the function is equal to the default parameter value.\n\nThis inspection is disabled by default to avoid performance degradation.\n\n**Example:**\n\n\n def my_function(a: int = 2):\n print(a)\n\n\n my_function(2)\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "PyArgumentEqualDefault", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyClassVarInspection", - "shortDescription": { - "text": "Invalid usage of ClassVar variables" - }, - "fullDescription": { - "text": "Reports invalid usages of ClassVar annotations. Example: 'from typing import ClassVar\n\n\nclass Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\nCat.color = \"black\" # OK\nmy_cat = Cat(5)\nmy_cat.color = \"gray\" # Error, setting class variable on instance'", - "markdown": "Reports invalid usages of [ClassVar](https://docs.python.org/3/library/typing.html#typing.ClassVar) annotations.\n\n**Example:**\n\n\n from typing import ClassVar\n\n\n class Cat:\n color: ClassVar[str] = \"white\"\n weight: int\n\n def __init__(self, weight: int):\n self.weight = weight\n\n\n Cat.color = \"black\" # OK\n my_cat = Cat(5)\n my_cat.color = \"gray\" # Error, setting class variable on instance\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyClassVar", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoRelationInspection", - "shortDescription": { - "text": "Incorrect comparison expression in Django templates" - }, - "fullDescription": { - "text": "Reports missing whitespaces before and after comparison operators in Django templates. Example: '{% if my_var==1 %}\n{% endif %}'", - "markdown": "Reports missing whitespaces before and after comparison operators in Django templates.\n\n**Example:**\n\n\n {% if my_var==1 %}\n {% endif %}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoRelationInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyFromFutureImportInspection", - "shortDescription": { - "text": "Improper position of from __future__ import" - }, - "fullDescription": { - "text": "Reports 'from __future__ import' statements that are used not at the beginning of a file. Example: 'a = 1\nfrom __future__ import print_function\nprint()' When the quick-fix is applied, the code changes to: 'from __future__ import print_function\n\na = 1\nprint()'", - "markdown": "Reports `from __future__ import`\nstatements that are used not at\nthe beginning of a file.\n\n**Example:**\n\n\n a = 1\n from __future__ import print_function\n print()\n\nWhen the quick-fix is applied, the code changes to:\n\n\n from __future__ import print_function\n\n a = 1\n print()\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyFromFutureImport", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyUnresolvedReferencesInspection", - "shortDescription": { - "text": "Unresolved references" - }, - "fullDescription": { - "text": "Reports references in your code that cannot be resolved. In a dynamically typed language, this is possible in a limited number of cases. If a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be: 'def print_string(s):\n print(s.abc())' In this code fragment 's' is always a string and 'abc' should be highlighted as unresolved. However, 's' type is inferred as 'Any' and no warning is reported. The IDE provides quick-fix actions to add missing references on-the-fly.", - "markdown": "Reports references in your code that cannot be resolved.\n\nIn a dynamically typed language, this is possible in a limited number of cases.\n\nIf a reference type is unknown, then its attributes are not highlighted as unresolved even if you know that they should be:\n\n\n def print_string(s):\n print(s.abc())\n\nIn this code fragment `s` is always a string and `abc` should be highlighted as unresolved. However, `s`\ntype is inferred as `Any` and no warning is reported.\n\nThe IDE provides quick-fix actions to add missing references on-the-fly." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyUnresolvedReferences", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyPackageRequirementsInspection", - "shortDescription": { - "text": "Unsatisfied package requirements" - }, - "fullDescription": { - "text": "Reports packages mentioned in requirements files (for example, 'requirements.txt' or 'Pipfile') but not installed, or imported but not mentioned in requirements files. The IDE shows a quick-fix banner so that you can install the missing packages in one click.", - "markdown": "Reports packages mentioned in requirements files (for example, `requirements.txt` or `Pipfile`) but not installed,\nor imported but not mentioned in requirements files.\n\n\nThe IDE shows a quick-fix banner so that you can install the missing packages in one click." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyPackageRequirements", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Restricted_Python_calls", - "shortDescription": { - "text": "Feature is not supported in the App Engine sandbox" - }, - "fullDescription": { - "text": "Reports usages of Python features that are restricted by the Google App Engine sandbox and will cause a failure on the production server.", - "markdown": "Reports usages of Python features that are restricted by the Google App\nEngine sandbox and will cause a failure on the production server." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "Restricted_Python_calls", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyTrailingSemicolonInspection", - "shortDescription": { - "text": "Prohibited trailing semicolon in a statement" - }, - "fullDescription": { - "text": "Reports trailing semicolons in statements. Example: 'def my_func(a):\n c = a ** 2;\n return c' IDE provides a quick-fix that removes a trailing semicolon. When you apply it, the code changes to: 'def my_func(a):\n c = a ** 2\n return c'", - "markdown": "Reports trailing semicolons in statements.\n\n**Example:**\n\n\n def my_func(a):\n c = a ** 2;\n return c\n\nIDE provides a quick-fix that removes a trailing semicolon. When you\napply it, the code changes to:\n\n\n def my_func(a):\n c = a ** 2\n return c\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyTrailingSemicolon", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyRedundantParenthesesInspection", - "shortDescription": { - "text": "Redundant parentheses" - }, - "fullDescription": { - "text": "Reports about redundant parentheses in expressions. The IDE provides the quick-fix action to remove the redundant parentheses.", - "markdown": "Reports about redundant parentheses in expressions.\n\nThe IDE provides the quick-fix action to remove the redundant parentheses." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyRedundantParentheses", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ExtendsTagPositionInspection", - "shortDescription": { - "text": "Misplaced {% extends %} tag" - }, - "fullDescription": { - "text": "Reports the '{% extends %}' tag that is not the first tag in a Django template. Example: '{% load my_custom_tags %}\n{% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}' In this example, the '{% extends %}' tag is highlighted, because it should be placed before the '{% load %}' tag.", - "markdown": "Reports the `{% extends %}` tag that is not the first tag in a\nDjango template.\n\n**Example:**\n\n\n {% load my_custom_tags %}\n {% extends \"../DjangoApp/templatetags/my_custom_tags.py\"%}\n\nIn this example, the `{% extends %}` tag is highlighted, because it should be placed before\nthe `{% load %}` tag." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ExtendsTagPositionInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyArgumentListInspection", - "shortDescription": { - "text": "Incorrect call arguments" - }, - "fullDescription": { - "text": "Reports discrepancies between declared parameters and actual arguments, as well as incorrect arguments, for example, duplicate named arguments, and incorrect argument order. Example: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__() # unfilled parameter\nbar(5, \"#\") # unexpected argument' The correct code fragment looks at follows: 'class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\nbar = Foo()\nbar.__call__(5)\nbar(5, p2=\"#\")'", - "markdown": "Reports discrepancies between declared parameters and actual arguments, as well as\nincorrect arguments, for example, duplicate named arguments, and incorrect argument order.\n\n**Example:**\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__() # unfilled parameter\n bar(5, \"#\") # unexpected argument\n\nThe correct code fragment looks at follows:\n\n\n class Foo:\n def __call__(self, p1: int, *, p2: str = \"%\"):\n return p2 * p1\n\n\n bar = Foo()\n bar.__call__(5)\n bar(5, p2=\"#\")\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyArgumentList", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyInterpreterInspection", - "shortDescription": { - "text": "An invalid interpreter" - }, - "fullDescription": { - "text": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly configured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features. The IDE provides quick access to the interpreter settings.", - "markdown": "Reports problems if there is no Python interpreter configured for the project or if the interpreter is invalid. Without a properly\nconfigured interpreter, you cannot execute your Python scripts and benefit from some Python code insight features.\n\nThe IDE provides quick access to the interpreter settings." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyInterpreter", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyPropertyAccessInspection", - "shortDescription": { - "text": "Inappropriate access to properties" - }, - "fullDescription": { - "text": "Reports cases when properties are accessed inappropriately: Read-only properties are set Write-only properties are read Non-deletable properties are deleted Example: 'class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\na = MyClass()\na.read_only = 10 # property cannot be set\ndel a.read_only # property cannot be deleted\nprint(a.write_only) # property cannot be read'", - "markdown": "Reports cases when properties are accessed inappropriately:\n\n* Read-only properties are set\n* Write-only properties are read\n* Non-deletable properties are deleted\n\n**Example:**\n\n\n class MyClass:\n @property\n def read_only(self): return None\n\n def __write_only_setter(self, value): pass\n\n write_only = property(None, __write_only_setter)\n\n\n a = MyClass()\n a.read_only = 10 # property cannot be set\n del a.read_only # property cannot be deleted\n print(a.write_only) # property cannot be read\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyPropertyAccess", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyStubPackagesAdvertiser", - "shortDescription": { - "text": "Stub packages advertiser" - }, - "fullDescription": { - "text": "Reports availability of stub packages. Stub package is a package that contains type information for the corresponding runtime package. Using stub packages ensures better coding assistance for the corresponding python package.", - "markdown": "Reports availability of stub packages.\n\n\n[Stub package](https://www.python.org/dev/peps/pep-0561/) is a package that contains type information for the corresponding\nruntime package.\n\nUsing stub packages ensures better coding assistance for the corresponding python package." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyStubPackagesAdvertiser", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyRelativeImportInspection", - "shortDescription": { - "text": "Suspicious relative imports" - }, - "fullDescription": { - "text": "Reports usages of relative imports inside plain directories, for example, directories neither containing '__init__.py' nor explicitly marked as namespace packages.", - "markdown": "Reports usages of relative imports inside plain directories, for example, directories neither containing `__init__.py` nor\nexplicitly marked as namespace packages." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyPackages", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyRedeclarationInspection", - "shortDescription": { - "text": "Redeclared names without usages" - }, - "fullDescription": { - "text": "Reports unconditional redeclarations of names without being used in between. Example: 'def x(): pass\n\n\nx = 2' It applies to function and class declarations, and top-level assignments. When the warning is shown, you can try a recommended action, for example, you might be prompted to rename the variable.", - "markdown": "Reports unconditional redeclarations of names without being used in between.\n\n**Example:**\n\n\n def x(): pass\n\n\n x = 2\n\nIt applies to function and class declarations, and top-level assignments.\n\nWhen the warning is shown, you can try a recommended action, for example, you might be prompted to\nrename the variable." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyRedeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyramidSetupInspection", - "shortDescription": { - "text": "Project is not installed for development" - }, - "fullDescription": { - "text": "Reports cases when no 'python setup.py develop' command was executed for the Pyramid project. You need to execute this command to install the newly created project for development.", - "markdown": "Reports cases when no `python setup.py develop` command was executed for the Pyramid project.\n\nYou need to execute this command to install the newly created project for development." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyramidSetup", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Pyramid", - "index": 62, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyProtectedMemberInspection", - "shortDescription": { - "text": "Accessing a protected member of a class or a module" - }, - "fullDescription": { - "text": "Reports cases when a protected member is accessed outside the class, a descendant of the class where it is defined, or a module. Example: 'class Foo:\n def _protected_method(self):\n pass\n\n\nclass Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\nfoo = Foo()\nfoo._protected_method() # Access to a protected method'", - "markdown": "Reports cases when a protected member is accessed outside the class,\na descendant of the class where it is defined, or a module.\n\n**Example:**\n\n\n class Foo:\n def _protected_method(self):\n pass\n\n\n class Bar(Foo):\n def public_method(self):\n self._protected_method()\n\n\n foo = Foo()\n foo._protected_method() # Access to a protected method\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyProtectedMember", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyStubPackagesCompatibilityInspection", - "shortDescription": { - "text": "Incompatible stub packages" - }, - "fullDescription": { - "text": "Reports stub packages that do not support the version of the corresponding runtime package. A stub package contains type information for some runtime package.", - "markdown": "Reports stub packages that do not support the version of the corresponding runtime package.\n\nA [stub package](https://www.python.org/dev/peps/pep-0561/) contains type information for some runtime package." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyStubPackagesCompatibility", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyUnboundLocalVariableInspection", - "shortDescription": { - "text": "Unbound local variables" - }, - "fullDescription": { - "text": "Reports local variables referenced before assignment. Example: 'x = 0\nif x > 10:\n b = 3\nprint(b)' The IDE reports a problem for 'print(b)'. A possible fix is: 'x = 0\nif x > 10:\n b = 3\n print(b)'", - "markdown": "Reports local variables referenced before assignment.\n\n**Example:**\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n\nThe IDE reports a problem for `print(b)`. A possible fix is:\n\n\n x = 0\n if x > 10:\n b = 3\n print(b)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyUnboundLocalVariable", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyNamedTupleInspection", - "shortDescription": { - "text": "Invalid definition of 'typing.NamedTuple'" - }, - "fullDescription": { - "text": "Reports invalid definition of a typing.NamedTuple. Example: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str' As a fix, place the field with the default value after the fields without default values: 'import typing\n\n\nclass FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"'", - "markdown": "Reports invalid definition of a\n[typing.NamedTuple](https://docs.python.org/3/library/typing.html#typing.NamedTuple).\n\n**Example:**\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n last: str = \"\"\n middle: str\n\nAs a fix, place the field with the default value after the fields without default values:\n\n\n import typing\n\n\n class FullName(typing.NamedTuple):\n first: str\n middle: str\n last: str = \"\"\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyNamedTuple", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyNestedDecoratorsInspection", - "shortDescription": { - "text": "Problematic nesting of decorators" - }, - "fullDescription": { - "text": "Reports problems with nesting decorators. The inspection highlights the cases when 'classmethod' or 'staticmethod' is applied before another decorator. Example: 'def innocent(f):\n return f\n\n\nclass A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass' As a quick-fix, the IDE offers to remove the decorator.", - "markdown": "Reports problems with nesting decorators. The inspection highlights the cases when `classmethod` or `staticmethod`\nis applied before another decorator.\n\n**Example:**\n\n\n def innocent(f):\n return f\n\n\n class A:\n @innocent # Decorator will not receive a callable it may expect\n @classmethod\n def f2(cls):\n pass\n\n @innocent # Decorator will not receive a callable it may expect\n @staticmethod\n def f1():\n pass\n\nAs a quick-fix, the IDE offers to remove the decorator." - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyNestedDecorators", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DuplicatedBlockNamesInspection", - "shortDescription": { - "text": "Duplicated block names" - }, - "fullDescription": { - "text": "Reports duplicated block names in Django templates. Example: '\n\n\n \n {% block title %}My amazing site{% endblock %}\n\n\n\n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n\n'", - "markdown": "Reports duplicated block names in Django templates.\n\n**Example:**\n\n\n \n \n \n \n {% block title %}My amazing site{% endblock %}\n \n\n \n
\n {% block title %}\n \n {% endblock %}\n
\n\n
\n {% block content %}{% endblock %}\n
\n \n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DuplicatedBlockNamesInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyOverloadsInspection", - "shortDescription": { - "text": "Overloads in regular Python files" - }, - "fullDescription": { - "text": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are not compatible with the implementation. Example: 'from typing import overload\n\n\n@overload\ndef foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n@overload\ndef foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\ndef foo(p1, p2, p3):\n print(p1, p2, p3)'", - "markdown": "Reports cases when overloads in regular Python files are placed after the implementation or when their signatures are\nnot compatible with the implementation.\n\n**Example:**\n\n\n from typing import overload\n\n\n @overload\n def foo(p1, p2): # Overload signature is not compatible with the implementation\n pass\n\n\n @overload\n def foo(p1): # Overload signature is not compatible with the implementation\n pass\n\n\n def foo(p1, p2, p3):\n print(p1, p2, p3)\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyOverloads", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "AppEngineThreadsafeInspection", - "shortDescription": { - "text": "Threadsafe is not available or set inappropriately" - }, - "fullDescription": { - "text": "Reports cases when threadsafe is not present or it is not set to either 'yes' or 'no'.", - "markdown": "Reports cases when threadsafe is not present or it is not set to either `yes` or `no`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "AppEngineThreadsafe", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Google App Engine (Python)", - "index": 4, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyExceptClausesOrderInspection", - "shortDescription": { - "text": "Wrong order of 'except' clauses" - }, - "fullDescription": { - "text": "Reports cases when 'except' clauses are not in the proper order, from the more specific to the more generic, or one exception class is caught twice. If you do not fix the order, some exceptions may not be caught by the most specific handler. Example: 'try:\n call()\nexcept ValueError:\n pass\nexcept UnicodeError:\n pass' The IDE recommends moving the clause up. When the quick-fix is applied, the code changes to: 'try:\n call()\nexcept UnicodeError:\n pass\nexcept ValueError:\n pass'", - "markdown": "Reports cases when `except` clauses are not in the proper order,\nfrom the more specific to the more generic, or one exception class is caught twice.\n\n\nIf you do not fix the order, some exceptions may not be caught by the most specific handler.\n\n**Example:**\n\n\n try:\n call()\n except ValueError:\n pass\n except UnicodeError:\n pass\n\nThe IDE recommends moving the clause up. When the quick-fix is applied, the code changes to:\n\n\n try:\n call()\n except UnicodeError:\n pass\n except ValueError:\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyExceptClausesOrder", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyDataclassInspection", - "shortDescription": { - "text": "Invalid definition and usage of Data Classes" - }, - "fullDescription": { - "text": "Reports invalid definitions and usages of classes created with 'dataclasses' or 'attr' modules. Example: 'import dataclasses\n\n\n@dataclasses.dataclass\nclass FullName:\n first: str\n middle: str = \"\"\n last: str'", - "markdown": "Reports invalid definitions and usages of classes created with\n`dataclasses` or `attr` modules.\n\n**Example:**\n\n\n import dataclasses\n\n\n @dataclasses.dataclass\n class FullName:\n first: str\n middle: str = \"\"\n last: str\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyDataclass", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyClassicStyleClassInspection", - "shortDescription": { - "text": "Classic style class usage" - }, - "fullDescription": { - "text": "Reports classic style classes usage. This inspection applies only to Python 2. Example: 'class A:\n pass' With quick-fixes provided by the IDE, this code fragment changes to: 'class A(object):\n def __init__(self):\n pass'", - "markdown": "Reports [classic style classes](https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes) usage. This inspection applies only to Python 2.\n\n**Example:**\n\n\n class A:\n pass\n\nWith quick-fixes provided by the IDE, this code fragment changes to:\n\n\n class A(object):\n def __init__(self):\n pass\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PyClassicStyleClass", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyprojectInspection", - "shortDescription": { - "text": "Depencencies in pyproject.toml" - }, - "fullDescription": { - "text": "Reports unsatisfied dependencies, declared [project.dependencies] table in pyproject.toml. Shows a quick-fix to install missing packages.", - "markdown": "Reports unsatisfied dependencies, declared \\[project.dependencies\\] table in pyproject.toml.\n\n\nShows a quick-fix to install missing packages." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyprojectInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DjangoUrlArgumentsInspection", - "shortDescription": { - "text": "Incorrect arguments in the ' {% url %}' tag" - }, - "fullDescription": { - "text": "Reports missing parameters in the template file if the 'url()' function has parameters in its URL path. Example: In the 'url.py' file 'url(r'^(?P[0-9]+)/', views.detail, name='detail')' In the template file '{% url 'polls:detail' %}'", - "markdown": "Reports missing parameters in the template file if the `url()`\nfunction has parameters in its URL path.\n\n**Example:**\n\nIn the `url.py` file\n\n\n url(r'^(?P[0-9]+)/', views.detail, name='detail')\n\nIn the template file\n\n\n {% url 'polls:detail' %}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DjangoUrlArgumentsInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Django", - "index": 21, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyPropertyDefinitionInspection", - "shortDescription": { - "text": "Incorrect property definition" - }, - "fullDescription": { - "text": "Reports problems with the arguments of 'property()' and functions annotated with '@property'. 'class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass' A quick-fix offers to update parameters.", - "markdown": "Reports problems with the arguments of `property()` and functions\nannotated with `@property`.\n\n\n class C:\n @property\n def abc(self): # Getter should return or yield something\n pass\n\n @abc.setter\n def foo(self, value): # Names of function and decorator don't match\n pass\n\n @abc.setter\n def abc(self, v1, v2): # Setter signature should be (self, value)\n pass\n\n @abc.deleter\n def abc(self, v1): # Delete signature should be (self)\n pass\n\nA quick-fix offers to update parameters." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "PyPropertyDefinition", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyIncorrectDocstringInspection", - "shortDescription": { - "text": "Incorrect docstring" - }, - "fullDescription": { - "text": "Reports mismatched parameters in a docstring. For example, 'b' is highlighted, because there is no such a parameter in the 'add' function. 'def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass' The inspection does not warn you of missing parameters if none of them is mentioned in a docstring: 'def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass'", - "markdown": "Reports mismatched parameters in a docstring. For example, `b` is highlighted, because there is no\nsuch a parameter in the `add` function.\n\n\n def add(a, c):\n \"\"\"\n @param a:\n @param b:\n @return:\n \"\"\"\n pass\n\nThe inspection does not warn you of missing parameters if none of them is mentioned in a docstring:\n\n\n def mult(a, c):\n \"\"\"\n @return:\n \"\"\"\n pass\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyIncorrectDocstring", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PyListCreationInspection", - "shortDescription": { - "text": "Non-optimal list declaration" - }, - "fullDescription": { - "text": "Reports cases when a list declaration can be rewritten with a list literal. This ensures better performance of your application. Example: 'l = [1]\nl.append(2)' When the quick-fix is applied, the code changes to: 'l = [1, 2]'", - "markdown": "Reports cases when a list declaration\ncan be rewritten with a list literal.\n\nThis ensures better performance of your application.\n\n**Example:**\n\n\n l = [1]\n l.append(2)\n\nWhen the quick-fix is applied, the code changes to:\n\n\n l = [1, 2]\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "PyListCreation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Python", - "index": 1, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "JavaScript", - "version": "232.9876", - "rules": [ - { - "id": "ConstantConditionalExpressionJS", - "shortDescription": { - "text": "Constant conditional expression" - }, - "fullDescription": { - "text": "Reports a conditional expression in the format 'true? result1: result2' or 'false? result1: result2. Suggests simplifying the expression.'", - "markdown": "Reports a conditional expression in the format `true? result1: result2` or `false? result1: result2``.\nSuggests simplifying the expression.\n`" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ConstantConditionalExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSTestFailedLine", - "shortDescription": { - "text": "Highlight failure line in test code" - }, - "fullDescription": { - "text": "Reports a failed method call or an assertion in a test.", - "markdown": "Reports a failed method call or an assertion in a test." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSTestFailedLine", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Unit testing", - "index": 8, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSValidateJSDoc", - "shortDescription": { - "text": "Syntax errors and unresolved references in JSDoc" - }, - "fullDescription": { - "text": "Reports a syntax discrepancy in a documentation comment.", - "markdown": "Reports a syntax discrepancy in a documentation comment." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSValidateJSDoc", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "IfStatementWithTooManyBranchesJS", - "shortDescription": { - "text": "'if' statement with too many branches" - }, - "fullDescription": { - "text": "Reports an 'if' statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction. Use the field below to specify the maximum number of branches expected.", - "markdown": "Reports an `if` statement with too many branches. Such statements may be confusing, and often indicate inadequate levels of design abstraction.\n\n\nUse the field below to specify the maximum number of branches expected." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "IfStatementWithTooManyBranchesJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NonBlockStatementBodyJS", - "shortDescription": { - "text": "Statement body without braces" - }, - "fullDescription": { - "text": "Reports a 'if', 'while', 'for', or 'with' statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance.", - "markdown": "Reports a `if`, `while`, `for`, or `with` statements whose body is not a block statement. Using code block in statement bodies is usually safer for downstream maintenance." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NonBlockStatementBodyJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "BreakStatementJS", - "shortDescription": { - "text": "'break' statement" - }, - "fullDescription": { - "text": "Reports a 'break' statements. Ignores 'break' statements that end case blocks.", - "markdown": "Reports a `break` statements. Ignores `break` statements that end case blocks." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "BreakStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FlowJSConfig", - "shortDescription": { - "text": "Missing .flowconfig" - }, - "fullDescription": { - "text": "Reports a JavaScript file with a '@flow' flag that doesn't have an associated '.flowconfig' file in the project.", - "markdown": "Reports a JavaScript file with a `@flow` flag that doesn't have an associated `.flowconfig` file in the project." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FlowJSConfig", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Flow type checker", - "index": 16, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSPotentiallyInvalidUsageOfClassThis", - "shortDescription": { - "text": "Potentially invalid reference to 'this' of a class from closure" - }, - "fullDescription": { - "text": "Reports an attempt to reference a member of an ECMAScript class via the 'this.' qualifier in a nested function that is not a lambda. 'this' in a nested function that is not a lambda is the function's own 'this' and doesn't relate to the outer class.", - "markdown": "Reports an attempt to reference a member of an ECMAScript class via the `this.` qualifier in a nested function that is not a lambda. \n`this` in a nested function that is not a lambda is the function's own `this` and doesn't relate to the outer class." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSPotentiallyInvalidUsageOfClassThis", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DebuggerStatementJS", - "shortDescription": { - "text": "'debugger' statement" - }, - "fullDescription": { - "text": "Reports a 'debugger' statement used for interaction with the Javascript debuggers. Such statements should not appear in production code.", - "markdown": "Reports a `debugger` statement used for interaction with the Javascript debuggers. Such statements should not appear in production code." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DebuggerStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnusedAssignment", - "shortDescription": { - "text": "Unused assignment" - }, - "fullDescription": { - "text": "Reports a variable whose value is never used after assignment. Suggests removing the unused variable to shorten the code and to avoid redundant allocations. The following cases are reported: A variable is never read after assignment. The value of a variable is always overwritten with another assignment before the variable is read next time. The initializer of a variable is redundant (for one of the above-mentioned reasons).", - "markdown": "Reports a variable whose value is never used after assignment. \nSuggests removing the unused variable to shorten the code and to avoid redundant allocations.\n\nThe following cases are reported:\n\n* A variable is never read after assignment.\n* The value of a variable is always overwritten with another assignment before the variable is read next time.\n* The initializer of a variable is redundant (for one of the above-mentioned reasons)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnusedAssignment", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Unused symbols", - "index": 19, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FlowJSError", - "shortDescription": { - "text": "Flow type checker" - }, - "fullDescription": { - "text": "Reports errors from Flow.", - "markdown": "Reports errors from [Flow](https://flowtype.org/)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "FlowJSError", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Flow type checker", - "index": 16, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ReuseOfLocalVariableJS", - "shortDescription": { - "text": "Reuse of local variable" - }, - "fullDescription": { - "text": "Reports reusing a local variable and overwriting its value with a new value that is not related to the original variable usage. Reusing a local variable in this way may be confusing because the intended semantics of the local variable may vary with each usage. It may also cause bugs, if code changes result in values that were expected to be overwritten while they are actually live. It is good practices to keep variable lifetimes as short as possible, and not reuse local variables for the sake of brevity.", - "markdown": "Reports reusing a local variable and overwriting its value with a new value that is not related to the original variable usage. Reusing a local variable in this way may be confusing because the intended semantics of the local variable may vary with each usage. It may also cause bugs, if code changes result in values that were expected to be overwritten while they are actually live. It is good practices to keep variable lifetimes as short as possible, and not reuse local variables for the sake of brevity." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ReuseOfLocalVariableJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Data flow", - "index": 20, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ShiftOutOfRangeJS", - "shortDescription": { - "text": "Shift operation by possibly wrong constant" - }, - "fullDescription": { - "text": "Reports a shift operation where the second operand is a constant outside the reasonable range, for example, an integer shift operation outside the range '0..31', shifting by negative or overly large values.", - "markdown": "Reports a shift operation where the second operand is a constant outside the reasonable range, for example, an integer shift operation outside the range `0..31`, shifting by negative or overly large values." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ShiftOutOfRangeJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Bitwise operation issues", - "index": 22, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSClosureCompilerSyntax", - "shortDescription": { - "text": "Incorrect usage of JSDoc tags" - }, - "fullDescription": { - "text": "Reports warnings implied by Google Closure Compiler annotations including correct use of '@abstract', '@interface', and '@implements' tags.", - "markdown": "Reports warnings implied by *Google Closure Compiler* annotations including correct use of `@abstract`, `@interface`, and `@implements` tags." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSClosureCompilerSyntax", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnnecessaryContinueJS", - "shortDescription": { - "text": "Unnecessary 'continue' statement" - }, - "fullDescription": { - "text": "Reports an unnecessary 'continue' statement at the end of a loop. Suggests removing such statements.", - "markdown": "Reports an unnecessary `continue` statement at the end of a loop. Suggests removing such statements." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnnecessaryContinueJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertLetToConst", - "shortDescription": { - "text": "'let' is used instead of 'const'" - }, - "fullDescription": { - "text": "Reports a 'let' declaration that can be made 'const'.", - "markdown": "Reports a `let` declaration that can be made `const`. " - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertLetToConst", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSXDomNesting", - "shortDescription": { - "text": "Invalid DOM element nesting" - }, - "fullDescription": { - "text": "Detects HTML elements in JSX files which are not nested properly according to the DOM specification. React reports runtime warnings on incorrectly nested elements.", - "markdown": "Detects HTML elements in JSX files which are not nested properly according to the DOM specification. React reports runtime warnings on incorrectly nested elements." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSXDomNesting", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/React", - "index": 26, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptValidateTypes", - "shortDescription": { - "text": "Type mismatch" - }, - "fullDescription": { - "text": "Reports a parameter, return value, or assigned expression of incorrect type.", - "markdown": "Reports a parameter, return value, or assigned expression of incorrect type." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "TypeScriptValidateTypes", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "BadExpressionStatementJS", - "shortDescription": { - "text": "Expression statement which is not assignment or call" - }, - "fullDescription": { - "text": "Reports an expression statement that is neither an assignment nor a call. Such statements usually indicate an error.", - "markdown": "Reports an expression statement that is neither an assignment nor a call. Such statements usually indicate an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "BadExpressionStatementJS", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ConfusingFloatingPointLiteralJS", - "shortDescription": { - "text": "Confusing floating point literal" - }, - "fullDescription": { - "text": "Reports any floating point number that does not have a decimal point, or any numbers before the decimal point, or and numbers after the decimal point. Such literals may be confusing, and violate several coding standards.", - "markdown": "Reports any floating point number that does not have a decimal point, or any numbers before the decimal point, or and numbers after the decimal point. Such literals may be confusing, and violate several coding standards." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ConfusingFloatingPointLiteralJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "BreakStatementWithLabelJS", - "shortDescription": { - "text": "'break' statement with label" - }, - "fullDescription": { - "text": "Reports a labeled 'break' statement.", - "markdown": "Reports a labeled `break` statement." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "BreakStatementWithLabelJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ContinueOrBreakFromFinallyBlockJS", - "shortDescription": { - "text": "'continue' or 'break' inside 'finally' block" - }, - "fullDescription": { - "text": "Reports a 'break' or 'continue' statement inside a 'finally' block. Such statements are very confusing, may hide exceptions, and complicate debugging.", - "markdown": "Reports a `break` or `continue` statement inside a `finally` block. Such statements are very confusing, may hide exceptions, and complicate debugging." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ContinueOrBreakFromFinallyBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "StatementsPerFunctionJS", - "shortDescription": { - "text": "Overly long function" - }, - "fullDescription": { - "text": "Reports an overly long function. Function length is calculated by counting up the number of non-empty statements in the function. Functions that are too long are error-prone and difficult to test. Use the field below to specify the maximum acceptable number of statements in a function.", - "markdown": "Reports an overly long function. Function length is calculated by counting up the number of non-empty statements in the function. Functions that are too long are error-prone and difficult to test.\n\n\nUse the field below to specify the maximum acceptable number of statements in a function." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionTooLongJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnnecessaryLocalVariableJS", - "shortDescription": { - "text": "Redundant local variable" - }, - "fullDescription": { - "text": "Reports an unnecessary local variable that does not make a function more comprehensible: a local variable that is immediately returned a local variable that is immediately assigned to another variable and is not used anymore a local variable that always has the same value as another local variable or parameter. Use the checkbox below to have this inspection ignore variables that are immediately returned or thrown. Some coding styles suggest using such variables for clarity and ease of debugging.", - "markdown": "Reports an unnecessary local variable that does not make a function more comprehensible:\n\n* a local variable that is immediately returned\n* a local variable that is immediately assigned to another variable and is not used anymore\n* a local variable that always has the same value as another local variable or parameter.\n\n\nUse the checkbox below to have this inspection ignore variables that are immediately\nreturned or thrown. Some coding styles suggest using such variables for clarity and\nease of debugging." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnnecessaryLocalVariableJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Data flow", - "index": 20, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSMethodCanBeStatic", - "shortDescription": { - "text": "Method can be made 'static'" - }, - "fullDescription": { - "text": "Reports a class method that can be safely made 'static'. A method can be 'static' if it does not reference any of its class' non-static methods and non-static fields and is not overridden in a subclass. Use the first checkbox below to inspect only 'private' methods.", - "markdown": "Reports a class method that can be safely made `static`. A method can be `static` if it does not reference any of its class' non-static methods and non-static fields and is not overridden in a subclass.\n\n\nUse the first checkbox below to inspect only `private` methods." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSMethodCanBeStatic", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSDeclarationsAtScopeStart", - "shortDescription": { - "text": "'var' declared not at the beginning of a function" - }, - "fullDescription": { - "text": "Checks that declarations of local variables declared with var are at the top of a function scope. By default, variable declarations are always moved (\"hoisted\") invisibly to the top of their containing scope when the code is executed. Therefore, declaring them at the top of the scope helps represent this behavior in the code.", - "markdown": "Checks that declarations of local variables declared with **var** are at the top of a function scope. \n\nBy default, variable declarations are always moved (\"hoisted\") invisibly to the top of their containing scope when the code is executed. Therefore, declaring them at the top of the scope helps represent this behavior in the code." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSDeclarationsAtScopeStart", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ContinueStatementWithLabelJS", - "shortDescription": { - "text": "'continue' statement with label" - }, - "fullDescription": { - "text": "Reports a labeled 'continue' statement.", - "markdown": "Reports a labeled `continue` statement." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ContinueStatementWithLabelJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSObjectNullOrUndefined", - "shortDescription": { - "text": "Object is 'null' or 'undefined'" - }, - "fullDescription": { - "text": "Reports an error caused by invoking a method, accessing a property, or calling a function on an object that is 'undefined' or 'null'.", - "markdown": "Reports an error caused by invoking a method, accessing a property, or calling a function on an object that is `undefined` or `null`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSObjectNullOrUndefined", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptMissingConfigOption", - "shortDescription": { - "text": "Missing tsconfig.json option " - }, - "fullDescription": { - "text": "Reports a usage that requires an explicit option in 'tsconfig.json'. For example, to use JSX in '.tsx' files, 'tsconfig.json' must contain '\"jsx\"' property.", - "markdown": "Reports a usage that requires an explicit option in `tsconfig.json`. For example, to use JSX in `.tsx` files, `tsconfig.json` must contain `\"jsx\"` property." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TypeScriptMissingConfigOption", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSXUnresolvedComponent", - "shortDescription": { - "text": "Unresolved JSX component" - }, - "fullDescription": { - "text": "Reports an unresolved reference to a JSX component. Suggests adding a missing import statement if the referenced component is defined in the project or its dependencies or creating a new component with this name. The template for a new component can be modified in Editor | File and Code Templates.", - "markdown": "Reports an unresolved reference to a JSX component. Suggests adding a missing import statement if the referenced component is defined in the project or its dependencies or creating a new component with this name.\n\nThe template for a new component can be modified in Editor \\| File and Code Templates." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSXUnresolvedComponent", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ShorthandObjectProperty", - "shortDescription": { - "text": "Property can be replaced with shorthand" - }, - "fullDescription": { - "text": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it. Example: 'var obj = {foo:foo}' After applying the quick-fix the code looks as follows: 'var obj = {foo}'", - "markdown": "Reports an object property that can be converted to ES6 shorthand style and provides a quick-fix to do it.\n\nExample:\n\n\n var obj = {foo:foo}\n\nAfter applying the quick-fix the code looks as follows:\n\n\n var obj = {foo}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ShorthandObjectProperty", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnnecessaryLabelOnBreakStatementJS", - "shortDescription": { - "text": "Unnecessary label on 'break' statement" - }, - "fullDescription": { - "text": "Reports a labeled 'break' statement whose labels may be removed without changing the flow of control.", - "markdown": "Reports a labeled `break` statement whose labels may be removed without changing the flow of control." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnnecessaryLabelOnBreakStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ContinueStatementJS", - "shortDescription": { - "text": "'continue' statement" - }, - "fullDescription": { - "text": "Reports a 'continue' statement.", - "markdown": "Reports a `continue` statement." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ContinueStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "AssignmentToForLoopParameterJS", - "shortDescription": { - "text": "Assignment to 'for' loop parameter" - }, - "fullDescription": { - "text": "Reports an assignment to a variable declared as a 'for' loop parameter. Although occasionally intended, this construct can be extremely confusing, and is often a result of an error.", - "markdown": "Reports an assignment to a variable declared as a `for` loop parameter. Although occasionally intended, this construct can be extremely confusing, and is often a result of an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "AssignmentToForLoopParameterJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Assignment issues", - "index": 39, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSPotentiallyInvalidConstructorUsage", - "shortDescription": { - "text": "Potentially invalid constructor usage" - }, - "fullDescription": { - "text": "Reports a usage of a potentially invalid constructor function, for example: a function that is not a constructor after 'new', using a constructor's prototype or calling a constructor without 'new'. A constructor function is assumed to have an upper case name (optional) or have an explicit JSDoc '@constructor' tag.", - "markdown": "Reports a usage of a potentially invalid constructor function, for example: a function that is not a constructor after `new`, using a constructor's prototype or calling a constructor without `new`. A constructor function is assumed to have an upper case name (optional) or have an explicit JSDoc `@constructor` tag." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSPotentiallyInvalidConstructorUsage", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PointlessArithmeticExpressionJS", - "shortDescription": { - "text": "Pointless arithmetic expression" - }, - "fullDescription": { - "text": "Reports an arithmetic expression that include adding or subtracting zero, multiplying by zero or one, division by one, and shift by zero. Such expressions may result from not fully completed automated refactoring.", - "markdown": "Reports an arithmetic expression that include adding or subtracting zero, multiplying by zero or one, division by one, and shift by zero. Such expressions may result from not fully completed automated refactoring." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PointlessArithmeticExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NodeCoreCodingAssistance", - "shortDescription": { - "text": "Unresolved Node.js APIs" - }, - "fullDescription": { - "text": "Suggests configuring coding assistance for Node.js, for example, 'require' and/or core modules ('path', 'http', 'fs', etc.). See https://nodejs.org/api/ for the complete list.", - "markdown": "Suggests configuring coding assistance for Node.js, for example, `require` and/or core modules ('path', 'http', 'fs', etc.).\n\n\nSee for the complete list." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NodeCoreCodingAssistance", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Node.js", - "index": 45, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUndeclaredVariable", - "shortDescription": { - "text": "Implicitly declared global JavaScript variable" - }, - "fullDescription": { - "text": "Reports an implicit declaration of a global variable. Example: 'var aaa = 1; // good\n bbb = 2; // bad, if bbb is not declared with 'var' somewhere'", - "markdown": "Reports an implicit declaration of a global variable.\n\nExample:\n\n\n var aaa = 1; // good\n bbb = 2; // bad, if bbb is not declared with 'var' somewhere\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSUndeclaredVariable", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DivideByZeroJS", - "shortDescription": { - "text": "Division by zero" - }, - "fullDescription": { - "text": "Reports division by zero or a remainder by zero.", - "markdown": "Reports division by zero or a remainder by zero." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DivideByZeroJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSPrimitiveTypeWrapperUsage", - "shortDescription": { - "text": "Primitive type object wrapper used" - }, - "fullDescription": { - "text": "Reports an improper usage of a wrapper for primitive types or a property of a primitive type being modified, as in the latter case the assigned value will be lost.", - "markdown": "Reports an improper usage of a wrapper for primitive types or a property of a primitive type being modified, as in the latter case the assigned value will be lost." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSPrimitiveTypeWrapperUsage", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptSmartCast", - "shortDescription": { - "text": "Narrowed type" - }, - "fullDescription": { - "text": "Reports a usage of a variable where the variable type is narrowed by a type guard. Note that severity level doesn't affect this inspection.", - "markdown": "Reports a usage of a variable where the variable type is narrowed by a type guard. Note that severity level doesn't affect this inspection." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TypeScriptSmartCast", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertIndexedForToForOf", - "shortDescription": { - "text": "Indexed 'for' is used instead of 'for..of'" - }, - "fullDescription": { - "text": "Reports an indexed 'for' loop used on an array. Suggests replacing it with a 'for..of' loop. 'for..of' loops are introduced in ECMAScript 6 and iterate over 'iterable' objects.", - "markdown": "Reports an indexed [for](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) loop used on an array. Suggests replacing it with a [for..of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop. \n`for..of` loops are introduced in ECMAScript 6 and iterate over `iterable` objects." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertIndexedForToForOf", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSLastCommaInArrayLiteral", - "shortDescription": { - "text": "Unneeded last comma in array literal" - }, - "fullDescription": { - "text": "Reports a usage of a trailing comma in an array literal. The warning is reported only when the JavaScript language version is set to ECMAScript 5.1. Although trailing commas in arrays are allowed by the specification, some browsers may throw an error when a trailing comma is used. You can configure formatting options for trailing commas in Code Style | JavaScript or TypeScript | Punctuation.", - "markdown": "Reports a usage of a trailing comma in an array literal.\n\nThe warning is reported only when the JavaScript language version is set to ECMAScript 5.1.\n\nAlthough trailing commas in arrays are allowed by the specification, some browsers may throw an error when a trailing comma is used.\n\nYou can configure formatting options for trailing commas in **Code Style** \\| **JavaScript** or **TypeScript** \\| **Punctuation**." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSLastCommaInArrayLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ConditionalExpressionJS", - "shortDescription": { - "text": "Conditional expression" - }, - "fullDescription": { - "text": "Reports a ternary conditional expression. Some coding standards prohibit such expressions in favor of explicit 'if' statements.", - "markdown": "Reports a ternary conditional expression. Some coding standards prohibit such expressions in favor of explicit `if` statements." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ConditionalExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertVarToLetConst", - "shortDescription": { - "text": "'var' is used instead of 'let' or 'const'" - }, - "fullDescription": { - "text": "Reports a 'var' declaration that is used instead of 'let' or 'const'. Both 'let' and 'const' are block-scoped and behave more strictly. Suggests replacing all 'var' declarations with 'let' or 'const' declarations, depending on the semantics of a particular value. The declarations may be moved to the top of the function or placed before the first usage of the variable to avoid Reference errors. Select the 'Conservatively convert var with Fix all action' option to prevent any changes in these complex cases when using the 'Fix all' action.", - "markdown": "Reports a `var` declaration that is used instead of `let` or `const`. \nBoth `let` and `const` are block-scoped and behave more strictly. \n\nSuggests replacing all `var` declarations with `let` or `const` declarations, depending on the semantics of a particular value. The declarations may be moved to the top of the function or placed before the first usage of the variable to avoid Reference errors. \nSelect the 'Conservatively convert var with Fix all action' option to prevent any changes in these complex cases when using the 'Fix all' action." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertVarToLetConst", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSReferencingMutableVariableFromClosure", - "shortDescription": { - "text": "Referencing mutable variable from closure" - }, - "fullDescription": { - "text": "Reports access to outer mutable variables from functions. Example: 'for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }'", - "markdown": "Reports access to outer mutable variables from functions.\n\nExample:\n\n\n for (var i = 1; i <= 3; i++) {\n setTimeout(function() {\n console.log(i); // bad\n }, 0);\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSReferencingMutableVariableFromClosure", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PointlessBooleanExpressionJS", - "shortDescription": { - "text": "Pointless statement or boolean expression" - }, - "fullDescription": { - "text": "Reports a pointless or pointlessly complicated boolean expression or statement. Example: 'let a = !(false && x);\n let b = false || x;' After the quick fix is applied the result looks like: 'let a = true;\n let b = x;'", - "markdown": "Reports a pointless or pointlessly complicated boolean expression or statement.\n\nExample:\n\n\n let a = !(false && x);\n let b = false || x;\n\nAfter the quick fix is applied the result looks like:\n\n\n let a = true;\n let b = x;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PointlessBooleanExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DynamicallyGeneratedCodeJS", - "shortDescription": { - "text": "Execution of dynamically generated code" - }, - "fullDescription": { - "text": "Reports a call of the 'eval()', 'setTimeout()', or 'setInterval()' function or an allocation of a 'Function' object. These functions are used to execute arbitrary strings of JavaScript text, which often dynamically generated. This can be very confusing, and may be a security risk. Ignores the cases when a callback function is provided to these methods statically, without code generation.", - "markdown": "Reports a call of the `eval()`, `setTimeout()`, or `setInterval()` function or an allocation of a `Function` object. These functions are used to execute arbitrary strings of JavaScript text, which often dynamically generated. This can be very confusing, and may be a security risk. \n\nIgnores the cases when a callback function is provided to these methods statically, without code generation." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DynamicallyGeneratedCodeJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NegatedConditionalExpressionJS", - "shortDescription": { - "text": "Negated conditional expression" - }, - "fullDescription": { - "text": "Reports a conditional expression whose condition is negated. Suggests flipping the order of branches in the conditional expression to increase the clarity of the statement. Example: '!condition ? 2 : 1'", - "markdown": "Reports a conditional expression whose condition is negated. Suggests flipping the order of branches in the conditional expression to increase the clarity of the statement. Example: `!condition ? 2 : 1`" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NegatedConditionalExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUrlImportUsage", - "shortDescription": { - "text": "URL import is used" - }, - "fullDescription": { - "text": "Checks used URL imports in the JavaScript language. Suggests downloading the module for the specified remote URL. Such association enables the IDE to provide proper code completion and navigation. URLs in import specifiers are supported only for ECMAScript modules in the JavaScript language.", - "markdown": "Checks used URL imports in the JavaScript language. Suggests downloading the module for the specified remote URL. Such association enables the IDE to provide proper code completion and navigation. \n\nURLs in import specifiers are supported only for ECMAScript modules in the JavaScript language." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSUrlImportUsage", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnnecessaryLabelOnContinueStatementJS", - "shortDescription": { - "text": "Unnecessary label on 'continue' statement" - }, - "fullDescription": { - "text": "Reports a labeled 'continue' statement whose labels may be removed without changing the flow of control.", - "markdown": "Reports a labeled `continue` statement whose labels may be removed without changing the flow of control." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnnecessaryLabelOnContinueStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ChainedEqualityJS", - "shortDescription": { - "text": "Chained equality" - }, - "fullDescription": { - "text": "Reports a chained equality comparison (i.e. 'a==b==c'). Such comparisons are confusing.", - "markdown": "Reports a chained equality comparison (i.e. `a==b==c`). Such comparisons are confusing." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ChainedEqualityComparisonsJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SillyAssignmentJS", - "shortDescription": { - "text": "Variable is assigned to itself" - }, - "fullDescription": { - "text": "Reports an assignment in the form 'x = x'.", - "markdown": "Reports an assignment in the form `x = x`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SillyAssignmentJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Assignment issues", - "index": 39, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSPotentiallyInvalidTargetOfIndexedPropertyAccess", - "shortDescription": { - "text": "Possibly incorrect target of indexed property access" - }, - "fullDescription": { - "text": "Reports a potentially invalid indexed property access, for example, 'Array[1]'.", - "markdown": "Reports a potentially invalid indexed property access, for example, `Array[1]`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSPotentiallyInvalidTargetOfIndexedPropertyAccess", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSAccessibilityCheck", - "shortDescription": { - "text": "Inaccessible @private and @protected members referenced" - }, - "fullDescription": { - "text": "Reports a reference to a JavaScript member that is marked with a '@private' or '@protected' tag but does not comply with visibility rules that these tags imply.", - "markdown": "Reports a reference to a JavaScript member that is marked with a `@private` or `@protected` tag but does not comply with visibility rules that these tags imply." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSAccessibilityCheck", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertRequireIntoImport", - "shortDescription": { - "text": "'require()' is used instead of 'import'" - }, - "fullDescription": { - "text": "Reports a 'require()' statement. Suggests converting it to a 'require()' call with an 'import' statement. Enable 'Convert require() inside inner scopes with Fix all action' to convert all 'require()' calls inside the nested functions and statements when using the 'Fix all' action. Please note that converting 'require()' statements inside inner scopes to 'import' statements may cause changes in the semantics of the code. Import statements are static module dependencies and are hoisted, which means that they are moved to the top of the current module. 'require()' calls load modules dynamically. They can be executed conditionally, and their scope is defined by the expression in which they are used. Clear the 'Convert require() inside inner scopes with Fix all action' checkbox to prevent any changes in these complex cases when using the 'Fix all' action.", - "markdown": "Reports a `require()` statement. Suggests converting it to a `require()` call with an `import` statement. \n\nEnable 'Convert require() inside inner scopes with Fix all action' to convert all `require()` calls inside the nested functions and statements when using the 'Fix all' action. \n\nPlease note that converting `require()` statements inside inner scopes to `import` statements may cause changes in the semantics of the code. Import statements are static module dependencies and are hoisted, which means that they are moved to the top of the current module. `require()` calls load modules dynamically. They can be executed conditionally, and their scope is defined by the expression in which they are used. \nClear the 'Convert require() inside inner scopes with Fix all action' checkbox to prevent any changes in these complex cases when using the 'Fix all' action." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertRequireIntoImport", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FunctionWithMultipleLoopsJS", - "shortDescription": { - "text": "Function with multiple loops" - }, - "fullDescription": { - "text": "Reports a function with multiple loop statements.", - "markdown": "Reports a function with multiple loop statements." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionWithMultipleLoopsJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LabeledStatementJS", - "shortDescription": { - "text": "Labeled statement" - }, - "fullDescription": { - "text": "Reports a labeled statement.", - "markdown": "Reports a labeled statement." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LabeledStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NpmUsedModulesInstalled", - "shortDescription": { - "text": "Missing module dependency" - }, - "fullDescription": { - "text": "Reports a module from a 'require()' call or an 'import' statement that is not installed or is not listed in package.json dependencies. Suggests installing the module and/or including it into package.json. For 'require()' calls, works only in the files from the scope of Node.js Core JavaScript library.", - "markdown": "Reports a module from a `require()` call or an `import` statement that is not installed or is not listed in package.json dependencies.\n\nSuggests installing the module and/or including it into package.json.\n\nFor `require()` calls, works only in the files from the scope of *Node.js Core* JavaScript library." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "NpmUsedModulesInstalled", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnusedCatchParameterJS", - "shortDescription": { - "text": "Unused 'catch' parameter" - }, - "fullDescription": { - "text": "Reports a 'catch' parameter that is not used in the corresponding block. The 'catch' parameters named 'ignore' or 'ignored' are ignored. Use the checkbox below to disable this inspection for 'catch' blocks with comments.", - "markdown": "Reports a `catch` parameter that is not used in the corresponding block. The `catch` parameters named `ignore` or `ignored` are ignored.\n\n\nUse the checkbox below to disable this inspection for `catch`\nblocks with comments." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnusedCatchParameterJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "WithStatementJS", - "shortDescription": { - "text": "'with' statement" - }, - "fullDescription": { - "text": "Reports a 'with' statements. Such statements result in potentially confusing implicit bindings, and may behave strangely in setting new variables.", - "markdown": "Reports a `with` statements. Such statements result in potentially confusing implicit bindings, and may behave strangely in setting new variables." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "WithStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptCheckImport", - "shortDescription": { - "text": "Unresolved imported name" - }, - "fullDescription": { - "text": "Reports an unresolved name or binding in an 'import' declaration in TypeScript code.", - "markdown": "Reports an unresolved name or binding in an `import` declaration in TypeScript code." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "TypeScriptCheckImport", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSConstantReassignment", - "shortDescription": { - "text": "Attempt to assign to const or readonly variable" - }, - "fullDescription": { - "text": "Reports reassigning a value to a constant or a readonly variable.", - "markdown": "Reports reassigning a value to a constant or a readonly variable." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JSConstantReassignment", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MagicNumberJS", - "shortDescription": { - "text": "Magic number" - }, - "fullDescription": { - "text": "Reports a \"magic number\" that is a numeric literal used without being named by a constant declaration. Magic numbers can result in code whose intention is unclear, and may result in errors if a magic number is changed in one code location but remains unchanged in another. The numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 0.0 and 1.0 are ignored.", - "markdown": "Reports a \"magic number\" that is a numeric literal used without being named by a constant declaration. Magic numbers can result in code whose intention is unclear, and may result in errors if a magic number is changed in one code location but remains unchanged in another. The numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 0.0 and 1.0 are ignored." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MagicNumberJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FunctionNamingConventionJS", - "shortDescription": { - "text": "Function naming convention" - }, - "fullDescription": { - "text": "Reports a function whose name is too short, too long, or does not follow the specified regular expression pattern. Use the fields provided below to specify minimum length, maximum length, and a regular expression for function names. Use the standard 'java.util.regex' format for regular expressions.", - "markdown": "Reports a function whose name is too short, too long, or does not follow the specified regular expression pattern.\n\n\nUse the fields provided below to specify minimum length, maximum length, and a regular expression\nfor function names. Use the standard `java.util.regex` format for regular expressions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionNamingConventionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Naming conventions", - "index": 50, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSXSyntaxUsed", - "shortDescription": { - "text": "JSX syntax used" - }, - "fullDescription": { - "text": "Reports a usage of a JSX tag in JavaScript code.", - "markdown": "Reports a usage of a JSX tag in JavaScript code." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JSXSyntaxUsed", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSJoinVariableDeclarationAndAssignment", - "shortDescription": { - "text": "Variable declaration can be merged with the first assignment to the variable" - }, - "fullDescription": { - "text": "Reports a variable that is declared without an initializer and is used much further in the code or in a single nested scope. Suggests moving the variable closer to its usages and joining it with the initializer expression.", - "markdown": "Reports a variable that is declared without an initializer and is used much further in the code or in a single nested scope. Suggests moving the variable closer to its usages and joining it with the initializer expression." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSJoinVariableDeclarationAndAssignment", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSRedundantSwitchStatement", - "shortDescription": { - "text": "'switch' statement is redundant and can be replaced" - }, - "fullDescription": { - "text": "Reports a 'switch' statement with an empty body, or with only one 'case' branch, or with a 'default' branch only.", - "markdown": "Reports a `switch` statement with an empty body, or with only one `case` branch, or with a `default` branch only." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSRedundantSwitchStatement", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Switch statement issues", - "index": 51, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptLibrary", - "shortDescription": { - "text": "Missing global library" - }, - "fullDescription": { - "text": "Reports a TypeScript library file that is required for a symbol but is not listed under the 'lib' compiler option in 'tsconfig.json'.", - "markdown": "Reports a TypeScript library file that is required for a symbol but is not listed under the `lib` compiler option in `tsconfig.json`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "TypeScriptLibrary", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptMissingAugmentationImport", - "shortDescription": { - "text": "Missing augmentation import" - }, - "fullDescription": { - "text": "Reports a usage from augmentation module without an explicit import.", - "markdown": "Reports a usage from [augmentation module](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation) without an explicit import." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptMissingAugmentationImport", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnusedGlobalSymbols", - "shortDescription": { - "text": "Unused global symbol" - }, - "fullDescription": { - "text": "Reports an unused globally accessible public function, variable, class, or property.", - "markdown": "Reports an unused globally accessible public function, variable, class, or property." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnusedGlobalSymbols", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Unused symbols", - "index": 19, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertModuleExportToExport", - "shortDescription": { - "text": "'module.exports' is used instead of 'export'" - }, - "fullDescription": { - "text": "Reports a 'module.export' statement. Suggests replacing it with an 'export' or 'export default' statement. Please note that the quick-fix for converting 'module.export' into 'export' is not available for 'module.export' inside functions or statements because 'export' statements can only be at the top level of a module.", - "markdown": "Reports a `module.export` statement. Suggests replacing it with an `export` or `export default` statement. \n\nPlease note that the quick-fix for converting `module.export` into `export` is not available for `module.export` inside functions or statements because `export` statements can only be at the top level of a module." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertModuleExportToExport", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DocumentWriteJS", - "shortDescription": { - "text": "Call to 'document.write()'" - }, - "fullDescription": { - "text": "Reports a method call to 'document.write()' or 'document.writeln()'. Most usages of such calls are performed better with explicit DOM calls, such as 'getElementByID()' and 'createElement()'. Additionally, the 'write()' and 'writeln()' calls will not work with XML DOMs, including DOMs for XHTML if viewed as XML. This can result in difficulty to point out bugs.", - "markdown": "Reports a method call to `document.write()` or `document.writeln()`. Most usages of such calls are performed better with explicit DOM calls, such as `getElementByID()` and `createElement()`. Additionally, the `write()` and `writeln()` calls will not work with XML DOMs, including DOMs for XHTML if viewed as XML. This can result in difficulty to point out bugs." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DocumentWriteJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/DOM issues", - "index": 52, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "AnonymousFunctionJS", - "shortDescription": { - "text": "Anonymous function" - }, - "fullDescription": { - "text": "Reports an anonymous function. An explicit name of a function expression may be helpful for debugging. Ignores function expressions without names if they have a 'name' property specified in the ECMAScript 6 standard. For example, 'var bar = function() {};' is not reported.", - "markdown": "Reports an anonymous function. An explicit name of a function expression may be helpful for debugging. Ignores function expressions without names if they have a `name` property specified in the ECMAScript 6 standard. For example, `var bar = function() {};` is not reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "AnonymousFunctionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially undesirable code constructs", - "index": 15, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "BlockStatementJS", - "shortDescription": { - "text": "Unnecessary block statement" - }, - "fullDescription": { - "text": "Reports a block statement that is not used as the body of 'if', 'for', 'while', 'do', 'with', or 'try' statements, or as the body of a function declaration. Starting from ECMAScript 6, JavaScript blocks introduce new scopes for 'let' and 'const' variables, but still free-standing block statements may be confusing and result in subtle bugs when used with 'var' variables.", - "markdown": "Reports a block statement that is not used as the body of `if`, `for`, `while`, `do`, `with`, or `try` statements, or as the body of a function declaration. Starting from ECMAScript 6, JavaScript blocks introduce new scopes for `let` and `const` variables, but still free-standing block statements may be confusing and result in subtle bugs when used with `var` variables." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "BlockStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ObjectAllocationIgnoredJS", - "shortDescription": { - "text": "Result of object allocation ignored" - }, - "fullDescription": { - "text": "Reports object allocation where the result of the allocated object is ignored, for example, 'new Error();' as a statement, without any assignment. Such allocation expressions may indicate an odd object initialization strategy.", - "markdown": "Reports object allocation where the result of the allocated object is ignored, for example, `new Error();` as a statement, without any assignment. Such allocation expressions may indicate an odd object initialization strategy." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ObjectAllocationIgnored", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "InfiniteRecursionJS", - "shortDescription": { - "text": "Infinite recursion" - }, - "fullDescription": { - "text": "Reports a function which must either recurse infinitely or throw an exception. Such functions may not return normally.", - "markdown": "Reports a function which must either recurse infinitely or throw an exception. Such functions may not return normally." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "InfiniteRecursionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NestedConditionalExpressionJS", - "shortDescription": { - "text": "Nested conditional expression" - }, - "fullDescription": { - "text": "Reports a ternary conditional expression within another ternary condition. Such nested conditionals may be extremely confusing, and best replaced by more explicit conditional logic.", - "markdown": "Reports a ternary conditional expression within another ternary condition. Such nested conditionals may be extremely confusing, and best replaced by more explicit conditional logic." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NestedConditionalExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSTypeOfValues", - "shortDescription": { - "text": "'typeof' comparison with non-standard value" - }, - "fullDescription": { - "text": "Reports a comparison of a 'typeof' expression with a literal string which is not one of the standard types: 'undefined', 'object', 'boolean', 'number', 'string', 'function', or 'symbol'. Such comparisons always return 'false'.", - "markdown": "Reports a comparison of a `typeof` expression with a literal string which is not one of the standard types: `undefined`, `object`, `boolean`, `number`, `string`, `function`, or `symbol`. Such comparisons always return `false`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSTypeOfValues", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "IncompatibleMaskJS", - "shortDescription": { - "text": "Incompatible bitwise mask operation" - }, - "fullDescription": { - "text": "Reports a bitwise mask expression which for sure evaluates to 'true' or 'false'. Expressions are of the form '(var & constant1) == constant2' or '(var | constant1) == constant2', where 'constant1' and 'constant2' are incompatible bitmask constants. Example: '// Incompatible mask: as the last byte in mask is zero,\n// something like 0x1200 would be possible, but not 0x1234\nif ((mask & 0xFF00) == 0x1234) {...}'", - "markdown": "Reports a bitwise mask expression which for sure evaluates to `true` or `false`. Expressions are of the form `(var & constant1) == constant2` or `(var | constant1) == constant2`, where `constant1` and `constant2` are incompatible bitmask constants.\n\nExample:\n\n\n // Incompatible mask: as the last byte in mask is zero,\n // something like 0x1200 would be possible, but not 0x1234\n if ((mask & 0xFF00) == 0x1234) {...}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "IncompatibleBitwiseMaskOperation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Bitwise operation issues", - "index": 22, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TextLabelInSwitchStatementJS", - "shortDescription": { - "text": "Text label in 'switch' statement" - }, - "fullDescription": { - "text": "Reports a labeled statement inside a 'switch' statement, which often results from a typo. Example: 'switch(x)\n {\n case 1:\n case2: //typo!\n case 3:\n break;\n }'", - "markdown": "Reports a labeled statement inside a `switch` statement, which often results from a typo.\n\nExample:\n\n\n switch(x)\n {\n case 1:\n case2: //typo!\n case 3:\n break;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TextLabelInSwitchStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Switch statement issues", - "index": 51, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6PossiblyAsyncFunction", - "shortDescription": { - "text": "'await' in non-async function" - }, - "fullDescription": { - "text": "Reports a usage of 'await' in a function that was possibly intended to be async but is actually missing the 'async' modifier. Although 'await' can be used as an identifier, it is likely that it was intended to be used as an operator, so the containing function should be made 'async'.", - "markdown": "Reports a usage of `await` in a function that was possibly intended to be async but is actually missing the `async` modifier. Although `await` can be used as an identifier, it is likely that it was intended to be used as an operator, so the containing function should be made `async`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6PossiblyAsyncFunction", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Async code and promises", - "index": 53, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EmptyCatchBlockJS", - "shortDescription": { - "text": "Empty 'catch' block" - }, - "fullDescription": { - "text": "Reports an empty 'catch' block. This indicates that errors are simply ignored instead of handling them. Any comment in a 'catch' block mutes the inspection.", - "markdown": "Reports an empty `catch` block. This indicates that errors are simply ignored instead of handling them. \n\nAny comment in a `catch` block mutes the inspection." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EmptyCatchBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSHint", - "shortDescription": { - "text": "JSHint" - }, - "fullDescription": { - "text": "Reports a problem detected by the JSHint linter.", - "markdown": "Reports a problem detected by the [JSHint](https://jshint.com/) linter." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JSHint", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code quality tools", - "index": 54, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FlowJSFlagCommentPlacement", - "shortDescription": { - "text": "Misplaced @flow flag" - }, - "fullDescription": { - "text": "Reports a '@flow' flag comment that is not located at the top of a file.", - "markdown": "Reports a `@flow` flag comment that is not located at the top of a file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FlowJSFlagCommentPlacement", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Flow type checker", - "index": 16, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Eslint", - "shortDescription": { - "text": "ESLint" - }, - "fullDescription": { - "text": "Reports a discrepancy detected by the ESLint linter. The highlighting is based on the rule severity specified in the ESLint configuration file for each individual rule. Clear the 'Use rule severity from the configuration file' checkbox to use the severity configured in this inspection for all ESLint rules.", - "markdown": "Reports a discrepancy detected by the [ESLint](https://eslint.org) linter. \n\nThe highlighting is based on the rule severity specified in the [ESLint configuration file](https://eslint.org/docs/user-guide/configuring) for each individual rule. \n\nClear the 'Use rule severity from the configuration file' checkbox to use the severity configured in this inspection for all ESLint rules." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "Eslint", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code quality tools", - "index": 54, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSDuplicatedDeclaration", - "shortDescription": { - "text": "Duplicate declaration" - }, - "fullDescription": { - "text": "Reports multiple declarations in a scope.", - "markdown": "Reports multiple declarations in a scope." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSDuplicatedDeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSEqualityComparisonWithCoercion.TS", - "shortDescription": { - "text": "Equality operator may cause type coercion" - }, - "fullDescription": { - "text": "Reports a usage of equality operators may cause unexpected type coercions. Suggests replacing '==' or '!=' equality operators with type-safe '===' or '!==' operators. Depending on the option selected, one of the following cases will be reported: All usages of '==' and '!=' operators. All usages except comparison with null. Some code styles allow using 'x == null' as a replacement for 'x === null || x === undefined'. Only suspicious expressions, such as: '==' or '!=' comparisons with '0', '''', 'null', 'true', 'false', or 'undefined'.", - "markdown": "Reports a usage of equality operators may cause unexpected type coercions. Suggests replacing `==` or `!=` equality operators with type-safe `===` or `!==` operators.\n\nDepending on the option selected, one of the following cases will be reported:\n\n* All usages of `==` and `!=` operators.\n* All usages except comparison with null. Some code styles allow using `x == null` as a replacement for `x === null || x === undefined`.\n* Only suspicious expressions, such as: `==` or `!=` comparisons with `0`, `''`, `null`, `true`, `false`, or `undefined`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EqualityComparisonWithCoercionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSOctalInteger", - "shortDescription": { - "text": "Octal integer" - }, - "fullDescription": { - "text": "Reports a deprecated octal integer literal prefixed with '0' instead of '0o'. Such literals are not allowed in modern ECMAScript code, and using them in the strict mode is an error. To force this inspection for ES5 and ES3 language levels, select the 'Warn about obsolete octal literals in ES5- code' checkbox below.", - "markdown": "Reports a deprecated octal integer literal prefixed with `0` instead of `0o`. \nSuch literals are not allowed in modern ECMAScript code, and using them in the strict mode is an error. \nTo force this inspection for ES5 and ES3 language levels, select the 'Warn about obsolete octal literals in ES5- code' checkbox below." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JSOctalInteger", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ExceptionCaughtLocallyJS", - "shortDescription": { - "text": "Exception used for local control-flow" - }, - "fullDescription": { - "text": "Reports a 'throw' statement whose exceptions are always caught by the containing 'try' statement. Using 'throw' statements as a 'goto' to change the local flow of control is confusing.", - "markdown": "Reports a `throw` statement whose exceptions are always caught by the containing `try` statement. Using `throw` statements as a `goto` to change the local flow of control is confusing." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ExceptionCaughtLocallyJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ThrowFromFinallyBlockJS", - "shortDescription": { - "text": "'throw' inside 'finally' block" - }, - "fullDescription": { - "text": "Reports s 'throw' statement inside a 'finally' block. Such 'throw' statements may mask exceptions thrown, and complicate debugging.", - "markdown": "Reports s `throw` statement inside a `finally` block. Such `throw` statements may mask exceptions thrown, and complicate debugging." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ThrowInsideFinallyBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptValidateGenericTypes", - "shortDescription": { - "text": "Incorrect generic type argument" - }, - "fullDescription": { - "text": "Reports an invalid type argument in a function, interface, or class declaration.", - "markdown": "Reports an invalid type argument in a function, interface, or class declaration." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "TypeScriptValidateGenericTypes", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CyclomaticComplexityJS", - "shortDescription": { - "text": "Overly complex function" - }, - "fullDescription": { - "text": "Reports a function with too many branching points in a function (too high cyclomatic complexity). Such functions may be confusing and hard to test. Use the field provided below to specify the maximum acceptable cyclomatic complexity for a function.", - "markdown": "Reports a function with too many branching points in a function (too high cyclomatic complexity). Such functions may be confusing and hard to test.\n\n\nUse the field provided below to specify the maximum acceptable cyclomatic complexity for a function." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "OverlyComplexFunctionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSMismatchedCollectionQueryUpdate", - "shortDescription": { - "text": "Mismatched query and update of collection" - }, - "fullDescription": { - "text": "Reports a collection of fields or variables whose contents are either queried and not updated or updated and not queried. Such mismatched queries and updates are pointless and may indicate either dead code or a typographical error. Query methods are automatically detected, based on whether they return something, or a callback is passed to them. Use the table below to specify which methods are update methods.", - "markdown": "Reports a collection of fields or variables whose contents are either queried and not updated or updated and not queried. Such mismatched queries and updates are pointless and may indicate either dead code or a typographical error.\n\n\nQuery methods are automatically detected, based on whether they return something, or a callback is passed to them.\nUse the table below to specify which methods are update methods." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSMismatchedCollectionQueryUpdate", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PackageJsonMismatchedDependency", - "shortDescription": { - "text": "Mismatched dependencies in package.json" - }, - "fullDescription": { - "text": "Reports a dependency from package.json that is not installed or doesn't match the specified version range.", - "markdown": "Reports a dependency from package.json that is not installed or doesn't match the specified [version range](https://docs.npmjs.com/about-semantic-versioning)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PackageJsonMismatchedDependency", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSPotentiallyInvalidUsageOfThis", - "shortDescription": { - "text": "Potentially invalid reference to 'this' from closure" - }, - "fullDescription": { - "text": "Reports a 'this' in closure that is used for referencing properties of outer context. Example: 'function Outer() {\n this.outerProp = 1;\n function inner() {\n // bad, because 'outerProp' of Outer\n // won't be updated here\n // on calling 'new Outer()' as may be expected\n this.outerProp = 2;\n }\n inner();\n}'", - "markdown": "Reports a `this` in closure that is used for referencing properties of outer context.\n\nExample:\n\n\n function Outer() {\n this.outerProp = 1;\n function inner() {\n // bad, because 'outerProp' of Outer\n // won't be updated here\n // on calling 'new Outer()' as may be expected\n this.outerProp = 2;\n }\n inner();\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSPotentiallyInvalidUsageOfThis", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSMissingSwitchDefault", - "shortDescription": { - "text": "'switch' statement has no 'default' branch" - }, - "fullDescription": { - "text": "Reports a 'switch' statement without a 'default' clause when some possible values are not enumerated.", - "markdown": "Reports a `switch` statement without a `default` clause when some possible values are not enumerated." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSMissingSwitchDefault", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Switch statement issues", - "index": 51, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSXNamespaceValidation", - "shortDescription": { - "text": "Missing JSX namespace" - }, - "fullDescription": { - "text": "Reports a usage of a JSX construction without importing namespace. Having the namespace in the file scope ensures proper code compilation.", - "markdown": "Reports a usage of a JSX construction without importing namespace. Having the namespace in the file scope ensures proper code compilation." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSXNamespaceValidation", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnresolvedLibraryURL", - "shortDescription": { - "text": "Missed locally stored library for HTTP link" - }, - "fullDescription": { - "text": "Reports a URL of an external JavaScript library that is not associated with any locally stored file. Suggests downloading the library. Such association enables the IDE to provide proper code completion and navigation.", - "markdown": "Reports a URL of an external JavaScript library that is not associated with any locally stored file. Suggests downloading the library. Such association enables the IDE to provide proper code completion and navigation." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnresolvedLibraryURL", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6PreferShortImport", - "shortDescription": { - "text": "Import can be shortened" - }, - "fullDescription": { - "text": "Reports an ES6 import whose 'from' part can be shortened. Suggests importing the parent directory.", - "markdown": "Reports an ES6 import whose `from` part can be shortened. Suggests importing the parent directory." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ES6PreferShortImport", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PointlessBitwiseExpressionJS", - "shortDescription": { - "text": "Bitwise expression can be simplified" - }, - "fullDescription": { - "text": "Reports an expression that includes 'and' with zero, 'or' by zero, or shifting by zero. Such expressions may result from not fully completed automated refactorings.", - "markdown": "Reports an expression that includes `and` with zero, `or` by zero, or shifting by zero. Such expressions may result from not fully completed automated refactorings." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PointlessBitwiseExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Bitwise operation issues", - "index": 22, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "InfiniteLoopJS", - "shortDescription": { - "text": "Infinite loop statement" - }, - "fullDescription": { - "text": "Reports a 'for', 'while', or 'do' statement which can only exit by throwing an exception. Such statements often indicate coding errors.", - "markdown": "Reports a `for`, `while`, or `do` statement which can only exit by throwing an exception. Such statements often indicate coding errors." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "InfiniteLoopJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSStringConcatenationToES6Template", - "shortDescription": { - "text": "String concatenation is used instead of template literal" - }, - "fullDescription": { - "text": "Reports a string concatenation. Suggests replacing it with a template literal Example '\"result: \" + a + \".\"' After applying the quick-fix the code looks as follows: '`result: ${a}.`'", - "markdown": "Reports a string concatenation. Suggests replacing it with a [template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)\n\nExample\n\n \"result: \" + a + \".\" \n\nAfter applying the quick-fix the code looks as follows:\n\n `result: ${a}.` \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSStringConcatenationToES6Template", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSArrowFunctionBracesCanBeRemoved", - "shortDescription": { - "text": "Redundant braces around arrow function body" - }, - "fullDescription": { - "text": "Reports an arrow function whose body only consists of braces and exactly one statement. Suggests converting to concise syntax without braces. 'let incrementer = (x) => {return x + 1};' After the quick-fix is applied, the code fragment looks as follows: 'let incrementer = (x) => x + 1;'", - "markdown": "Reports an arrow function whose body only consists of braces and exactly one statement. Suggests converting to concise syntax without braces.\n\n\n let incrementer = (x) => {return x + 1};\n\nAfter the quick-fix is applied, the code fragment looks as follows:\n\n\n let incrementer = (x) => x + 1;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSArrowFunctionBracesCanBeRemoved", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ReplaceAssignmentWithOperatorAssignmentJS", - "shortDescription": { - "text": "Assignment could be replaced with operator assignment" - }, - "fullDescription": { - "text": "Reports an assignment operation that can be replaced by an operator assignment to make your code shorter and probably clearer. Example: 'x = x + 3;'\n 'x = x / 3;'\n After the quick fix is applied the result looks like: 'x += 3;'\n 'x /= 3;'", - "markdown": "Reports an assignment operation that can be replaced by an operator assignment to make your code shorter and probably clearer.\n\n\nExample:\n\n x = x + 3;\n x = x / 3;\n\nAfter the quick fix is applied the result looks like:\n\n x += 3;\n x /= 3;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "AssignmentReplaceableWithOperatorAssignmentJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Assignment issues", - "index": 39, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSFileReferences", - "shortDescription": { - "text": "Unresolved file reference" - }, - "fullDescription": { - "text": "Reports an unresolved file reference in a JavaScript file, including CommonJS and AMD modules references.", - "markdown": "Reports an unresolved file reference in a JavaScript file, including CommonJS and AMD modules references." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSFileReferences", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Stylelint", - "shortDescription": { - "text": "Stylelint" - }, - "fullDescription": { - "text": "Reports a discrepancy detected by the Stylelint linter. The highlighting is based on the rule severity specified in the Stylelint configuration file for each individual rule.", - "markdown": "Reports a discrepancy detected by the [Stylelint](http://stylelint.io) linter. \n\nThe highlighting is based on the rule severity specified in the [Stylelint configuration file](https://stylelint.io/user-guide/configure) for each individual rule." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "Stylelint", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Code quality tools", - "index": 57, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FunctionWithInconsistentReturnsJS", - "shortDescription": { - "text": "Function with inconsistent returns" - }, - "fullDescription": { - "text": "Reports a function that returns a value in some cases while in other cases no value is returned. This usually indicates an error. Example: 'function foo() {\n if (true)\n return 3;\n return;\n}'", - "markdown": "Reports a function that returns a value in some cases while in other cases no value is returned. This usually indicates an error.\n\nExample:\n\n\n function foo() {\n if (true)\n return 3;\n return;\n }\n\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionWithInconsistentReturnsJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ClassMemberInitializationOrder", - "shortDescription": { - "text": "Use of possibly unassigned property in a static initializer" - }, - "fullDescription": { - "text": "Reports a class member initializer which references another non-hoisted class member while the latter may be not initialized yet. Initialization of class members happens consequently for fields, so a field cannot reference another field that is declared later.", - "markdown": "Reports a class member initializer which references another non-hoisted class member while the latter may be not initialized yet. \n\nInitialization of class members happens consequently for fields, so a field cannot reference another field that is declared later." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ES6ClassMemberInitializationOrder", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EmptyTryBlockJS", - "shortDescription": { - "text": "Empty 'try' block" - }, - "fullDescription": { - "text": "Reports an empty 'try' block, which usually indicates an error.", - "markdown": "Reports an empty `try` block, which usually indicates an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EmptyTryBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ReservedWordUsedAsNameJS", - "shortDescription": { - "text": "Reserved word used as name" - }, - "fullDescription": { - "text": "Reports a JavaScript reserved word used as a name. The JavaScript specification reserves a number of words which are currently not used as keywords. Using those words as identifiers may result in broken code if later versions of JavaScript start using them as keywords.", - "markdown": "Reports a JavaScript reserved word used as a name. The JavaScript specification reserves a number of words which are currently not used as keywords. Using those words as identifiers may result in broken code if later versions of JavaScript start using them as keywords." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ReservedWordAsName", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSClassNamingConvention", - "shortDescription": { - "text": "Class naming convention" - }, - "fullDescription": { - "text": "Reports a class or a function that is annotated with a JSDoc '@constructor' or '@class' tag whose names are too short, too long, or do not follow the specified regular expression pattern. Use the fields provided below to specify minimum length, maximum length, and a regular expression expected for classes names. Use the standard 'java.util.regex' format for regular expressions.", - "markdown": "Reports a class or a function that is annotated with a JSDoc `@constructor` or `@class` tag whose names are too short, too long, or do not follow the specified regular expression pattern.\n\n\nUse the fields provided below to specify minimum length, maximum length, and a regular expression\nexpected for classes names. Use the standard `java.util.regex` format for regular expressions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSClassNamingConvention", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Naming conventions", - "index": 50, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptValidateJSTypes", - "shortDescription": { - "text": "Type mismatch in 'any' type" - }, - "fullDescription": { - "text": "Reports a function call with a parameter, return value, or assigned expression or incorrect type, if the context symbol can be implicitly resolved to the 'any' type. declare var test: any;\ntest.hasOwnProperty(true); //reports 'true'", - "markdown": "Reports a function call with a parameter, return value, or assigned expression or incorrect type, if the context symbol can be implicitly resolved to the `any` type.\n\n```\ndeclare var test: any;\ntest.hasOwnProperty(true); //reports 'true'\n```" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptValidateJSTypes", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NestedFunctionJS", - "shortDescription": { - "text": "Nested function" - }, - "fullDescription": { - "text": "Reports a function nested inside another function. Although JavaScript allows functions to be nested, such constructs may be confusing. Use the checkbox below to ignore anonymous nested functions.", - "markdown": "Reports a function nested inside another function. Although JavaScript allows functions to be nested, such constructs may be confusing.\n\n\nUse the checkbox below to ignore anonymous nested functions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NestedFunctionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XHTMLIncompatabilitiesJS", - "shortDescription": { - "text": "Incompatible XHTML usages" - }, - "fullDescription": { - "text": "Reports common JavaScript DOM patterns which may present problems with XHTML documents. In particular, the patterns detected will behave completely differently depending on whether the document is loaded as XML or HTML. This can result in subtle bugs where script behaviour is dependent on the MIME-type of the document, rather than its content. Patterns detected include document.body, document.images, document.applets, document.links, document.forms, and document.anchors.", - "markdown": "Reports common JavaScript DOM patterns which may present problems with XHTML documents. In particular, the patterns detected will behave completely differently depending on whether the document is loaded as XML or HTML. This can result in subtle bugs where script behaviour is dependent on the MIME-type of the document, rather than its content. Patterns detected include **document.body** , **document.images** , **document.applets** , **document.links** , **document.forms** , and **document.anchors**." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "XHTMLIncompatabilitiesJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/DOM issues", - "index": 52, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "IncrementDecrementResultUsedJS", - "shortDescription": { - "text": "Result of increment or decrement used" - }, - "fullDescription": { - "text": "Reports an increment ('++') or decrement ('--') expression where the result of the assignment is used in a containing expression. Such assignments can result in confusion due to the order of operations, as evaluation of the assignment may affect the outer expression in unexpected ways. Example: 'var a = b++'", - "markdown": "Reports an increment (`++`) or decrement (`--`) expression where the result of the assignment is used in a containing expression. Such assignments can result in confusion due to the order of operations, as evaluation of the assignment may affect the outer expression in unexpected ways. Example: `var a = b++`" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "IncrementDecrementResultUsedJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SuspiciousTypeOfGuard", - "shortDescription": { - "text": "Unsound type guard check" - }, - "fullDescription": { - "text": "Reports a 'typeof' or 'instanceof' unsound type guard check. The 'typeof x' type guard can be unsound in one of the following two cases: 'typeof x' never corresponds to the specified value (for example, 'typeof x === 'number'' when 'x' is of the type 'string | boolean') 'typeof x' always corresponds to the specified value (for example, 'typeof x === 'string'' when 'x' is of the type 'string') The 'x instanceof A' type guard can be unsound in one of the following two cases: The type of 'x' is not related to 'A' The type of 'x' is 'A' or a subtype of 'A'", - "markdown": "Reports a `typeof` or `instanceof` unsound type guard check. The `typeof x` type guard can be unsound in one of the following two cases:\n\n* `typeof x` never corresponds to the specified value (for example, `typeof x === 'number'` when `x` is of the type 'string \\| boolean')\n* `typeof x` always corresponds to the specified value (for example, `typeof x === 'string'` when `x` is of the type 'string')\n\n
\n\nThe `x instanceof A` type guard can be unsound in one of the following two cases:\n\n* The type of `x` is not related to `A`\n* The type of `x` is `A` or a subtype of `A`" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SuspiciousTypeOfGuard", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptJSXUnresolvedComponent", - "shortDescription": { - "text": "Unresolved JSX component" - }, - "fullDescription": { - "text": "Reports an unresolved reference to a JSX component. Suggests adding an import statement if the referenced component is defined in the project or its dependencies or creating a new component with the specified name. The template for a new component can be modified in Editor | File and Code Templates.", - "markdown": "Reports an unresolved reference to a JSX component. Suggests adding an import statement if the referenced component is defined in the project or its dependencies or creating a new component with the specified name.\n\nThe template for a new component can be modified in Editor \\| File and Code Templates." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptJSXUnresolvedComponent", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptFieldCanBeMadeReadonly", - "shortDescription": { - "text": "Field can be readonly" - }, - "fullDescription": { - "text": "Reports a private field that can be made readonly (for example, if the field is assigned only in the constructor).", - "markdown": "Reports a private field that can be made readonly (for example, if the field is assigned only in the constructor)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptFieldCanBeMadeReadonly", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6DestructuringVariablesMerge", - "shortDescription": { - "text": "Destructuring properties with the same key" - }, - "fullDescription": { - "text": "Reports multiple destructuring properties with identical keys. Suggests merging the properties.", - "markdown": "Reports multiple destructuring properties with identical keys. Suggests merging the properties." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6DestructuringVariablesMerge", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LoopStatementThatDoesntLoopJS", - "shortDescription": { - "text": "Loop statement that doesn't loop" - }, - "fullDescription": { - "text": "Reports a 'for', 'while', or 'do' statement whose bodies are guaranteed to execute at most once. Normally, this indicates an error.", - "markdown": "Reports a `for`, `while`, or `do` statement whose bodies are guaranteed to execute at most once. Normally, this indicates an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LoopStatementThatDoesntLoopJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NegatedIfStatementJS", - "shortDescription": { - "text": "Negated 'if' statement" - }, - "fullDescription": { - "text": "Reports if statements which have an else branch and a negated condition. Flipping the order of the if and else branches will usually increase the clarity of such statements.", - "markdown": "Reports **if** statements which have an **else** branch and a negated condition. Flipping the order of the **if** and **else** branches will usually increase the clarity of such statements." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NegatedIfStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSNonASCIINames", - "shortDescription": { - "text": "Identifiers with non-ASCII symbols" - }, - "fullDescription": { - "text": "Reports a non-ASCII symbol in a name. If the 'Allow only ASCII names' option is selected, reports all names that contain non-ASCII symbols. Otherwise reports all names that contain both ASCII and non-ASCII symbols.", - "markdown": "Reports a non-ASCII symbol in a name. \n\nIf the 'Allow only ASCII names' option is selected, reports all names that contain non-ASCII symbols. \nOtherwise reports all names that contain both ASCII and non-ASCII symbols." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSNonASCIINames", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Naming conventions", - "index": 50, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptRedundantGenericType", - "shortDescription": { - "text": "Redundant type arguments" - }, - "fullDescription": { - "text": "Reports a type argument that is equal to the default one and can be removed. Example: 'type Foo = T;\nlet z: Foo;'", - "markdown": "Reports a type argument that is equal to the default one and can be removed.\n\n\nExample:\n\n\n type Foo = T;\n let z: Foo;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptRedundantGenericType", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptUMDGlobal", - "shortDescription": { - "text": "Referenced UMD global variable" - }, - "fullDescription": { - "text": "Reports a usage of a Universal Module Definition (UMD) global variable if the current file is a module (ECMAScript or CommonJS). Referencing UMD variables without explicit imports can lead to a runtime error if the library isn't included implicitly.", - "markdown": "Reports a usage of a Universal Module Definition (UMD) global variable if the current file is a module (ECMAScript or CommonJS). Referencing UMD variables without explicit imports can lead to a runtime error if the library isn't included implicitly." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptUMDGlobal", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnnecessaryReturnJS", - "shortDescription": { - "text": "Unnecessary 'return' statement" - }, - "fullDescription": { - "text": "Reports an unnecessary 'return' statement, that is, a 'return' statement that returns no value and occurs just before the function would have \"fallen through\" the bottom. These statements may be safely removed.", - "markdown": "Reports an unnecessary `return` statement, that is, a `return` statement that returns no value and occurs just before the function would have \"fallen through\" the bottom. These statements may be safely removed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnnecessaryReturnStatementJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ConditionalExpressionWithIdenticalBranchesJS", - "shortDescription": { - "text": "Conditional expression with identical branches" - }, - "fullDescription": { - "text": "Reports a ternary conditional expression with identical 'then' and 'else' branches.", - "markdown": "Reports a ternary conditional expression with identical `then` and `else` branches." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ConditionalExpressionWithIdenticalBranchesJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSIncompatibleTypesComparison", - "shortDescription": { - "text": "Comparison of expressions having incompatible types" - }, - "fullDescription": { - "text": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values.", - "markdown": "Reports a comparison with operands of incompatible types or an operand with a type without possible common values." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSIncompatibleTypesComparison", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSAnnotator", - "shortDescription": { - "text": "ECMAScript specification is not followed" - }, - "fullDescription": { - "text": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. Generally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors.", - "markdown": "Reports basic syntax issues and inconsistencies with language specification, such as invalid usages of keywords, usages of incompatible numeric format, or multiple parameters to getters/setters. \nGenerally, such errors must always be reported and shouldn't be disabled. But in some cases, such as issues due to the dynamic nature of JavaScript, the use of not yet supported language features, or bugs in IDE's checker, it may be handy to disable reporting these very basic errors." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JSAnnotator", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnfilteredForInLoop", - "shortDescription": { - "text": "Unfiltered for..in loop" - }, - "fullDescription": { - "text": "Reports unfiltered 'for-in' loops. The use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when 'Object''s prototype may be incorrectly modified. For example, the following code will print 42 and myMethod: 'Object.prototype.myMethod = function myMethod() {};\nlet a = { foo: 42 };\nfor (let i in a) {\n console.log(a[i]);\n}' Suggests replacing the whole loop with a 'Object.keys()' method or adding a 'hasOwnProperty()' check. After applying the quick-fix the code looks as follows: 'for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n}'", - "markdown": "Reports unfiltered `for-in` loops. \n\nThe use of this construct results in processing not only own properties of an object but properties from its prototype as well. It may be unexpected in some specific cases, for example, in utility methods that copy or modify all properties or when `Object`'s prototype may be incorrectly modified. For example, the following code will print **42** and **myMethod** : \n\n\n Object.prototype.myMethod = function myMethod() {};\n let a = { foo: 42 };\n for (let i in a) {\n console.log(a[i]);\n }\n\nSuggests replacing the whole loop with a `Object.keys()` method or adding a `hasOwnProperty()` check. After applying the quick-fix the code looks as follows:\n\n\n for (let i in a) {\n if (a.hasOwnProperty(i)) {\n console.log(a[i]);\n }\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnfilteredForInLoop", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSLastCommaInObjectLiteral", - "shortDescription": { - "text": "Unneeded last comma in object literal" - }, - "fullDescription": { - "text": "Reports usages of a trailing comma in object literals. The warning is reported only when the JavaScript language version is set to ECMAScript 5.1. Trailing commas in object literals are allowed by the specification, however, some browsers might throw an error when a trailing comma is used. You can configure formatting options for trailing commas in Code Style | JavaScript or TypeScript | Punctuation.", - "markdown": "Reports usages of a trailing comma in object literals.\n\nThe warning is reported only when the JavaScript language version is set to ECMAScript 5.1.\n\nTrailing commas in object literals are allowed by the specification, however, some browsers might throw an error when a trailing comma is used.\n\nYou can configure formatting options for trailing commas in **Code Style** \\| **JavaScript** or **TypeScript** \\| **Punctuation**." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSLastCommaInObjectLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSFunctionExpressionToArrowFunction", - "shortDescription": { - "text": "Function expression is used instead of arrow function" - }, - "fullDescription": { - "text": "Reports a function expression. Suggests converting it to an arrow function. Example: 'arr.map(function(el) {return el + 1})' After applying the quick-fix the code looks as follows: 'arr.map(el => el + 1)'", - "markdown": "Reports a [function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function) expression. Suggests converting it to an [arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions).\n\nExample:\n\n arr.map(function(el) {return el + 1})\n\nAfter applying the quick-fix the code looks as follows:\n\n arr.map(el => el + 1)\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSFunctionExpressionToArrowFunction", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6TopLevelAwaitExpression", - "shortDescription": { - "text": "Top-level 'await' expression" - }, - "fullDescription": { - "text": "Reports a usage of a top-level 'await' expression. While the new 'top-level async' proposal is on its way, using 'await' outside async functions is not allowed.", - "markdown": "Reports a usage of a top-level `await` expression. While the new 'top-level async' proposal is on its way, using `await` outside async functions is not allowed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "ES6TopLevelAwaitExpression", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Async code and promises", - "index": 53, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6MissingAwait", - "shortDescription": { - "text": "Missing await for an async function call" - }, - "fullDescription": { - "text": "Reports an 'async' function call without an expected 'await' prefix inside an 'async' function. Such call returns a 'Promise' and control flow is continued immediately. Example: 'async function bar() { /* ... */ }\nasync function foo() {\n bar(); // bad\n}' After the quick-fix is applied, the 'await' prefix is added: 'async function bar() { /* ... */ }\nasync function foo() {\n await bar(); // good\n}' When the 'Report for promises in return statements' checkbox is selected, also suggests adding 'await' in return statements. While this is generally not necessary, it gives two main benefits. You won't forget to add 'await' when surrounding your code with 'try-catch'. An explicit 'await' helps V8 runtime to provide async stack traces.", - "markdown": "Reports an `async` function call without an expected `await` prefix inside an `async` function. Such call returns a `Promise` and control flow is continued immediately.\n\nExample:\n\n\n async function bar() { /* ... */ }\n async function foo() {\n bar(); // bad\n }\n\n\nAfter the quick-fix is applied, the `await` prefix is added:\n\n\n async function bar() { /* ... */ }\n async function foo() {\n await bar(); // good\n }\n\n
\n\nWhen the 'Report for promises in return statements' checkbox is selected, also suggests adding `await` in return statements. \nWhile this is generally not necessary, it gives two main benefits. \n\n* You won't forget to add `await` when surrounding your code with `try-catch`.\n* An explicit `await` helps V8 runtime to provide [async stack traces](https://bit.ly/v8-zero-cost-async-stack-traces)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6MissingAwait", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Async code and promises", - "index": 53, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TailRecursionJS", - "shortDescription": { - "text": "Tail recursion" - }, - "fullDescription": { - "text": "Reports a tail recursion, that is, when a function calls itself as its last action before returning. A tail recursion can always be replaced by looping, which will be considerably faster. Some JavaScript engines perform this optimization, while others do not. Thus, tail recursive solutions may have considerably different performance characteristics in different environments.", - "markdown": "Reports a tail recursion, that is, when a function calls itself as its last action before returning. A tail recursion can always be replaced by looping, which will be considerably faster. Some JavaScript engines perform this optimization, while others do not. Thus, tail recursive solutions may have considerably different performance characteristics in different environments." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TailRecursionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Control flow issues", - "index": 3, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6ConvertToForOf", - "shortDescription": { - "text": "'for..in' is used instead of 'for..of'" - }, - "fullDescription": { - "text": "Reports a usage of a 'for..in' loop on an array. Suggests replacing it with a 'for..of' loop. 'for..of' loops, which are introduced in ECMAScript 6, iterate over 'iterable' objects. For arrays, this structure is preferable to 'for..in', because it works only with array values but not with array object's properties.", - "markdown": "Reports a usage of a [for..in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop on an array. Suggests replacing it with a [for..of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) loop. \n`for..of` loops, which are introduced in ECMAScript 6, iterate over `iterable` objects. For arrays, this structure is preferable to `for..in`, because it works only with array values but not with array object's properties." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6ConvertToForOf", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/ES2015 migration aids", - "index": 23, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FlowJSCoverage", - "shortDescription": { - "text": "Code is not covered by Flow" - }, - "fullDescription": { - "text": "Reports JavaScript code fragments that are not covered by the Flow type checker. To use this inspection, configure the Flow executable in Settings | Languages & Frameworks | JavaScript.", - "markdown": "Reports JavaScript code fragments that are not covered by the Flow type checker. To use this inspection, configure the Flow executable in [Settings \\| Languages \\& Frameworks \\| JavaScript](settings://Settings.JavaScript)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "FlowJSCoverage", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Flow type checker", - "index": 16, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ParameterNamingConventionJS", - "shortDescription": { - "text": "Function parameter naming convention" - }, - "fullDescription": { - "text": "Reports a function parameter whose name is too short, too long, or doesn't follow the specified regular expression pattern. Use the fields provided below to specify minimum length, maximum length and regular expression expected for local variables names. Use the standard 'java.util.regex' format regular expressions.", - "markdown": "Reports a function parameter whose name is too short, too long, or doesn't follow the specified regular expression pattern.\n\n\nUse the fields provided below to specify minimum length, maximum length and regular expression\nexpected for local variables names. Use the standard `java.util.regex` format regular expressions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ParameterNamingConventionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Naming conventions", - "index": 50, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUndefinedPropertyAssignment", - "shortDescription": { - "text": "Undefined property assignment" - }, - "fullDescription": { - "text": "Reports an assignment to a property that is not defined in the type of a variable. Example: '/**\n * @type {{ property1: string, property2: number }}\n */\nlet myVariable = create();\n\nmyVariable.newProperty = 3; // bad'", - "markdown": "Reports an assignment to a property that is not defined in the type of a variable.\n\nExample:\n\n\n /**\n * @type {{ property1: string, property2: number }}\n */\n let myVariable = create();\n\n myVariable.newProperty = 3; // bad\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSUndefinedPropertyAssignment", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "StandardJS", - "shortDescription": { - "text": "Standard code style" - }, - "fullDescription": { - "text": "Reports a discrepancy detected by the JavaScript Standard Style linter. The highlighting severity in the editor is based on the severity level the linter reports.", - "markdown": "Reports a discrepancy detected by the [JavaScript Standard Style](https://standardjs.com/) linter. \n\nThe highlighting severity in the editor is based on the severity level the linter reports." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "StandardJS", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code quality tools", - "index": 54, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ParametersPerFunctionJS", - "shortDescription": { - "text": "Function with too many parameters" - }, - "fullDescription": { - "text": "Reports a function with too many parameters. Such functions often indicate problems with design. Use the field below to specify the maximum acceptable number of parameters for a function.", - "markdown": "Reports a function with too many parameters. Such functions often indicate problems with design.\n\n\nUse the field below to specify the maximum acceptable number of parameters for a function." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "OverlyComplexFunctionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ThisExpressionReferencesGlobalObjectJS", - "shortDescription": { - "text": "'this' expression which references the global object" - }, - "fullDescription": { - "text": "Reports a 'this' expression outside an object literal or a constructor body. Such 'this' expressions reference the top-level \"global\" JavaScript object, but are mostly useless.", - "markdown": "Reports a `this` expression outside an object literal or a constructor body. Such `this` expressions reference the top-level \"global\" JavaScript object, but are mostly useless." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ThisExpressionReferencesGlobalObjectJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Validity issues", - "index": 28, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NestedAssignmentJS", - "shortDescription": { - "text": "Nested assignment" - }, - "fullDescription": { - "text": "Reports an assignment expression nested inside another expression, for example, 'a = b = 1'. Such expressions may be confusing and violate the general design principle that a given construct should do precisely one thing.", - "markdown": "Reports an assignment expression nested inside another expression, for example, `a = b = 1`. Such expressions may be confusing and violate the general design principle that a given construct should do precisely one thing." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NestedAssignmentJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Assignment issues", - "index": 39, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DefaultNotLastCaseInSwitchJS", - "shortDescription": { - "text": "'default' not last case in 'switch'" - }, - "fullDescription": { - "text": "Reports a 'switch' statement where the 'default' case comes before another case instead of being the very last case, which may cause confusion.", - "markdown": "Reports a `switch` statement where the `default` case comes before another case instead of being the very last case, which may cause confusion." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DefaultNotLastCaseInSwitchJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Switch statement issues", - "index": 51, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ConfusingPlusesOrMinusesJS", - "shortDescription": { - "text": "Confusing sequence of '+' or '-'" - }, - "fullDescription": { - "text": "Reports a suspicious combination of '+' or '-' characters in JavaScript code (for example, 'a+++b'. Such sequences are confusing, and their semantics may change through changes in the whitespace.", - "markdown": "Reports a suspicious combination of `+` or `-` characters in JavaScript code (for example, `a+++b`. Such sequences are confusing, and their semantics may change through changes in the whitespace." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ConfusingPlusesOrMinusesJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSDeprecatedSymbols", - "shortDescription": { - "text": "Deprecated symbol used" - }, - "fullDescription": { - "text": "Reports a usage of a deprecated function variable.", - "markdown": "Reports a usage of a deprecated function variable." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSDeprecatedSymbols", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LocalVariableNamingConventionJS", - "shortDescription": { - "text": "Local variable naming convention" - }, - "fullDescription": { - "text": "Reports a local variable whose name is too short, too long, or doesn't follow the specified regular expression pattern. Use the fields provided below to specify minimum length, maximum length, and a regular expression expected for local variables names. Use the standard 'java.util.regex' format regular expressions.", - "markdown": "Reports a local variable whose name is too short, too long, or doesn't follow the specified regular expression pattern.\n\n\nUse the fields provided below to specify minimum length, maximum length, and a regular expression\nexpected for local variables names. Use the standard `java.util.regex` format regular expressions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LocalVariableNamingConventionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Naming conventions", - "index": 50, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EmptyFinallyBlockJS", - "shortDescription": { - "text": "Empty 'finally' block" - }, - "fullDescription": { - "text": "Reports an empty 'finally' block, which usually indicates an error.", - "markdown": "Reports an empty `finally` block, which usually indicates an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EmptyFinallyBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSCommentMatchesSignature", - "shortDescription": { - "text": "Mismatched JSDoc and function signature" - }, - "fullDescription": { - "text": "Reports mismatch between the names and the number of parameters within a JSDoc comment and the actual parameters of a function. Suggests updating parameters in JSDoc comment. Example: '/**\n * @param height Height in pixels\n */\nfunction sq(height, width) {} // width is not documented' After the quick-fix is applied: '/**\n * @param height Height in pixels\n * @param width\n */\nfunction sq(height, width) {}'", - "markdown": "Reports mismatch between the names and the number of parameters within a JSDoc comment and the actual parameters of a function. Suggests updating parameters in JSDoc comment.\n\n**Example:**\n\n\n /**\n * @param height Height in pixels\n */\n function sq(height, width) {} // width is not documented\n\nAfter the quick-fix is applied:\n\n\n /**\n * @param height Height in pixels\n * @param width\n */\n function sq(height, width) {}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSCommentMatchesSignature", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UpdateDependencyToLatestVersion", - "shortDescription": { - "text": "Update package.json dependencies to latest versions" - }, - "fullDescription": { - "text": "Suggests to upgrade your package.json dependencies to the latest versions, ignoring specified versions.", - "markdown": "Suggests to upgrade your package.json dependencies to the latest versions, ignoring specified versions." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "UpdateDependencyToLatestVersion", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Imports and dependencies", - "index": 47, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptConfig", - "shortDescription": { - "text": "Inconsistent tsconfig.json properties" - }, - "fullDescription": { - "text": "Reports inconsistency of a 'paths', 'checkJs', or 'extends' property in a tsconfig.json file. The 'checkJs' property requires 'allowJs'. The 'extends' property should be a valid file reference.", - "markdown": "Reports inconsistency of a `paths`, `checkJs`, or `extends` property in a tsconfig.json file. \nThe `checkJs` property requires `allowJs`. \nThe `extends` property should be a valid file reference." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TypeScriptConfig", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSSuspiciousNameCombination", - "shortDescription": { - "text": "Suspicious variable/parameter name combination" - }, - "fullDescription": { - "text": "Reports an assignment or a function call where the name of the target variable or the function parameter does not match the name of the value assigned to it. Example: 'var x = 0;\n var y = x;' or 'var x = 0, y = 0;\n var rc = new Rectangle(y, x, 20, 20);' Here the inspection guesses that 'x' and 'y' are mixed up. Specify the names that should not be used together. An error is reported if a parameter name or an assignment target name contains words from one group while the name of the assigned or passed variable contains words from another group.", - "markdown": "Reports an assignment or a function call where the name of the target variable or the function parameter does not match the name of the value assigned to it.\n\nExample:\n\n\n var x = 0;\n var y = x;\n\nor\n\n\n var x = 0, y = 0;\n var rc = new Rectangle(y, x, 20, 20);\n\nHere the inspection guesses that `x` and `y` are mixed up.\n\nSpecify the names that should not be used together. An error is reported\nif a parameter name or an assignment target name contains words from one group while the name of the assigned or passed\nvariable contains words from another group." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSSuspiciousNameCombination", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnresolvedExtXType", - "shortDescription": { - "text": "Unresolved Ext JS xtype" - }, - "fullDescription": { - "text": "Reports an Ext JS 'xtype' reference that doesn't have a corresponding class.", - "markdown": "Reports an Ext JS `xtype` reference that doesn't have a corresponding class." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnresolvedExtXType", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ForLoopThatDoesntUseLoopVariableJS", - "shortDescription": { - "text": "'for' loop where update or condition does not use loop variable" - }, - "fullDescription": { - "text": "Reports a 'for' loop where the condition or update does not use the 'for' loop variable.", - "markdown": "Reports a `for` loop where the condition or update does not use the `for` loop variable." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ForLoopThatDoesntUseLoopVariableJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TypeScriptAbstractClassConstructorCanBeMadeProtected", - "shortDescription": { - "text": "Abstract class constructor can be made protected" - }, - "fullDescription": { - "text": "Reports a public constructor of an abstract class and suggests making it protected (because it is useless to have it public).", - "markdown": "Reports a public constructor of an abstract class and suggests making it protected (because it is useless to have it public)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "TypeScriptAbstractClassConstructorCanBeMadeProtected", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/TypeScript", - "index": 27, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "FunctionWithMultipleReturnPointsJS", - "shortDescription": { - "text": "Function with multiple return points" - }, - "fullDescription": { - "text": "Reports a function with multiple return points. Such functions are hard to understand and maintain.", - "markdown": "Reports a function with multiple return points. Such functions are hard to understand and maintain." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionWithMultipleReturnPointsJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSIgnoredPromiseFromCall", - "shortDescription": { - "text": "Result of method call returning a promise is ignored" - }, - "fullDescription": { - "text": "Reports a function call that returns a 'Promise' that is not used later. Such calls are usually unintended and indicate an error.", - "markdown": "Reports a function call that returns a `Promise` that is not used later. Such calls are usually unintended and indicate an error." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSIgnoredPromiseFromCall", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Async code and promises", - "index": 53, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ThreeNegationsPerFunctionJS", - "shortDescription": { - "text": "Function with more than three negations" - }, - "fullDescription": { - "text": "Reports a function with three or more negation operations ('!' or '!='). Such functions may be unnecessarily confusing.", - "markdown": "Reports a function with three or more negation operations (`!` or `!=`). Such functions may be unnecessarily confusing." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "FunctionWithMoreThanThreeNegationsJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Function metrics", - "index": 35, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSRemoveUnnecessaryParentheses", - "shortDescription": { - "text": "Unnecessary parentheses" - }, - "fullDescription": { - "text": "Reports redundant parentheses. In expressions: 'var x = ((1) + 2) + 3' In arrow function argument lists: 'var incrementer = (x) => x + 1' In TypeScript and Flow type declarations: 'type Card = (Suit & Rank) | (Suit & Number)'", - "markdown": "Reports redundant parentheses.\n\nIn expressions:\n\n var x = ((1) + 2) + 3\n\nIn arrow function argument lists:\n\n var incrementer = (x) => x + 1\n\nIn TypeScript and Flow type declarations:\n\n type Card = (Suit & Rank) | (Suit & Number)\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSRemoveUnnecessaryParentheses", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Code style issues", - "index": 12, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "OverlyComplexBooleanExpressionJS", - "shortDescription": { - "text": "Overly complex boolean expression" - }, - "fullDescription": { - "text": "Reports a boolean expression with too many terms. Such expressions may be confusing and bug-prone. Use the field below to specify the maximum number of terms allowed in an arithmetic expression.", - "markdown": "Reports a boolean expression with too many terms. Such expressions may be confusing and bug-prone.\n\n\nUse the field below to specify the maximum number of terms allowed in an arithmetic expression." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "OverlyComplexBooleanExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "OverlyComplexArithmeticExpressionJS", - "shortDescription": { - "text": "Overly complex arithmetic expression" - }, - "fullDescription": { - "text": "Reports an arithmetic expression with too many terms. Such expressions may be confusing and bug-prone. Use the field below to specify the maximum number of terms allowed in an arithmetic expression.", - "markdown": "Reports an arithmetic expression with too many terms. Such expressions may be confusing and bug-prone.\n\n\nUse the field below to specify the maximum number of terms allowed in an arithmetic expression." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "OverlyComplexArithmeticExpressionJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Potentially confusing code constructs", - "index": 29, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ES6RedundantNestingInTemplateLiteral", - "shortDescription": { - "text": "Redundant nesting in template literal" - }, - "fullDescription": { - "text": "Reports nested instances of a string or a template literal. Suggests inlining the nested instances into the containing template string. Example: 'let a = `Hello, ${`Brave ${\"New\"}`} ${\"World\"}!`' After applying the quick-fix the code looks as follows: 'let a = `Hello, Brave New World!`'", - "markdown": "Reports nested instances of a string or a template literal. Suggests inlining the nested instances into the containing template string.\n\nExample:\n\n\n let a = `Hello, ${`Brave ${\"New\"}`} ${\"World\"}!`\n\nAfter applying the quick-fix the code looks as follows:\n\n\n let a = `Hello, Brave New World!`\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "ES6RedundantNestingInTemplateLiteral", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "StringLiteralBreaksHTMLJS", - "shortDescription": { - "text": "String literal which breaks HTML parsing" - }, - "fullDescription": { - "text": "Reports a string literal that contains a '\n\nThe following usages are ignored:\n\n* Inside a return statement\n* In some binary operations\n* For overridden non-void functions" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSVoidFunctionReturnValueUsed", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Probable bugs", - "index": 17, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSUnusedLocalSymbols", - "shortDescription": { - "text": "Unused local symbol" - }, - "fullDescription": { - "text": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration.", - "markdown": "Reports an unused locally accessible parameter, local variable, function, class, or private member declaration." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JSUnusedLocalSymbols", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Unused symbols", - "index": 19, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ReturnFromFinallyBlockJS", - "shortDescription": { - "text": "'return' inside 'finally' block" - }, - "fullDescription": { - "text": "Reports a 'return' statement inside a 'finally' block. Such 'return' statements may mask exceptions thrown, and complicate debugging.", - "markdown": "Reports a `return` statement inside a `finally` block. Such `return` statements may mask exceptions thrown, and complicate debugging." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ReturnInsideFinallyBlockJS", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Try statement issues", - "index": 33, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JSValidateTypes", - "shortDescription": { - "text": "Type mismatch" - }, - "fullDescription": { - "text": "Reports incorrect type of: a parameter in a function call a return value an assigned expression TypeScript code is ignored.", - "markdown": "Reports incorrect type of:\n\n* a parameter in a function call\n* a return value\n* an assigned expression\n\nTypeScript code is ignored." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JSValidateTypes", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.intellij.plugins.postcss", - "version": "232.9876", - "rules": [ - { - "id": "PostCssCustomSelector", - "shortDescription": { - "text": "Invalid custom selector" - }, - "fullDescription": { - "text": "Reports a syntax error in PostCSS Custom Selector. Example: '@custom-selector :--heading h1, h2, h3;'", - "markdown": "Reports a syntax error in [PostCSS Custom Selector](https://github.com/postcss/postcss-custom-selectors).\n\nExample:\n\n\n @custom-selector :--heading h1, h2, h3;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "PostCssCustomSelector", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "PostCSS", - "index": 5, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PostCssUnresolvedModuleValueReference", - "shortDescription": { - "text": "Unresolved CSS module value" - }, - "fullDescription": { - "text": "Reports an unresolved reference to a CSS Module Value ('@value' declaration). Example: '@value foo from unknown;'", - "markdown": "Reports an unresolved reference to a [CSS Module Value](https://github.com/css-modules/postcss-modules-values) (`@value` declaration).\n\nExample:\n\n\n @value foo from unknown;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "PostCssUnresolvedModuleValueReference", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "PostCSS", - "index": 5, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PostCssNesting", - "shortDescription": { - "text": "Invalid nested rule" - }, - "fullDescription": { - "text": "Reports a nested style rule whose syntax doesn't comply with the PostCSS Nested or the PostCSS Nesting specification. Example: '.phone {\n &_title {}\n}'", - "markdown": "Reports a nested style rule whose syntax doesn't comply with the [PostCSS Nested](https://github.com/postcss/postcss-nested) or the [PostCSS Nesting](https://github.com/csstools/postcss-nesting) specification.\n\nExample:\n\n\n .phone {\n &_title {}\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PostCssNesting", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "PostCSS", - "index": 5, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PostCssCustomMedia", - "shortDescription": { - "text": "Invalid custom media" - }, - "fullDescription": { - "text": "Reports a syntax error in a PostCSS Custom Media query. Example: '@custom-media --small-viewport (max-width: 30em);'", - "markdown": "Reports a syntax error in a [PostCSS Custom Media](https://github.com/postcss/postcss-custom-media) query.\n\nExample:\n\n\n @custom-media --small-viewport (max-width: 30em);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "PostCssCustomMedia", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "PostCSS", - "index": 5, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PostCssMediaRange", - "shortDescription": { - "text": "Invalid media query range" - }, - "fullDescription": { - "text": "Checks range context syntax, which may alternatively be used for media features with a 'range' type. Example: '@media screen and (500px <= width <= 1200px) {}'", - "markdown": "Checks [range context](https://github.com/postcss/postcss-media-minmax) syntax, which may alternatively be used for media features with a 'range' type.\n\nExample:\n\n\n @media screen and (500px <= width <= 1200px) {}\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "PostCssMediaRange", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "PostCSS", - "index": 5, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.jetbrains.plugins.sass", - "version": "232.9876", - "rules": [ - { - "id": "SassScssUnresolvedMixin", - "shortDescription": { - "text": "Unresolved mixin" - }, - "fullDescription": { - "text": "Reports an unresolved Sass/SCSS mixin reference. Example: '* {\n @include unknown-mixin;\n}'", - "markdown": "Reports an unresolved [Sass/SCSS mixin](https://sass-lang.com/documentation/at-rules/mixin) reference.\n\n**Example:**\n\n\n * {\n @include unknown-mixin;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SassScssUnresolvedMixin", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Sass/SCSS", - "index": 6, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SassScssResolvedByNameOnly", - "shortDescription": { - "text": "Missing import" - }, - "fullDescription": { - "text": "Reports a reference to a variable, mixin, or function that is declared in another file but this file isn't explicitly imported in the current file. Example: '* {\n margin: $var-in-other-file;\n}'", - "markdown": "Reports a reference to a variable, mixin, or function that is declared in another file but this file isn't explicitly [imported](https://sass-lang.com/documentation/at-rules/import) in the current file.\n\n**Example:**\n\n\n * {\n margin: $var-in-other-file;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "SassScssResolvedByNameOnly", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Sass/SCSS", - "index": 6, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SassScssUnresolvedPlaceholderSelector", - "shortDescription": { - "text": "Unresolved placeholder selector" - }, - "fullDescription": { - "text": "Reports an unresolved Sass/SCSS placeholder selector reference. Example: '* {\n @extend %unknown-placeholder-selector;\n}'", - "markdown": "Reports an unresolved [Sass/SCSS placeholder selector](https://sass-lang.com/documentation/variables) reference.\n\n**Example:**\n\n\n * {\n @extend %unknown-placeholder-selector;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SassScssUnresolvedPlaceholderSelector", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Sass/SCSS", - "index": 6, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SassScssUnresolvedVariable", - "shortDescription": { - "text": "Unresolved variable" - }, - "fullDescription": { - "text": "Reports an unresolved Sass/SCSS variable reference. Example: '* {\n margin: $unknown-var;\n}'", - "markdown": "Reports an unresolved [Sass/SCSS variable](https://sass-lang.com/documentation/variables) reference.\n\n**Example:**\n\n\n * {\n margin: $unknown-var;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SassScssUnresolvedVariable", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Sass/SCSS", - "index": 6, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.jetbrains.sh", - "version": "232.9876", - "rules": [ - { - "id": "ShellCheck", - "shortDescription": { - "text": "ShellCheck" - }, - "fullDescription": { - "text": "Reports shell script bugs detected by the integrated ShellCheck static analysis tool.", - "markdown": "Reports shell script bugs detected by the integrated [ShellCheck](https://github.com/koalaman/shellcheck) static analysis tool." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "ShellCheck", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "Shell script", - "index": 7, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "Karma", - "version": "232.9876", - "rules": [ - { - "id": "KarmaConfigFile", - "shortDescription": { - "text": "Invalid Karma configuration file" - }, - "fullDescription": { - "text": "Reports a potential error in a file path ('basePath', 'files') for a Karma configuration file, for example, 'karma.conf.js'.", - "markdown": "Reports a potential error in a file path ('basePath', 'files') for a Karma configuration file, for example, `karma.conf.js`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "KarmaConfigFile", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/Unit testing", - "index": 8, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.intellij", - "version": "232.9876.134", - "rules": [ - { - "id": "JsonSchemaDeprecation", - "shortDescription": { - "text": "Deprecated JSON property" - }, - "fullDescription": { - "text": "Reports a deprecated property in a JSON file. Note that deprecation mechanism is not defined in the JSON Schema specification yet, and this inspection uses a non-standard extension 'deprecationMessage'.", - "markdown": "Reports a deprecated property in a JSON file. \nNote that deprecation mechanism is not defined in the JSON Schema specification yet, and this inspection uses a non-standard extension 'deprecationMessage'." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "JsonSchemaDeprecation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JsonSchemaRefReference", - "shortDescription": { - "text": "Unresolved '$ref' and '$schema' references" - }, - "fullDescription": { - "text": "Reports an unresolved '$ref' or '$schema' path in a JSON schema.", - "markdown": "Reports an unresolved `$ref` or `$schema` path in a JSON schema. " - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JsonSchemaRefReference", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlUnknownBooleanAttribute", - "shortDescription": { - "text": "Incorrect boolean attribute" - }, - "fullDescription": { - "text": "Reports an HTML non-boolean attribute without a value. Suggests configuring attributes that should not be reported.", - "markdown": "Reports an HTML non-boolean attribute without a value. Suggests configuring attributes that should not be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlUnknownBooleanAttribute", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DuplicatedCode", - "shortDescription": { - "text": "Duplicated code fragment" - }, - "fullDescription": { - "text": "Reports duplicated blocks of code from the selected scope: the same file or the entire project. The inspection features quick-fixes that help you to set the size of detected duplicates, navigate to repetitive code fragments, and compare them in a tool window. The inspection options allow you to select the scope of the reported duplicated fragments and set the initial size for the duplicated language constructs.", - "markdown": "Reports duplicated blocks of code from the selected scope: the same file or the entire project.\n\nThe inspection features quick-fixes that help you to set the size of detected duplicates, navigate to repetitive code fragments, and compare them in a tool window.\n\nThe inspection options allow you to select the scope of the reported duplicated fragments and set the initial size for the duplicated language constructs." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "DuplicatedCode", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "InconsistentLineSeparators", - "shortDescription": { - "text": "Inconsistent line separators" - }, - "fullDescription": { - "text": "Reports files with line separators different from the ones that are specified in the project's settings. For example, the inspection will be triggered if you set the line separator to '\\n' in Settings | Editor | Code Style | Line separator, while the file you are editing uses '\\r\\n' as a line separator. The inspection also warns you about mixed line separators within a file.", - "markdown": "Reports files with line separators different from the ones that are specified in the project's settings.\n\nFor example, the inspection will be triggered if you set the line separator to `\\n` in\n[Settings \\| Editor \\| Code Style \\| Line separator](settings://preferences.sourceCode?Line%20separator),\nwhile the file you are editing uses `\\r\\n` as a line separator.\n\nThe inspection also warns you about mixed line separators within a file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "InconsistentLineSeparators", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RedundantSuppression", - "shortDescription": { - "text": "Redundant suppression" - }, - "fullDescription": { - "text": "Reports usages of the following elements that can be safely removed because the inspection they affect is no longer applicable in this context: '@SuppressWarning' annotation, or '// noinspection' line comment, or '/** noinspection */' JavaDoc comment Example: 'public class C {\n // symbol is already private,\n // but annotation is still around\n @SuppressWarnings({\"WeakerAccess\"})\n private boolean CONST = true;\n void f() {\n CONST = false;\n }\n}'", - "markdown": "Reports usages of the following elements that can be safely removed because the inspection they affect is no longer applicable in this context:\n\n* `@SuppressWarning` annotation, or\n* `// noinspection` line comment, or\n* `/** noinspection */` JavaDoc comment\n\nExample:\n\n\n public class C {\n // symbol is already private,\n // but annotation is still around\n @SuppressWarnings({\"WeakerAccess\"})\n private boolean CONST = true;\n void f() {\n CONST = false;\n }\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "RedundantSuppression", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ProblematicWhitespace", - "shortDescription": { - "text": "Problematic whitespace" - }, - "fullDescription": { - "text": "Reports the following problems: Tabs used for indentation when the code style is configured to use only spaces. Spaces used for indentation when the code style is configured to use only tabs. Spaces used for indentation and tabs used for alignment when the code style is configured to use smart tabs.", - "markdown": "Reports the following problems:\n\n* Tabs used for indentation when the code style is configured to use only spaces.\n* Spaces used for indentation when the code style is configured to use only tabs.\n* Spaces used for indentation and tabs used for alignment when the code style is configured to use smart tabs." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ProblematicWhitespace", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlUnknownTarget", - "shortDescription": { - "text": "Unresolved file in a link" - }, - "fullDescription": { - "text": "Reports an unresolved file in a link.", - "markdown": "Reports an unresolved file in a link." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlUnknownTarget", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SSBasedInspection", - "shortDescription": { - "text": "Structural search inspection" - }, - "fullDescription": { - "text": "Allows configuring Structural Search/Structural Replace templates that you can apply to the file you are editing. All matches will be highlighted and marked with the template name that you have configured. If you configure the Structural Replace pattern as well, the corresponding replace option will be available as a quick-fix.", - "markdown": "Allows configuring **Structural Search/Structural Replace** templates that you can apply to the file you are editing.\n\nAll matches will be highlighted and marked with the template name that you have configured.\nIf you configure the **Structural Replace** pattern as well, the corresponding replace option will be available as a quick-fix." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SSBasedInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Structural search", - "index": 34, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LongLine", - "shortDescription": { - "text": "Line is longer than allowed by code style" - }, - "fullDescription": { - "text": "Reports lines that are longer than the Hard wrap at parameter specified in Settings | Editor | Code Style | General.", - "markdown": "Reports lines that are longer than the **Hard wrap at** parameter specified in [Settings \\| Editor \\| Code Style \\| General](settings://preferences.sourceCode?Hard%20wrap%20at)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LongLine", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlWrongRootElement", - "shortDescription": { - "text": "Wrong root element" - }, - "fullDescription": { - "text": "Reports a root tag name different from the name specified in the '' tag.", - "markdown": "Reports a root tag name different from the name specified in the `` tag." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "XmlWrongRootElement", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckValidXmlInScriptTagBody", - "shortDescription": { - "text": "Malformed content of 'script' tag" - }, - "fullDescription": { - "text": "Reports contents of 'script' tags that are invalid XML. Example: '' After the quick-fix is applied: ''", - "markdown": "Reports contents of `script` tags that are invalid XML. \n\n**Example:**\n\n\n \n\nAfter the quick-fix is applied:\n\n\n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CheckValidXmlInScriptTagBody", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpSuspiciousBackref", - "shortDescription": { - "text": "Suspicious back reference" - }, - "fullDescription": { - "text": "Reports back references that will not be resolvable at runtime. This means that the back reference can never match anything. A back reference will not be resolvable when the group is defined after the back reference, or if the group is defined in a different branch of an alternation. Example of a group defined after its back reference: '\\1(abc)' Example of a group and a back reference in different branches: 'a(b)c|(xy)\\1z' New in 2022.1", - "markdown": "Reports back references that will not be resolvable at runtime. This means that the back reference can never match anything. A back reference will not be resolvable when the group is defined after the back reference, or if the group is defined in a different branch of an alternation.\n\n**Example of a group defined after its back reference:**\n\n\n \\1(abc)\n\n**Example of a group and a back reference in different branches:**\n\n\n a(b)c|(xy)\\1z\n\nNew in 2022.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpSuspiciousBackref", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpSingleCharAlternation", - "shortDescription": { - "text": "Single character alternation" - }, - "fullDescription": { - "text": "Reports single char alternation in a RegExp. It is simpler to use a character class instead. This may also provide better matching performance. Example: 'a|b|c|d' After the quick-fix is applied: '[abcd]' New in 2017.1", - "markdown": "Reports single char alternation in a RegExp. It is simpler to use a character class instead. This may also provide better matching performance.\n\n**Example:**\n\n\n a|b|c|d\n\nAfter the quick-fix is applied:\n\n\n [abcd]\n\n\nNew in 2017.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpSingleCharAlternation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlUnknownAttribute", - "shortDescription": { - "text": "Unknown attribute" - }, - "fullDescription": { - "text": "Reports an unknown HTML attribute. Suggests configuring attributes that should not be reported.", - "markdown": "Reports an unknown HTML attribute. Suggests configuring attributes that should not be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlUnknownAttribute", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckTagEmptyBody", - "shortDescription": { - "text": "Empty element content" - }, - "fullDescription": { - "text": "Reports XML elements without contents. Example: '\n \n ' After the quick-fix is applied: '\n \n '", - "markdown": "Reports XML elements without contents.\n\n**Example:**\n\n\n \n \n \n\nAfter the quick-fix is applied:\n\n\n \n \n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CheckTagEmptyBody", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpRedundantEscape", - "shortDescription": { - "text": "Redundant character escape" - }, - "fullDescription": { - "text": "Reports redundant character escape sequences that can be replaced with unescaped characters preserving the meaning. Many escape sequences that are necessary outside of a character class are redundant inside square brackets '[]' of a character class. Although unescaped opening curly braces '{' outside of character classes are allowed in some dialects (JavaScript, Python, and so on), it can cause confusion and make the pattern less portable, because there are dialects that require escaping curly braces as characters. For this reason the inspection does not report escaped opening curly braces. Example: '\\-\\;[\\.]' After the quick-fix is applied: '-;[.]' The Ignore escaped closing brackets '}' and ']' option specifies whether to report '\\}' and '\\]' outside of a character class when they are allowed to be unescaped by the RegExp dialect. New in 2017.3", - "markdown": "Reports redundant character escape sequences that can be replaced with unescaped characters preserving the meaning. Many escape sequences that are necessary outside of a character class are redundant inside square brackets `[]` of a character class.\n\n\nAlthough unescaped opening curly braces `{` outside of character classes are allowed in some dialects (JavaScript, Python, and so on),\nit can cause confusion and make the pattern less portable, because there are dialects that require escaping curly braces as characters.\nFor this reason the inspection does not report escaped opening curly braces.\n\n**Example:**\n\n\n \\-\\;[\\.]\n\nAfter the quick-fix is applied:\n\n\n -;[.]\n\n\nThe **Ignore escaped closing brackets '}' and '\\]'** option specifies whether to report `\\}` and `\\]` outside of a character class\nwhen they are allowed to be unescaped by the RegExp dialect.\n\nNew in 2017.3" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpRedundantEscape", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnresolvedReference", - "shortDescription": { - "text": "Unresolved reference" - }, - "fullDescription": { - "text": "Reports an unresolved reference to a named pattern ('define') in RELAX-NG files that use XML syntax. Suggests creating the referenced 'define' element.", - "markdown": "Reports an unresolved reference to a named pattern (`define`) in RELAX-NG files that use XML syntax. Suggests creating the referenced `define` element." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "UnresolvedReference", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "RELAX NG", - "index": 48, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlMissingClosingTag", - "shortDescription": { - "text": "Missing closing tag" - }, - "fullDescription": { - "text": "Reports an HTML element without a closing tag. Some coding styles require that HTML elements have closing tags even where this is optional. Example: '\n \n

Behold!\n \n ' After the quick-fix is applied: '\n \n

Behold!

\n \n '", - "markdown": "Reports an HTML element without a closing tag. Some coding styles require that HTML elements have closing tags even where this is optional.\n\n**Example:**\n\n\n \n \n

Behold!\n \n \n\nAfter the quick-fix is applied:\n\n\n \n \n

Behold!

\n \n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "HtmlMissingClosingTag", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CustomRegExpInspection", - "shortDescription": { - "text": "Custom RegExp inspection" - }, - "fullDescription": { - "text": "Custom Regex Inspection", - "markdown": "Custom Regex Inspection" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "CustomRegExpInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "IncorrectFormatting", - "shortDescription": { - "text": "Incorrect formatting" - }, - "fullDescription": { - "text": "Reports formatting issues that appear if your code doesn't follow your project's code style settings. This inspection is not compatible with languages that require third-party formatters for code formatting, for example, Go or C with CLangFormat enabled.", - "markdown": "Reports formatting issues that appear if your code doesn't\nfollow your project's code style settings.\n\n\nThis inspection is not compatible with languages that require\nthird-party formatters for code formatting, for example, Go or\nC with CLangFormat enabled." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "IncorrectFormatting", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlExtraClosingTag", - "shortDescription": { - "text": "Redundant closing tag" - }, - "fullDescription": { - "text": "Reports redundant closing tags on empty elements, for example, 'img' or 'br'. Example: '\n \n

\n \n ' After the quick-fix is applied: '\n \n
\n \n '", - "markdown": "Reports redundant closing tags on empty elements, for example, `img` or `br`.\n\n**Example:**\n\n\n \n \n

\n \n \n\nAfter the quick-fix is applied:\n\n\n \n \n
\n \n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlExtraClosingTag", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlUnknownAnchorTarget", - "shortDescription": { - "text": "Unresolved fragment in a link" - }, - "fullDescription": { - "text": "Reports an unresolved last part of an URL after the '#' sign.", - "markdown": "Reports an unresolved last part of an URL after the `#` sign." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlUnknownAnchorTarget", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpUnexpectedAnchor", - "shortDescription": { - "text": "Begin or end anchor in unexpected position" - }, - "fullDescription": { - "text": "Reports '^' or '\\A' anchors not at the beginning of the pattern and '$', '\\Z' or '\\z' anchors not at the end of the pattern. In the wrong position these RegExp anchors prevent the pattern from matching anything. In case of the '^' and '$' anchors, most likely the literal character was meant and the escape forgotten. Example: '(Price $10)' New in 2018.1", - "markdown": "Reports `^` or `\\A` anchors not at the beginning of the pattern and `$`, `\\Z` or `\\z` anchors not at the end of the pattern. In the wrong position these RegExp anchors prevent the pattern from matching anything. In case of the `^` and `$` anchors, most likely the literal character was meant and the escape forgotten.\n\n**Example:**\n\n\n (Price $10)\n\n\nNew in 2018.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpUnexpectedAnchor", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SpellCheckingInspection", - "shortDescription": { - "text": "Typo" - }, - "fullDescription": { - "text": "Reports typos and misspellings in your code, comments, and literals and fixes them with one click.", - "markdown": "Reports typos and misspellings in your code, comments, and literals and fixes them with one click." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "SpellCheckingInspection", - "ideaSeverity": "TYPO", - "qodanaSeverity": "Low" - } - }, - "relationships": [ - { - "target": { - "id": "Proofreading", - "index": 56, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckXmlFileWithXercesValidator", - "shortDescription": { - "text": "Failed external validation" - }, - "fullDescription": { - "text": "Reports a discrepancy in an XML file with the specified DTD or schema detected by the Xerces validator.", - "markdown": "Reports a discrepancy in an XML file with the specified DTD or schema detected by the Xerces validator." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CheckXmlFileWithXercesValidator", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlUnknownTag", - "shortDescription": { - "text": "Unknown tag" - }, - "fullDescription": { - "text": "Reports an unknown HTML tag. Suggests configuring tags that should not be reported.", - "markdown": "Reports an unknown HTML tag. Suggests configuring tags that should not be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlUnknownTag", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpEscapedMetaCharacter", - "shortDescription": { - "text": "Escaped meta character" - }, - "fullDescription": { - "text": "Reports escaped meta characters. Some RegExp coding styles specify that meta characters should be placed inside a character class, to make the regular expression easier to understand. This inspection does not warn about the meta character '[', ']' and '^', because those would need additional escaping inside a character class. Example: '\\d+\\.\\d+' After the quick-fix is applied: '\\d+[.]\\d+' New in 2017.1", - "markdown": "Reports escaped meta characters. Some RegExp coding styles specify that meta characters should be placed inside a character class, to make the regular expression easier to understand. This inspection does not warn about the meta character `[`, `]` and `^`, because those would need additional escaping inside a character class.\n\n**Example:**\n\n\n \\d+\\.\\d+\n\nAfter the quick-fix is applied:\n\n\n \\d+[.]\\d+\n\nNew in 2017.1" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "RegExpEscapedMetaCharacter", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlHighlighting", - "shortDescription": { - "text": "XML highlighting" - }, - "fullDescription": { - "text": "Reports XML validation problems in the results of a batch code inspection.", - "markdown": "Reports XML validation problems in the results of a batch code inspection." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "XmlHighlighting", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlDuplicatedId", - "shortDescription": { - "text": "Duplicate 'id' attribute" - }, - "fullDescription": { - "text": "Reports a duplicate 'id' attribute in XML.", - "markdown": "Reports a duplicate `id` attribute in XML." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "XmlDuplicatedId", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpDuplicateCharacterInClass", - "shortDescription": { - "text": "Duplicate character in character class" - }, - "fullDescription": { - "text": "Reports duplicate characters inside a RegExp character class. Duplicate characters are unnecessary and can be removed without changing the semantics of the regex. Example: '[aabc]' After the quick-fix is applied: '[abc]'", - "markdown": "Reports duplicate characters inside a RegExp character class. Duplicate characters are unnecessary and can be removed without changing the semantics of the regex.\n\n**Example:**\n\n\n [aabc]\n\nAfter the quick-fix is applied:\n\n\n [abc]\n" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpDuplicateCharacterInClass", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlInvalidId", - "shortDescription": { - "text": "Unresolved 'id' reference" - }, - "fullDescription": { - "text": "Reports an unresolved 'id' reference in XML.", - "markdown": "Reports an unresolved `id` reference in XML." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "XmlInvalidId", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlUnboundNsPrefix", - "shortDescription": { - "text": "Unbound namespace prefix" - }, - "fullDescription": { - "text": "Reports an unbound namespace prefix in XML.", - "markdown": "Reports an unbound namespace prefix in XML." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "XmlUnboundNsPrefix", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RequiredAttributes", - "shortDescription": { - "text": "Missing required attribute" - }, - "fullDescription": { - "text": "Reports a missing mandatory attribute in an XML/HTML tag. Suggests configuring attributes that should not be reported.", - "markdown": "Reports a missing mandatory attribute in an XML/HTML tag. Suggests configuring attributes that should not be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "RequiredAttributes", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "ReassignedToPlainText", - "shortDescription": { - "text": "Reassigned to plain text" - }, - "fullDescription": { - "text": "Reports files that were explicitly re-assigned to Plain Text File Type. This association is unnecessary because the platform auto-detects text files by content automatically. You can dismiss this warning by removing the file type association in Settings | Editor | File Types | Text.", - "markdown": "Reports files that were explicitly re-assigned to Plain Text File Type. This association is unnecessary because the platform auto-detects text files by content automatically.\n\nYou can dismiss this warning by removing the file type association\nin **Settings \\| Editor \\| File Types \\| Text**." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "ReassignedToPlainText", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlUnusedNamespaceDeclaration", - "shortDescription": { - "text": "Unused schema declaration" - }, - "fullDescription": { - "text": "Reports an unused namespace declaration or location hint in XML.", - "markdown": "Reports an unused namespace declaration or location hint in XML." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "XmlUnusedNamespaceDeclaration", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpRedundantClassElement", - "shortDescription": { - "text": "Redundant '\\d', '[:digit:]', or '\\D' class elements" - }, - "fullDescription": { - "text": "Reports redundant '\\d' or '[:digit:]' that are used in one class with '\\w' or '[:word:]' ('\\D' with '\\W') and can be removed. Example: '[\\w\\d]' After the quick-fix is applied: '[\\w]' New in 2022.2", - "markdown": "Reports redundant `\\d` or `[:digit:]` that are used in one class with `\\w` or `[:word:]` (`\\D` with `\\W`) and can be removed.\n\n**Example:**\n\n\n [\\w\\d]\n\nAfter the quick-fix is applied:\n\n\n [\\w]\n\nNew in 2022.2" - }, - "defaultConfiguration": { - "enabled": true, - "level": "note", - "parameters": { - "suppressToolId": "RegExpRedundantClassElement", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpSimplifiable", - "shortDescription": { - "text": "Regular expression can be simplified" - }, - "fullDescription": { - "text": "Reports regular expressions that can be simplified. Example: '[a] xx* [ah-hz]' After the quick-fix is applied: 'a x+ [ahz]' New in 2022.1", - "markdown": "Reports regular expressions that can be simplified.\n\n**Example:**\n\n\n [a] xx* [ah-hz]\n\nAfter the quick-fix is applied:\n\n\n a x+ [ahz]\n\nNew in 2022.1" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "RegExpSimplifiable", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpEmptyAlternationBranch", - "shortDescription": { - "text": "Empty branch in alternation" - }, - "fullDescription": { - "text": "Reports empty branches in a RegExp alternation. An empty branch will only match the empty string, and in most cases that is not what is desired. This inspection will not report a single empty branch at the start or the end of an alternation. Example: '(alpha||bravo)' After the quick-fix is applied: '(alpha|bravo)' New in 2017.2", - "markdown": "Reports empty branches in a RegExp alternation. An empty branch will only match the empty string, and in most cases that is not what is desired. This inspection will not report a single empty branch at the start or the end of an alternation.\n\n**Example:**\n\n\n (alpha||bravo)\n\nAfter the quick-fix is applied:\n\n\n (alpha|bravo)\n\nNew in 2017.2" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpEmptyAlternationBranch", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Annotator", - "shortDescription": { - "text": "Annotator" - }, - "fullDescription": { - "text": "Reports issues essential to this file (e.g., syntax errors) in the result of a batch code inspection run. These issues are usually always highlighted in the editor and can't be configured, unlike inspections. These options control the scope of checks performed by this inspection: Option \"Report syntax errors\": report parser-related issues. Option \"Report issues from language-specific annotators\": report issues found by annotators configured for the relevant language. See Custom Language Support: Annotators for details. Option \"Report other highlighting problems\": report issues specific to the language of the current file (e.g., type mismatches or unreported exceptions). See Custom Language Support: Highlighting for details.", - "markdown": "Reports issues essential to this file (e.g., syntax errors) in the result of a batch code inspection run. These issues are usually always highlighted in the editor and can't be configured, unlike inspections. These options control the scope of checks performed by this inspection:\n\n* Option \"**Report syntax errors**\": report parser-related issues.\n* Option \"**Report issues from language-specific annotators** \": report issues found by annotators configured for the relevant language. See [Custom Language Support: Annotators](https://plugins.jetbrains.com/docs/intellij/annotator.html) for details.\n* Option \"**Report other highlighting problems** \": report issues specific to the language of the current file (e.g., type mismatches or unreported exceptions). See [Custom Language Support: Highlighting](https://plugins.jetbrains.com/docs/intellij/syntax-highlighting-and-error-highlighting.html#semantic-highlighting) for details." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "Annotator", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlPathReference", - "shortDescription": { - "text": "Unresolved file reference" - }, - "fullDescription": { - "text": "Reports an unresolved file reference in XML.", - "markdown": "Reports an unresolved file reference in XML." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "XmlPathReference", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpUnnecessaryNonCapturingGroup", - "shortDescription": { - "text": "Unnecessary non-capturing group" - }, - "fullDescription": { - "text": "Reports unnecessary non-capturing groups, which have no influence on the match result. Example: 'Everybody be cool, (?:this) is a robbery!' After the quick-fix is applied: 'Everybody be cool, this is a robbery!' New in 2021.1", - "markdown": "Reports unnecessary non-capturing groups, which have no influence on the match result.\n\n**Example:**\n\n\n Everybody be cool, (?:this) is a robbery!\n\nAfter the quick-fix is applied:\n\n\n Everybody be cool, this is a robbery!\n\nNew in 2021.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpUnnecessaryNonCapturingGroup", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TodoComment", - "shortDescription": { - "text": "TODO comment" - }, - "fullDescription": { - "text": "Reports TODO comments in your code. You can configure the format for TODO comments in Settings | Editor | TODO. Enable the Only warn on TODO comments without any details option to only warn on empty TODO comments, that don't provide any description on the task that should be done. Disable to report all TODO comments.", - "markdown": "Reports **TODO** comments in your code.\n\nYou can configure the format for **TODO** comments in [Settings \\| Editor \\| TODO](settings://preferences.toDoOptions).\n\nEnable the **Only warn on TODO comments without any details** option to only warn on empty TODO comments, that\ndon't provide any description on the task that should be done. Disable to report all TODO comments." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TodoComment", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "Json5StandardCompliance", - "shortDescription": { - "text": "Compliance with JSON5 standard" - }, - "fullDescription": { - "text": "Reports inconsistency with the language specification in a JSON5 file.", - "markdown": "Reports inconsistency with [the language specification](http://json5.org) in a JSON5 file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "Json5StandardCompliance", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JsonDuplicatePropertyKeys", - "shortDescription": { - "text": "Duplicate keys in object literals" - }, - "fullDescription": { - "text": "Reports a duplicate key in an object literal.", - "markdown": "Reports a duplicate key in an object literal." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JsonDuplicatePropertyKeys", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlDeprecatedElement", - "shortDescription": { - "text": "Deprecated symbol" - }, - "fullDescription": { - "text": "Reports a deprecated XML element or attribute. Symbols can be marked by XML comment or documentation tag with text 'deprecated'.", - "markdown": "Reports a deprecated XML element or attribute.\n\nSymbols can be marked by XML comment or documentation tag with text 'deprecated'." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "XmlDeprecatedElement", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpRedundantNestedCharacterClass", - "shortDescription": { - "text": "Redundant nested character class" - }, - "fullDescription": { - "text": "Reports unnecessary nested character classes. Example: '[a-c[x-z]]' After the quick-fix is applied: '[a-cx-z]' New in 2020.2", - "markdown": "Reports unnecessary nested character classes.\n\n**Example:**\n\n\n [a-c[x-z]]\n\nAfter the quick-fix is applied:\n\n\n [a-cx-z]\n\nNew in 2020.2" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpRedundantNestedCharacterClass", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlWrongAttributeValue", - "shortDescription": { - "text": "Wrong attribute value" - }, - "fullDescription": { - "text": "Reports an incorrect HTML attribute value.", - "markdown": "Reports an incorrect HTML attribute value." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlWrongAttributeValue", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "XmlDefaultAttributeValue", - "shortDescription": { - "text": "Redundant attribute with default value" - }, - "fullDescription": { - "text": "Reports a redundant assignment of the default value to an XML attribute.", - "markdown": "Reports a redundant assignment of the default value to an XML attribute." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "XmlDefaultAttributeValue", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpOctalEscape", - "shortDescription": { - "text": "Octal escape" - }, - "fullDescription": { - "text": "Reports octal escapes, which are easily confused with back references. Use hexadecimal escapes to avoid confusion. Example: '\\07' After the quick-fix is applied: '\\x07' New in 2017.1", - "markdown": "Reports octal escapes, which are easily confused with back references. Use hexadecimal escapes to avoid confusion.\n\n**Example:**\n\n\n \\07\n\nAfter the quick-fix is applied:\n\n\n \\x07\n\nNew in 2017.1" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "RegExpOctalEscape", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnusedDefine", - "shortDescription": { - "text": "Unused define" - }, - "fullDescription": { - "text": "Reports an unused named pattern ('define') in a RELAX-NG file (XML or Compact Syntax). 'define' elements that are used through an include in another file are ignored.", - "markdown": "Reports an unused named pattern (`define`) in a RELAX-NG file (XML or Compact Syntax). `define` elements that are used through an include in another file are ignored." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnusedDefine", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RELAX NG", - "index": 48, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JsonSchemaCompliance", - "shortDescription": { - "text": "Compliance with JSON schema" - }, - "fullDescription": { - "text": "Reports inconsistence between a JSON file and the JSON schema that is assigned to it.", - "markdown": "Reports inconsistence between a JSON file and the [JSON schema](https://json-schema.org) that is assigned to it. " - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JsonSchemaCompliance", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "EmptyDirectory", - "shortDescription": { - "text": "Empty directory" - }, - "fullDescription": { - "text": "Reports empty directories. Available only from Code | Inspect Code or Code | Analyze Code | Run Inspection by Name and isn't reported in the editor. Use the Only report empty directories located under a source folder option to have only directories under source roots reported.", - "markdown": "Reports empty directories.\n\nAvailable only from **Code \\| Inspect Code** or\n**Code \\| Analyze Code \\| Run Inspection by Name** and isn't reported in the editor.\n\nUse the **Only report empty directories located under a source folder** option to have only directories under source\nroots reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "EmptyDirectory", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpAnonymousGroup", - "shortDescription": { - "text": "Anonymous capturing group or numeric back reference" - }, - "fullDescription": { - "text": "Reports anonymous capturing groups and numeric back references in a RegExp. These are only reported when the RegExp dialect supports named group and named group references. Named groups and named back references improve code readability and are recommended to use instead. When a capture is not needed, matching can be more performant and use less memory by using a non-capturing group, i.e. '(?:xxx)' instead of '(xxx)'. Example: '(\\d\\d\\d\\d)\\1' A better regex pattern could look like this: '(?\\d\\d\\d\\d)\\k' New in 2017.2", - "markdown": "Reports anonymous capturing groups and numeric back references in a RegExp. These are only reported when the RegExp dialect supports named group and named group references. Named groups and named back references improve code readability and are recommended to use instead. When a capture is not needed, matching can be more performant and use less memory by using a non-capturing group, i.e. `(?:xxx)` instead of `(xxx)`.\n\n**Example:**\n\n\n (\\d\\d\\d\\d)\\1\n\nA better regex pattern could look like this:\n\n\n (?\\d\\d\\d\\d)\\k\n\nNew in 2017.2" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpAnonymousGroup", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckDtdRefs", - "shortDescription": { - "text": "Unresolved DTD reference" - }, - "fullDescription": { - "text": "Reports inconsistency in a DTD-specific reference, for example, in a reference to an XML entity or to a DTD element declaration. Works in DTD an XML files.", - "markdown": "Reports inconsistency in a DTD-specific reference, for example, in a reference to an XML entity or to a DTD element declaration. Works in DTD an XML files." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CheckDtdRefs", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "XML", - "index": 38, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "NonAsciiCharacters", - "shortDescription": { - "text": "Non-ASCII characters" - }, - "fullDescription": { - "text": "Reports code elements that use non-ASCII symbols in an unusual context. Example: Non-ASCII characters used in identifiers, strings, or comments. Identifiers written in different languages, such as 'myСollection' with the letter 'C' written in Cyrillic. Comments or strings containing Unicode symbols, such as long dashes and arrows.", - "markdown": "Reports code elements that use non-ASCII symbols in an unusual context.\n\nExample:\n\n* Non-ASCII characters used in identifiers, strings, or comments.\n* Identifiers written in different languages, such as `my`**С**`ollection` with the letter **C** written in Cyrillic.\n* Comments or strings containing Unicode symbols, such as long dashes and arrows." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "NonAsciiCharacters", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Internationalization", - "index": 64, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LossyEncoding", - "shortDescription": { - "text": "Lossy encoding" - }, - "fullDescription": { - "text": "Reports characters that cannot be displayed because of the current document encoding. Examples: If you type international characters in a document with the US-ASCII charset, some characters will be lost on save. If you load a UTF-8-encoded file using the ISO-8859-1 one-byte charset, some characters will be displayed incorrectly. You can fix this by changing the file encoding either by specifying the encoding directly in the file, e.g. by editing 'encoding=' attribute in the XML prolog of XML file, or by changing the corresponding options in Settings | Editor | File Encodings.", - "markdown": "Reports characters that cannot be displayed because of the current document encoding.\n\nExamples:\n\n* If you type international characters in a document with the **US-ASCII** charset, some characters will be lost on save.\n* If you load a **UTF-8** -encoded file using the **ISO-8859-1** one-byte charset, some characters will be displayed incorrectly.\n\nYou can fix this by changing the file encoding\neither by specifying the encoding directly in the file, e.g. by editing `encoding=` attribute in the XML prolog of XML file,\nor by changing the corresponding options in **Settings \\| Editor \\| File Encodings**." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LossyEncoding", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Internationalization", - "index": 64, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpDuplicateAlternationBranch", - "shortDescription": { - "text": "Duplicate branch in alternation" - }, - "fullDescription": { - "text": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression. Example: '(alpha|bravo|charlie|alpha)' After the quick-fix is applied: '(alpha|bravo|charlie)' New in 2017.1", - "markdown": "Reports duplicate branches in a RegExp alternation. Duplicate branches slow down matching and obscure the intent of the expression.\n\n**Example:**\n\n\n (alpha|bravo|charlie|alpha)\n\nAfter the quick-fix is applied:\n\n\n (alpha|bravo|charlie)\n\nNew in 2017.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpDuplicateAlternationBranch", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "RegExpRepeatedSpace", - "shortDescription": { - "text": "Consecutive spaces" - }, - "fullDescription": { - "text": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier. Example: '( )' After the quick-fix is applied: '( {5})' New in 2017.1", - "markdown": "Reports multiple consecutive spaces in a RegExp. Because spaces are not visible by default, it can be hard to see how many spaces are required. The RegExp can be made more clear by replacing the consecutive spaces with a single space and a counted quantifier.\n\n**Example:**\n\n\n ( )\n\nAfter the quick-fix is applied:\n\n\n ( {5})\n\n\nNew in 2017.1" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "RegExpRepeatedSpace", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "RegExp", - "index": 43, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "IgnoreFileDuplicateEntry", - "shortDescription": { - "text": "Ignore file duplicates" - }, - "fullDescription": { - "text": "Reports duplicate entries (patterns) in the ignore file (e.g. .gitignore, .hgignore). Duplicate entries in these files are redundant and can be removed. Example: '# Output directories\n /out/\n /target/\n /out/'", - "markdown": "Reports duplicate entries (patterns) in the ignore file (e.g. .gitignore, .hgignore). Duplicate entries in these files are redundant and can be removed.\n\nExample:\n\n\n # Output directories\n /out/\n /target/\n /out/\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "IgnoreFileDuplicateEntry", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Version control", - "index": 65, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "JsonStandardCompliance", - "shortDescription": { - "text": "Compliance with JSON standard" - }, - "fullDescription": { - "text": "Reports the following discrepancies of a JSON file with the language specification: A line or block comment (configurable). Multiple top-level values (expect for JSON Lines files, configurable for others). A trailing comma in an object or array (configurable). A single quoted string. A property key is a not a double quoted strings. A NaN or Infinity/-Infinity numeric value as a floating point literal (configurable).", - "markdown": "Reports the following discrepancies of a JSON file with [the language specification](https://tools.ietf.org/html/rfc7159):\n\n* A line or block comment (configurable).\n* Multiple top-level values (expect for JSON Lines files, configurable for others).\n* A trailing comma in an object or array (configurable).\n* A single quoted string.\n* A property key is a not a double quoted strings.\n* A NaN or Infinity/-Infinity numeric value as a floating point literal (configurable)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "JsonStandardCompliance", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "JSON and JSON5", - "index": 9, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckEmptyScriptTag", - "shortDescription": { - "text": "Empty tag" - }, - "fullDescription": { - "text": "Reports empty tags that do not work in some browsers. Example: '\n \n '", - "markdown": "Reports empty tags that do not work in some browsers.\n\n**Example:**\n\n\n \n \n \n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CheckEmptyScriptTag", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.intellij.database", - "version": "232.9876", - "rules": [ - { - "id": "MongoJSSideEffectsInspection", - "shortDescription": { - "text": "Statement with side effects" - }, - "fullDescription": { - "text": "Reports statements that can cause side effects while the data source is in read-only mode. For more information about enabling read-only mode, see Enable read-only mode for a connection in the IDE documentation. The Disable read-only mode quick-fix turns off the read-only mode for the respective data source. Example: 'db.my_collection.insertOne()'", - "markdown": "Reports statements that can cause side effects while the data source is in read-only mode.\n\nFor more information about enabling read-only mode, see\n[Enable\nread-only mode for a connection in the IDE documentation](https://www.jetbrains.com/help/datagrip/configuring-database-connections.html#enable-read-only-mode-for-a-connection).\n\nThe **Disable read-only mode** quick-fix turns off the read-only mode for the respective data source.\n\nExample:\n\n\n db.my_collection.insertOne()\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSSideEffects", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MysqlLoadDataPathInspection", - "shortDescription": { - "text": "LOAD statement path" - }, - "fullDescription": { - "text": "Reports paths that start with the tilde character in LOAD statements. Example (MySQL): 'CREATE TABLE table_name (id int);\nLOAD DATA LOCAL INFILE '~/Documents/some_file.txt'\nINTO TABLE table_name FIELDS TERMINATED BY ',' LINES TERMINATED BY '\\n'\nIGNORE 1 LINES;' Instead of the tilde character, use a full path to the file.", - "markdown": "Reports paths that start with the tilde character in LOAD statements.\n\nExample (MySQL):\n\n CREATE TABLE table_name (id int);\n LOAD DATA LOCAL INFILE '~/Documents/some_file.txt'\n INTO TABLE table_name FIELDS TERMINATED BY ',' LINES TERMINATED BY '\\n'\n IGNORE 1 LINES;\n\nInstead of the tilde character, use a full path to the file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MysqlLoadDataPath", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MySQL", - "index": 13, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MongoJSExtSideEffectsInspection", - "shortDescription": { - "text": "Statement with side effects" - }, - "fullDescription": { - "text": "Reports statements that may cause side effects while the data source is in read-only mode. The quick-fix turns off the read-only mode for the respective data source. Example: 'db.my_collection.insertOne()'", - "markdown": "Reports statements that may cause side effects while the data source is in read-only mode.\n\nThe quick-fix turns off the read-only mode for the respective data source.\n\nExample:\n\n\n db.my_collection.insertOne()\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSSideEffects", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MysqlSpaceAfterFunctionNameInspection", - "shortDescription": { - "text": "Whitespace between the function name and the open parenthesis" - }, - "fullDescription": { - "text": "Reports any whitespace in a function call between the function name and the open parenthesis, which is not supported by default. Example (MySQL): 'SELECT MAX (qty) FROM orders;'", - "markdown": "Reports any whitespace in a function call between the function name and the open parenthesis, which is not supported by default.\n\nExample (MySQL):\n\n SELECT MAX (qty) FROM orders;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "MysqlSpaceAfterFunctionName", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "MySQL", - "index": 13, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlMissingReturnInspection", - "shortDescription": { - "text": "Missing return statement" - }, - "fullDescription": { - "text": "Reports functions that have no RETURN statements. Example (Oracle): 'CREATE FUNCTION foo RETURN int AS\nBEGIN\nEND;' The 'foo' function must return the integer value but the function body returns nothing. To fix the error, add a RETURN statement (for example, 'return 1;'). 'CREATE FUNCTION foo RETURN int AS\nBEGIN\n RETURN 1;\nEND;'", - "markdown": "Reports functions that have no RETURN statements.\n\nExample (Oracle):\n\n CREATE FUNCTION foo RETURN int AS\n BEGIN\n END;\n\nThe `foo` function must return the integer value but the function body returns nothing. To fix the error,\nadd a RETURN statement (for example, `return 1;`).\n\n CREATE FUNCTION foo RETURN int AS\n BEGIN\n RETURN 1;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "SqlMissingReturn", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlUnusedSubqueryItemInspection", - "shortDescription": { - "text": "Unused subquery item" - }, - "fullDescription": { - "text": "Reports columns, aliases, and other subquery items that are not referenced in the outer query expression. Example (PostgreSQL): 'CREATE TABLE for_subquery(id INT);\nSELECT a, q FROM (SELECT 1 AS a, 10 AS b, 2 + 3 AS q, id\n FROM for_subquery) x;' We reference 'a' and 'q' aliases from a subquery. But the 'b' alias and the 'id' column are not referenced in the outer SELECT statement. Therefore, 'b' and 'id' are grayed out.", - "markdown": "Reports columns, aliases, and other subquery items that are not referenced in the outer query expression.\n\nExample (PostgreSQL):\n\n CREATE TABLE for_subquery(id INT);\n SELECT a, q FROM (SELECT 1 AS a, 10 AS b, 2 + 3 AS q, id\n FROM for_subquery) x;\n\nWe reference `a` and `q` aliases from a subquery. But the `b` alias and the `id` column are\nnot referenced in the outer SELECT statement. Therefore, `b` and `id` are grayed out." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlUnused", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlCaseVsIfInspection", - "shortDescription": { - "text": "Using CASE instead of conditional function and vice versa" - }, - "fullDescription": { - "text": "Reports situations when CASE and IF are interchangeable. Example (MySQL): 'SELECT CASE\nWHEN C1 IS NULL THEN 1\nELSE 0\nEND\nFROM dual;' To keep your code short, you can replace the CASE structure with IF. You can do that by applying the Replace with 'IF' call intention action. The example code will look as follows: 'SELECT IF(C1 IS NULL, 1, 0)\nFROM dual;' To revert IF to CASE, click IF and apply the Replace with CASE expression intention action.", - "markdown": "Reports situations when CASE and IF are interchangeable.\n\nExample (MySQL):\n\n SELECT CASE\n WHEN C1 IS NULL THEN 1\n ELSE 0\n END\n FROM dual;\n\nTo keep your code short, you can replace the CASE structure with IF. You can do that by applying the **Replace with 'IF' call**\nintention action. The example code will look as follows:\n\n SELECT IF(C1 IS NULL, 1, 0)\n FROM dual;\n\nTo revert IF to CASE, click IF and apply the **Replace with CASE expression** intention action." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlCaseVsIf", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlShouldBeInGroupByInspection", - "shortDescription": { - "text": "Column should be in group by clause" - }, - "fullDescription": { - "text": "Reports columns that are not in the GROUP BY clause or inside an aggregate function call. Example (Microsoft SQL Server): 'CREATE TABLE t1 (a INT, b INT);\nSELECT a, b FROM t1 GROUP BY a;' If you run the SELECT query, you will receive an error because Microsoft SQL Server expects the 'b' column in GROUP BY or used inside an aggregate function. The following two examples will fix the error. 'SELECT a, b FROM t1 GROUP BY a, b;\nSELECT a, max(b) max_b FROM t1 GROUP BY a;'", - "markdown": "Reports columns that are not in the GROUP BY clause or inside an aggregate function call.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE t1 (a INT, b INT);\n SELECT a, b FROM t1 GROUP BY a;\n\nIf you run the SELECT query, you will receive an error because Microsoft SQL Server expects the `b` column in GROUP BY or used\ninside an aggregate function. The following two examples will fix the error.\n\n SELECT a, b FROM t1 GROUP BY a, b;\n SELECT a, max(b) max_b FROM t1 GROUP BY a;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlShouldBeInGroupBy", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlAutoIncrementDuplicateInspection", - "shortDescription": { - "text": "Auto-increment duplicate" - }, - "fullDescription": { - "text": "Reports tables that contain two columns with an automatic increment. In MySQL, Microsoft SQL Server, and Db2 dialects, a table can have only one field with a auto-increment option, and this field must be a key. Example (MySQL): 'CREATE TABLE my_table\n(\n id INT AUTO_INCREMENT,\n c2 INT AUTO_INCREMENT,\n);' The AUTO_INCREMENT constraint for 'c2' will be highlighted as 'c1' already has this constraint. To fix the warning, you can make 'id' a primary key and delete AUTO_INCREMENT for 'c2'. 'CREATE TABLE my_table\n(\n id INT AUTO_INCREMENT PRIMARY KEY,\n c2 INT,\n);'", - "markdown": "Reports tables that contain two columns with an automatic increment. In MySQL, Microsoft SQL Server, and Db2 dialects, a table can have only one field with a auto-increment option, and this field must be a key.\n\nExample (MySQL):\n\n CREATE TABLE my_table\n (\n id INT AUTO_INCREMENT,\n c2 INT AUTO_INCREMENT,\n );\n\nThe AUTO_INCREMENT constraint for `c2` will be highlighted as `c1` already has this constraint. To fix the warning,\nyou can make `id` a primary key and delete AUTO_INCREMENT for `c2`.\n\n CREATE TABLE my_table\n (\n id INT AUTO_INCREMENT PRIMARY KEY,\n c2 INT,\n );\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlAutoIncrementDuplicate", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlStringLengthExceededInspection", - "shortDescription": { - "text": "Implicit string truncation" - }, - "fullDescription": { - "text": "Reports variables that exceed the defined length in characters. Example (Microsoft SQL Server): 'CREATE PROCEDURE test() AS\nBEGIN\nDECLARE myVarOk VARCHAR(5) = 'abcde';\nDECLARE myVarExceeded VARCHAR(5) = 'abcde12345';\n\nSET myVarOk = 'xyz';\nSET myVarExceeded = '123456789';\nEND;' The 'myVarExceeded' variable is defined as 'VARCHAR(5)' but both assigned values (''abcde12345'' and ''123456789'') exceed this limitation. You can truncate assigned values or increase the defined length. To increase the length, use the Increase type length quick-fix. After the quick-fix is applied: 'CREATE PROCEDURE test() AS\nBEGIN\nDECLARE myVarOk VARCHAR(5) = 'abcde';\nDECLARE myVarExceeded VARCHAR(10) = 'abcde12345';\n\nSET myVarOk = 'xyz';\nSET myVarExceeded = '123456789';\nEND;'", - "markdown": "Reports variables that exceed the defined length in characters.\n\nExample (Microsoft SQL Server):\n\n CREATE PROCEDURE test() AS\n BEGIN\n DECLARE myVarOk VARCHAR(5) = 'abcde';\n DECLARE myVarExceeded VARCHAR(5) = 'abcde12345';\n\n SET myVarOk = 'xyz';\n SET myVarExceeded = '123456789';\n END;\n\nThe `myVarExceeded` variable is defined as `VARCHAR(5)` but both assigned values (`'abcde12345'` and\n`'123456789'`) exceed this limitation. You can truncate assigned values or increase the defined length.\nTo increase the length, use the **Increase type length** quick-fix.\n\nAfter the quick-fix is applied:\n\n CREATE PROCEDURE test() AS\n BEGIN\n DECLARE myVarOk VARCHAR(5) = 'abcde';\n DECLARE myVarExceeded VARCHAR(10) = 'abcde12345';\n\n SET myVarOk = 'xyz';\n SET myVarExceeded = '123456789';\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlStringLengthExceeded", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlSideEffectsInspection", - "shortDescription": { - "text": "Statement with side effects" - }, - "fullDescription": { - "text": "Reports statements that might lead to modification of a database during a read-only connection. To enable read-only mode for a connection, right-click a data source in the Database tool window (View | Tool Windows | Database) and select Properties. In the Data Sources and Drivers dialog, click the Options tab and select the Read-only checkbox. Example (MySQL): 'CREATE TABLE foo(a INT);\nINSERT INTO foo VALUES (1);' As 'CREATE TABLE' and 'INSERT INTO' statements lead to a database modification, these statements will be highlighted in read-only connection mode.", - "markdown": "Reports statements that might lead to modification of a database during a read-only connection.\n\nTo enable read-only mode for a\nconnection,\nright-click a data source in the **Database** tool window (**View \\| Tool Windows \\| Database** ) and select **Properties** .\nIn the **Data Sources and Drivers** dialog, click the **Options** tab and select the **Read-only** checkbox.\n\nExample (MySQL):\n\n CREATE TABLE foo(a INT);\n INSERT INTO foo VALUES (1);\n\nAs `CREATE TABLE` and `INSERT INTO` statements lead to a database modification, these statements will be highlighted\nin read-only connection mode." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlSideEffects", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDtInspection", - "shortDescription": { - "text": "Ill-formed date/time literals" - }, - "fullDescription": { - "text": "Reports errors in date and time literals. This inspection is available in MySQL, Oracle, Db2, and H2. Example (MySQL): 'SELECT TIME '10 -12:13:14' FROM dual;\nSELECT TIME ' 12 : 13 : 14 ' FROM dual;\nSELECT TIME '12 13 14' FROM dual;\nSELECT TIME '12-13-14' FROM dual;\nSELECT TIME '12.13.14' FROM dual;\nSELECT TIME '12:13:' FROM dual;\nSELECT TIME '12:13' FROM dual;\nSELECT TIME '12:' FROM dual;' In this example, dates ignore the MySQL standard for date and time literals. Therefore, they will be highlighted. For more information about date and time literals in MySQL, see Date and Time Literals at dev.mysql.com. The following date and type literals are valid for MySQL. 'SELECT TIME '12:13:14' FROM dual;\nSELECT TIME '12:13:14.555' FROM dual;\nSELECT TIME '12:13:14.' FROM dual;\nSELECT TIME '-12:13:14' FROM dual;\nSELECT TIME '10 12:13:14' FROM dual;\nSELECT TIME '-10 12:13:14' FROM dual;'", - "markdown": "Reports errors in date and time literals. This inspection is available in MySQL, Oracle, Db2, and H2.\n\nExample (MySQL):\n\n SELECT TIME '10 -12:13:14' FROM dual;\n SELECT TIME ' 12 : 13 : 14 ' FROM dual;\n SELECT TIME '12 13 14' FROM dual;\n SELECT TIME '12-13-14' FROM dual;\n SELECT TIME '12.13.14' FROM dual;\n SELECT TIME '12:13:' FROM dual;\n SELECT TIME '12:13' FROM dual;\n SELECT TIME '12:' FROM dual;\n\nIn this example, dates ignore the MySQL standard for date and time literals. Therefore, they will be highlighted.\nFor more information about date and time literals in MySQL, see [Date and Time Literals at dev.mysql.com](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-literals.html).\n\nThe following date and type literals are valid for MySQL.\n\n SELECT TIME '12:13:14' FROM dual;\n SELECT TIME '12:13:14.555' FROM dual;\n SELECT TIME '12:13:14.' FROM dual;\n SELECT TIME '-12:13:14' FROM dual;\n SELECT TIME '10 12:13:14' FROM dual;\n SELECT TIME '-10 12:13:14' FROM dual;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDateTime", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlIllegalCursorStateInspection", - "shortDescription": { - "text": "Illegal cursor state" - }, - "fullDescription": { - "text": "Reports illegal cursor states inside SQL routines. A routine has CLOSE or FETCH statements but a cursor might be closed. A routine has the OPEN statement but a cursor might be opened. Example (Microsoft SQL Server): 'CREATE TABLE t(col INT);\n\nCREATE PROCEDURE foo() AS\nBEGIN\nDECLARE my_cursor CURSOR FOR SELECT * FROM t;\nDECLARE a INT;\nFETCH my_cursor INTO a;\nCLOSE my_cursor;\nEND;' According to CLOSE (Transact-SQL) at docs.microsoft.com, CLOSE must be issued on an open cursor, and CLOSE is not allowed on cursors that have only been declared or are already closed. So, we need to open the cursor to fix the warning. 'CREATE PROCEDURE foo() AS\nBEGIN\nDECLARE my_cursor CURSOR FOR SELECT * FROM t;\nDECLARE a INT;\nOPEN my_cursor;\nFETCH my_cursor INTO a;\nCLOSE my_cursor;\nEND;'", - "markdown": "Reports illegal cursor states inside SQL routines.\n\n* A routine has CLOSE or FETCH statements but a cursor might be closed.\n* A routine has the OPEN statement but a cursor might be opened.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE t(col INT);\n\n CREATE PROCEDURE foo() AS\n BEGIN\n DECLARE my_cursor CURSOR FOR SELECT * FROM t;\n DECLARE a INT;\n FETCH my_cursor INTO a;\n CLOSE my_cursor;\n END;\n\nAccording to [CLOSE (Transact-SQL) at\ndocs.microsoft.com](https://docs.microsoft.com/en-us/sql/t-sql/language-elements/close-transact-sql), CLOSE must be issued on an open cursor, and CLOSE is not allowed on cursors that have only been declared or are\nalready closed. So, we need to open the cursor to fix the warning.\n\n CREATE PROCEDURE foo() AS\n BEGIN\n DECLARE my_cursor CURSOR FOR SELECT * FROM t;\n DECLARE a INT;\n OPEN my_cursor;\n FETCH my_cursor INTO a;\n CLOSE my_cursor;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlIllegalCursorState", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlJoinWithoutOnInspection", - "shortDescription": { - "text": "Unsafe 'join' clause in 'delete' statement" - }, - "fullDescription": { - "text": "Reports missing conditional checks for statements that might modify the whole database. For example, usages of JOIN clauses inside DELETE statements without ON or WHERE. Without conditional checks on JOIN, DELETE drops contents of the entire table. Example (MySQL): 'CREATE TABLE foo (a INT,b INT,c INT);\nCREATE TABLE bar (a INT,b INT,c INT);\n\nDELETE table1 FROM foo table1 INNER JOIN bar table2;'", - "markdown": "Reports missing conditional checks for statements that might modify the whole database.\n\nFor example, usages of JOIN clauses inside DELETE statements without ON or WHERE. Without conditional checks on JOIN, DELETE drops\ncontents of the entire table.\n\nExample (MySQL):\n\n CREATE TABLE foo (a INT,b INT,c INT);\n CREATE TABLE bar (a INT,b INT,c INT);\n\n DELETE table1 FROM foo table1 INNER JOIN bar table2;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlJoinWithoutOn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDropIndexedColumnInspection", - "shortDescription": { - "text": "Index is dependent on column" - }, - "fullDescription": { - "text": "Reports cases when you try to drop columns from indexed tables. This inspection is available in Microsoft SQL Server and Sybase ASE. Example (Microsoft SQL Server): 'CREATE TABLE test_index\n(\ncol INT NOT NULL,\ncol2 INT NOT NULL,\ncol3 INT NOT NULL UNIQUE,\ncol4 VARCHAR(200)\n);\n\nCREATE UNIQUE INDEX aaaa ON test_index (col, col2);\n\nALTER TABLE test_index\nDROP COLUMN col;' You cannot delete the 'col' column because it is in the indexed table. To delete the column, you need to delete the 'aaaa' index first (for example, DROP INDEX aaaa).", - "markdown": "Reports cases when you try to drop columns from indexed tables. This inspection is available in Microsoft SQL Server and Sybase ASE.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE test_index\n (\n col INT NOT NULL,\n col2 INT NOT NULL,\n col3 INT NOT NULL UNIQUE,\n col4 VARCHAR(200)\n );\n\n CREATE UNIQUE INDEX aaaa ON test_index (col, col2);\n\n ALTER TABLE test_index\n DROP COLUMN col;\n\nYou cannot delete the `col` column because it is in the indexed table. To delete the column, you need to delete the\n`aaaa` index first (for example, DROP INDEX aaaa)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDropIndexedColumn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlCheckUsingColumnsInspection", - "shortDescription": { - "text": "Check using clause columns" - }, - "fullDescription": { - "text": "Reports columns in the USING clause that does not exist in both tables. Example (MySQL): 'CREATE TABLE t1 (i INT, j INT);\nCREATE TABLE t2 (k INT, l INT);\nSELECT * FROM t1 JOIN t2 USING (j);' In USING clauses, a column name must be present in both tables, and the SELECT query will automatically join those tables by using the given column name. As we do not have the 'j' column in 't2', we can rewrite the query using ON. The ON clause can join tables where the column names do not match in both tables. 'SELECT * FROM t1 JOIN t2 ON t1.j = t2.l;'", - "markdown": "Reports columns in the USING clause that does not exist in both tables.\n\nExample (MySQL):\n\n CREATE TABLE t1 (i INT, j INT);\n CREATE TABLE t2 (k INT, l INT);\n SELECT * FROM t1 JOIN t2 USING (j);\n\nIn USING clauses, a column name must be present in both tables, and the SELECT query will automatically join\nthose tables by using the given column name. As we do not have the `j` column in `t2`, we can\nrewrite the query using ON. The ON clause can join tables where the column names do not match in both tables.\n\n SELECT * FROM t1 JOIN t2 ON t1.j = t2.l;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlCheckUsingColumns", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlInsertValuesInspection", - "shortDescription": { - "text": "VALUES clause cardinality" - }, - "fullDescription": { - "text": "Reports situations when a number of parameters in VALUES does not match a number of columns in a target table. Example (MySQL): 'CREATE TABLE foo(a INT, b INT, c INT);\n\nINSERT INTO foo VALUES (1,2,3,4)' The 'foo' table has three columns but in the INSERT INTO statement we pass four.", - "markdown": "Reports situations when a number of parameters in VALUES does not match a number of columns in a target table.\n\nExample (MySQL):\n\n CREATE TABLE foo(a INT, b INT, c INT);\n\n INSERT INTO foo VALUES (1,2,3,4)\n\nThe `foo` table has three columns but in the INSERT INTO statement we pass four." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlInsertValues", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlConstantConditionInspection", - "shortDescription": { - "text": "Constant condition" - }, - "fullDescription": { - "text": "Reports conditions in WHERE or JOIN clauses that are always TRUE or always FALSE. Example (MySQL): 'CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\nSELECT a FROM t1 WHERE 'Cat' = 'Cat';' The ''Cat' = 'Cat'' is always true and will be reported.", - "markdown": "Reports conditions in WHERE or JOIN clauses that are always TRUE or always FALSE.\n\nExample (MySQL):\n\n CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\n SELECT a FROM t1 WHERE 'Cat' = 'Cat';\n\nThe `'Cat' = 'Cat'` is always true and will be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlConstantCondition", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDialectInspection", - "shortDescription": { - "text": "SQL dialect detection" - }, - "fullDescription": { - "text": "Reports situations when a dialect is not assigned to an SQL file. For example, when you open a new SQL file without assigning a dialect to it, you see a notification where the best matching dialect is advised. Click the Use link to use the advised dialect. Alternatively, click the Change dialect to link to select the other dialect.", - "markdown": "Reports situations when a dialect is not assigned to an SQL file.\n\nFor example, when you open a new SQL file without assigning a dialect\nto it, you see a notification where the best matching dialect is advised. Click the **Use \\** link to use the advised\ndialect. Alternatively, click the **Change dialect to** link to select the other dialect." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDialectInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlRedundantElseNullInspection", - "shortDescription": { - "text": "Redundant ELSE NULL clause" - }, - "fullDescription": { - "text": "Reports redundant ELSE NULL clauses. Example (MySQL): 'SELECT CASE WHEN 2 > 1 THEN 'OK' ELSE NULL END AS alias FROM foo;' The 'ELSE NULL' part will never be executed and may be omitted.", - "markdown": "Reports redundant ELSE NULL clauses.\n\nExample (MySQL):\n\n SELECT CASE WHEN 2 > 1 THEN 'OK' ELSE NULL END AS alias FROM foo;\n\nThe `ELSE NULL` part will never be executed and may be omitted." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlRedundantElseNull", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlCallNotationInspection", - "shortDescription": { - "text": "Using of named and positional arguments" - }, - "fullDescription": { - "text": "Reports calls in which positional arguments go after the named ones. Works in PostgreSQL, Oracle, and Db2. Example (In PostgreSQL): 'CREATE FUNCTION foo(a int, b int, c int) RETURNS int\n LANGUAGE plpgsql AS\n$$\nBEGIN\n RETURN a + b + c;\nEND\n$$;\nSELECT foo(a => 1, b => 2, c => 3);\n -- `3` goes after the named argument\nSELECT foo(1, b => 2, 3);\n -- `1` and `3` go after the named argument\nSELECT foo(b => 2, 1, 3);'", - "markdown": "Reports calls in which positional arguments go after the named ones. Works in PostgreSQL, Oracle, and Db2.\n\nExample (In PostgreSQL):\n\n CREATE FUNCTION foo(a int, b int, c int) RETURNS int\n LANGUAGE plpgsql AS\n $$\n BEGIN\n RETURN a + b + c;\n END\n $$;\n SELECT foo(a => 1, b => 2, c => 3);\n -- `3` goes after the named argument\n SELECT foo(1, b => 2, 3);\n -- `1` and `3` go after the named argument\n SELECT foo(b => 2, 1, 3);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "SqlCallNotation", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MysqlParsingInspection", - "shortDescription": { - "text": "Unsupported syntax in pre-8.0 versions" - }, - "fullDescription": { - "text": "Reports invalid usages of UNION in queries. The inspection works in MySQL versions that are earlier than 8.0. Example (MySQL): 'SELECT * FROM (SELECT 1 UNION (SELECT 1 UNION SELECT 2)) a;'", - "markdown": "Reports invalid usages of UNION in queries.\n\nThe inspection works in MySQL versions that are earlier than 8.0.\n\nExample (MySQL):\n\n\n SELECT * FROM (SELECT 1 UNION (SELECT 1 UNION SELECT 2)) a;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MysqlParsing", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MySQL", - "index": 13, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MongoJSExtDeprecationInspection", - "shortDescription": { - "text": "Deprecated element" - }, - "fullDescription": { - "text": "Reports usages of deprecated methods in MongoDB and JavaScript code. The quick-fix replaces deprecated methods with recommended alternatives. Example: 'db.my_collection.insert()' After the quick-fix is applied: 'db.my_collection.insertOne()'", - "markdown": "Reports usages of deprecated methods in MongoDB and JavaScript code.\n\nThe quick-fix replaces deprecated methods with recommended alternatives.\n\nExample:\n\n\n db.my_collection.insert()\n\nAfter the quick-fix is applied:\n\n\n db.my_collection.insertOne()\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSDeprecation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDuplicateColumnInspection", - "shortDescription": { - "text": "Duplicating column name in SELECT" - }, - "fullDescription": { - "text": "Reports duplicated names of column aliases in SELECT lists. Example (Sybase ASE): 'CREATE TABLE t1 (a TEXT, b INT, c INT);\n\nSELECT a AS x, b AS x FROM t1;' The 'x' alias name is used for 'a' and 'b' columns. These assignments are highlighted as errors because you cannot use identical alias names for columns in Sybase ASE.", - "markdown": "Reports duplicated names of column aliases in SELECT lists.\n\nExample (Sybase ASE):\n\n CREATE TABLE t1 (a TEXT, b INT, c INT);\n\n SELECT a AS x, b AS x FROM t1;\n\nThe `x` alias name is used for `a` and `b` columns. These assignments are highlighted as errors because\nyou cannot use identical alias names for columns in Sybase ASE." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDuplicateColumn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlShadowingAliasInspection", - "shortDescription": { - "text": "Column is shadowed by alias" - }, - "fullDescription": { - "text": "Reports SELECT aliases with names that match column names in the FROM clause. Example (MySQL): 'CREATE TABLE foo (a INT, b INT, c INT);\nSELECT a b, c FROM foo;' The 'a' column uses the 'b' alias but the 'b' name is also used by the column from the 'foo' table.", - "markdown": "Reports SELECT aliases with names that match column names in the FROM clause.\n\nExample (MySQL):\n\n CREATE TABLE foo (a INT, b INT, c INT);\n SELECT a b, c FROM foo;\n\nThe `a` column uses the `b` alias but the `b` name is also used by the column from the `foo`\ntable." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlShadowingAlias", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MongoJSDeprecationInspection", - "shortDescription": { - "text": "Deprecated element" - }, - "fullDescription": { - "text": "Reports usages of deprecated methods in MongoDB and JavaScript code. The quick-fix replaces deprecated methods with recommended alternatives. Example: 'db.my_collection.insert()' After the quick-fix is applied: 'db.my_collection.insertOne()'", - "markdown": "Reports usages of deprecated methods in MongoDB and JavaScript code.\n\nThe quick-fix replaces deprecated methods with recommended alternatives.\n\nExample:\n\n db.my_collection.insert()\n\nAfter the quick-fix is applied:\n\n db.my_collection.insertOne()\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSDeprecation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlTypeInspection", - "shortDescription": { - "text": "Types compatibility" - }, - "fullDescription": { - "text": "Reports type-related errors.", - "markdown": "Reports type-related errors." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlType", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlUnreachableCodeInspection", - "shortDescription": { - "text": "Unreachable code" - }, - "fullDescription": { - "text": "Reports unreachable statements inside SQL routines. Example (Microsoft SQL Server): 'CREATE FUNCTION foo() RETURNS INT AS\nBEGIN\n THROW;\n RETURN 1;\nEND;' In Microsoft SQL Server, the 'THROW' statement raises an exception and transfers execution to the CATCH block of the TRY...CATCH construct. Therefore, the 'RETURN 1;' part will never be executed.", - "markdown": "Reports unreachable statements inside SQL routines.\n\nExample (Microsoft SQL Server):\n\n CREATE FUNCTION foo() RETURNS INT AS\n BEGIN\n THROW;\n RETURN 1;\n END;\n\nIn Microsoft SQL Server, the `THROW` statement raises an exception and transfers execution to the CATCH block of the TRY...CATCH\nconstruct. Therefore, the `RETURN 1;` part will never be executed." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlUnreachable", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlUnicodeStringLiteralInspection", - "shortDescription": { - "text": "Unicode usage in SQL" - }, - "fullDescription": { - "text": "Reports string literals that use national characters without the 'N' prefix. Without the N prefix, the string is converted to the default code page of the database. This default code page may not recognize certain characters. For more information, see nchar and nvarchar (Transact-SQL) at docs.microsoft.com. Example (Microsoft SQL Server): 'SELECT 'abcde' AS a;\nSELECT N'abcde' AS b;\nSELECT 'абвгд' AS c;\nSELECT N'абвгд' AS d;' The 'SELECT 'абвгд' AS c;' does not have the 'N' prefix, the ''абвгд'' part will be highlighted.", - "markdown": "Reports string literals that use national characters without the `N` prefix.\n\nWithout the N prefix, the string is converted to the default\ncode page of the database. This default code page may not recognize certain characters. For more information, see\n[nchar and nvarchar\n(Transact-SQL)\nat docs.microsoft.com](https://docs.microsoft.com/en-us/sql/t-sql/data-types/nchar-and-nvarchar-transact-sql).\n\nExample (Microsoft SQL Server):\n\n SELECT 'abcde' AS a;\n SELECT N'abcde' AS b;\n SELECT 'абвгд' AS c;\n SELECT N'абвгд' AS d;\n\nThe `SELECT 'абвгд' AS c;` does not have the `N` prefix, the `'абвгд'` part will be highlighted." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlUnicodeStringLiteral", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlNoDataSourceInspection", - "shortDescription": { - "text": "No data sources configured" - }, - "fullDescription": { - "text": "Reports the absence of data sources in the Database tool window (View | Tool Windows | Database).", - "markdown": "Reports the absence of data sources in the **Database** tool window (**View \\| Tool Windows \\| Database**)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlNoDataSourceInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlUnusedVariableInspection", - "shortDescription": { - "text": "Unused variable" - }, - "fullDescription": { - "text": "Reports unused arguments, variables, or parameters. Example (PostgreSQL): 'CREATE FUNCTION foo(PARAMUSED INT, PARAMUNUSED INT) RETURNS INT AS\n$$\nBEGIN\n RETURN PARAMUSED;\nEND\n$$ LANGUAGE plpgsql;' The 'PARAMUNUSED' parameter is not used in the function and might be deleted.", - "markdown": "Reports unused arguments, variables, or parameters.\n\nExample (PostgreSQL):\n\n CREATE FUNCTION foo(PARAMUSED INT, PARAMUNUSED INT) RETURNS INT AS\n $$\n BEGIN\n RETURN PARAMUSED;\n END\n $$ LANGUAGE plpgsql;\n\nThe `PARAMUNUSED` parameter is not used in the function and might be deleted." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlUnused", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlResolveInspection", - "shortDescription": { - "text": "Unresolved reference" - }, - "fullDescription": { - "text": "Reports unresolved SQL references. Example (MySQL): 'CREATE TABLE users(id INT, name VARCHAR(40));\nCREATE TABLE admins(id INT, col1 INT);\n\nSELECT users.id, admins.id FROM admins WHERE admins.id > 1;' The 'users.id' column is unresolved because the 'users' table is missing in the FROM clause.", - "markdown": "Reports unresolved SQL references.\n\nExample (MySQL):\n\n CREATE TABLE users(id INT, name VARCHAR(40));\n CREATE TABLE admins(id INT, col1 INT);\n\n SELECT users.id, admins.id FROM admins WHERE admins.id > 1;\n\nThe `users.id` column is unresolved because the `users` table is missing in the FROM clause." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "SqlResolve", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "PgSelectFromProcedureInspection", - "shortDescription": { - "text": "Postgres: Select from procedure call" - }, - "fullDescription": { - "text": "Reports situations when you make SELECT from a function or a DBLINK without an alias with a type (for example, 'AS t1(s VARCHAR)'). This requirement does not apply to scalar functions. Example (PostgreSQL): 'CREATE FUNCTION produce_a_table() RETURNS RECORD AS $$\nSELECT 1;\n$$ LANGUAGE sql;\nSELECT * FROM produce_a_table() AS s (c1 INT);\nSELECT * FROM produce_a_table() AS s (c1);\nSELECT * FROM DBLINK('dbname=mydb', 'SELECT proname, prosrc FROM pg_proc') AS t1;' The 'AS s (c1 INT)' has a typed alias, while 'AS s (c1)' and 'AS t1' do not. In this case, the second call of 'produce_a_table()' and 'DBLINK()' will be highlighted.", - "markdown": "Reports situations when you make SELECT from a function or a DBLINK without an alias with a type (for example, `AS t1(s VARCHAR)`).\n\nThis requirement does not apply to scalar functions.\n\nExample (PostgreSQL):\n\n CREATE FUNCTION produce_a_table() RETURNS RECORD AS $$\n SELECT 1;\n $$ LANGUAGE sql;\n SELECT * FROM produce_a_table() AS s (c1 INT);\n SELECT * FROM produce_a_table() AS s (c1);\n SELECT * FROM DBLINK('dbname=mydb', 'SELECT proname, prosrc FROM pg_proc') AS t1;\n\nThe `AS s (c1 INT)` has a typed alias, while `AS s (c1)` and `AS t1` do not.\nIn this case, the second call of `produce_a_table()` and `DBLINK()` will be highlighted." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "PgSelectFromProcedure", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "PostgreSQL", - "index": 59, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlCurrentSchemaInspection", - "shortDescription": { - "text": "Current console schema introspected" - }, - "fullDescription": { - "text": "Reports schemas and databases in the current session that are not introspected. For example, this warning might occur when you try to create a table in the schema that is not introspected. Introspection is a method of inspecting a data source. When you perform introspection, structural information in the data source is inspected to detect tables, columns, functions, and other elements with their attributes.", - "markdown": "Reports schemas and databases in the current session that are not introspected.\n\nFor example, this warning might occur when you try to create a table in the schema that is not introspected.\n\nIntrospection is a method of inspecting a data source. When you perform introspection, structural information in the data source is\ninspected to detect tables, columns, functions, and other elements with their attributes." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlCurrentSchemaInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlMisleadingReferenceInspection", - "shortDescription": { - "text": "Misleading references" - }, - "fullDescription": { - "text": "Reports ambiguous references in SQL code. For example, when a name refer to both a table column and a routine parameter. The execution of such code might lead to errors or unexpected results due to counter-intuitive resolution logic. Usually, names with a more local scope have higher priority. Example (PostgreSQL): 'CREATE TABLE foo\n(\n id INT,\n name VARCHAR(5)\n);\nCREATE FUNCTION func(name VARCHAR(5)) RETURNS INT AS\n$$\nDECLARE\n b INT;\nBEGIN\n -- `name` is ambiguous as it is used as a column name and a parameter\n SELECT COUNT(*) INTO b FROM foo t WHERE t.name = name;\n RETURN b;\nEND;\n$$ LANGUAGE plpgsql;' In PostgreSQL, you can use the '#variable_conflict' directives to explicitly specify a correct reference. For example, use '#variable_conflict use_column' to refer to a column name, or '#variable_conflict use_variable' to refer to a parameter. 'CREATE TABLE foo\n(\n id INT,\n name VARCHAR(5)\n);\nCREATE FUNCTION func(name VARCHAR(5)) RETURNS INT AS\n$$\n #variable_conflict use_column\nDECLARE\n b INT;\nBEGIN\n SELECT COUNT(*) INTO b FROM foo t WHERE t.name = name;\n RETURN b;\nEND;\n$$ LANGUAGE plpgsql;'", - "markdown": "Reports ambiguous references in SQL code.\n\nFor example, when a name refer to both a table column and a routine parameter. The execution of such code might lead to errors or unexpected\nresults due to counter-intuitive resolution logic. Usually, names with a more local scope have higher priority.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo\n (\n id INT,\n name VARCHAR(5)\n );\n CREATE FUNCTION func(name VARCHAR(5)) RETURNS INT AS\n $$\n DECLARE\n b INT;\n BEGIN\n -- `name` is ambiguous as it is used as a column name and a parameter\n SELECT COUNT(*) INTO b FROM foo t WHERE t.name = name;\n RETURN b;\n END;\n $$ LANGUAGE plpgsql;\n\nIn PostgreSQL, you can use the `#variable_conflict` directives to explicitly specify a correct reference. For example,\nuse `#variable_conflict use_column` to refer to a column name, or `#variable_conflict use_variable` to refer to a\nparameter.\n\n CREATE TABLE foo\n (\n id INT,\n name VARCHAR(5)\n );\n CREATE FUNCTION func(name VARCHAR(5)) RETURNS INT AS\n $$\n #variable_conflict use_column\n DECLARE\n b INT;\n BEGIN\n SELECT COUNT(*) INTO b FROM foo t WHERE t.name = name;\n RETURN b;\n END;\n $$ LANGUAGE plpgsql;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlMisleadingReference", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlInsertIntoGeneratedColumnInspection", - "shortDescription": { - "text": "Insertion into generated columns" - }, - "fullDescription": { - "text": "Reports INSERT statements that assign values to generated columns. Generated columns can be read, but their values can not be directly written. Example (PostgreSQL): 'CREATE TABLE foo\n(\n col1 INT,\n col2 INT GENERATED ALWAYS AS (col1 + 1) STORED\n);\nINSERT INTO foo(col1, col2) VALUES (1, 2);'\n You cannot insert '2' into the 'col2' column because this column is generated. For this script to work, you can change '2' to DEFAULT. 'INSERT INTO foo(col1, col2) VALUES (1, DEFAULT);'", - "markdown": "Reports INSERT statements that assign values to generated columns. Generated columns can be read, but their values can not be directly written.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo\n (\n col1 INT,\n col2 INT GENERATED ALWAYS AS (col1 + 1) STORED\n );\n INSERT INTO foo(col1, col2) VALUES (1, 2);\n\nYou cannot insert `2` into the `col2` column because this column is generated.\nFor this script to work, you can change `2` to DEFAULT.\n`INSERT INTO foo(col1, col2) VALUES (1, DEFAULT);`" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlInsertIntoGeneratedColumn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlRedundantLimitInspection", - "shortDescription": { - "text": "Redundant row limiting in queries" - }, - "fullDescription": { - "text": "Reports redundant row limiting clauses like FETCH and LIMIT in queries. Example (PostgreSQL): 'CREATE TABLE foo(a INT);\n\nSELECT * FROM foo WHERE EXISTS(SELECT * FROM foo LIMIT 2);\nSELECT * FROM foo WHERE EXISTS(SELECT * FROM foo FETCH FIRST 2 ROWS ONLY);' To fix the warning, you can add OFFSET to limiting clauses. If OFFSET is missing, then LIMIT is redundant because the usage of LIMIT does not influence the operation result of EXISTS. In case with OFFSET, we skip first 'N' rows and this will influence the output. 'SELECT * FROM foo WHERE EXISTS(SELECT * FROM foo OFFSET 1 ROW LIMIT 2);\nSELECT * FROM foo WHERE EXISTS(SELECT * FROM foo OFFSET 1 ROW FETCH FIRST 2 ROWS ONLY);'", - "markdown": "Reports redundant row limiting clauses like FETCH and LIMIT in queries.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT);\n\n SELECT * FROM foo WHERE EXISTS(SELECT * FROM foo LIMIT 2);\n SELECT * FROM foo WHERE EXISTS(SELECT * FROM foo FETCH FIRST 2 ROWS ONLY);\n\nTo fix the warning, you can add OFFSET to limiting clauses. If OFFSET is missing, then LIMIT is redundant because\nthe usage of LIMIT does not influence the operation result of EXISTS. In case with OFFSET, we skip first `N` rows and this will\ninfluence the output.\n\n SELECT * FROM foo WHERE EXISTS(SELECT * FROM foo OFFSET 1 ROW LIMIT 2);\n SELECT * FROM foo WHERE EXISTS(SELECT * FROM foo OFFSET 1 ROW FETCH FIRST 2 ROWS ONLY);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlRedundantLimit", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlInsertNullIntoNotNullInspection", - "shortDescription": { - "text": "Insert NULL into NOT NULL column" - }, - "fullDescription": { - "text": "Reports cases when you insert NULL values into columns that accept only NOT NULL values. Example (Microsoft SQL Server): 'CREATE TABLE br2 (\nid INT NOT NULL,\ncol1 NVARCHAR (20) NOT NULL,\ncol2 NVARCHAR (20) NOT NULL,\n);\n--\nINSERT INTO br2 (id, col1, col2)\nVALUES (1, NULL, NULL);' You cannot insert NULL values in 'col1' and 'col2' because they are defined as NOT NULL. If you run the script as is, you will receive an error. To fix this code, replace NULL in the VALUES part with some values (for example, '42' and ''bird''). INSERT INTO br2 (id, col1, col2)\nVALUES (1, 42, 'bird');", - "markdown": "Reports cases when you insert NULL values into columns that accept only NOT NULL values.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE br2 (\n id INT NOT NULL,\n col1 NVARCHAR (20) NOT NULL,\n col2 NVARCHAR (20) NOT NULL,\n );\n --\n INSERT INTO br2 (id, col1, col2)\n VALUES (1, NULL, NULL);\n\nYou cannot insert NULL values in `col1` and `col2` because they are defined as NOT NULL. If you run the script as\nis,\nyou will receive an error. To fix this code, replace NULL in the VALUES part with some values (for example, `42` and\n`'bird'`).\n\n```\nINSERT INTO br2 (id, col1, col2)\nVALUES (1, 42, 'bird');\n```" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlInsertNullIntoNotNull", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDerivedTableAliasInspection", - "shortDescription": { - "text": "Each derived table should have alias" - }, - "fullDescription": { - "text": "Reports derived tables without aliases. Example (MySQL): 'CREATE TABLE table1 (id INT, name VARCHAR(20), cats FLOAT);\nCREATE TABLE table2 (id INT, age INTEGER);\n\nSELECT id AS ID, name, cats, age\nFROM (SELECT table1.id, name, cats, age\nFROM table1\nJOIN table2 ON table1.id = table2.id);' According to Derived Tables at dev.mysql.com, an alias is mandatory. You can add the alias by using the Introduce alias quick-fix. After the quick-fix is applied: 'SELECT id AS ID, name, cats, age\nFROM (SELECT table1.id, name, cats, age\nFROM table1\nJOIN table2 ON table1.id = table2.id);'", - "markdown": "Reports derived tables without aliases.\n\nExample (MySQL):\n\n CREATE TABLE table1 (id INT, name VARCHAR(20), cats FLOAT);\n CREATE TABLE table2 (id INT, age INTEGER);\n\n SELECT id AS ID, name, cats, age\n FROM (SELECT table1.id, name, cats, age\n FROM table1\n JOIN table2 ON table1.id = table2.id);\n\nAccording to [Derived Tables at dev.mysql.com](https://dev.mysql.com/doc/refman/8.0/en/derived-tables.html), an alias is\nmandatory. You can add the alias by using the **Introduce alias** quick-fix.\n\nAfter the quick-fix is applied:\n\n SELECT id AS ID, name, cats, age\n FROM (SELECT table1.id, name, cats, age\n FROM table1\n JOIN table2 ON table1.id = table2.id);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDerivedTableAlias", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MsBuiltinInspection", - "shortDescription": { - "text": "Builtin functions" - }, - "fullDescription": { - "text": "Reports truncations of string arguments in ISNULL functions. The ISNULL syntax is 'ISNULL(check_expression, replacement_value)'. According to ISNULL at docs.microsoft.com, 'replacement_value' will be truncated if 'replacement_value' is longer than 'check_expression'. Example (Microsoft SQL Server): 'DECLARE @name1 VARCHAR(2) = NULL;\nDECLARE @name2 VARCHAR(10) = 'Example';\nDECLARE @name3 VARCHAR(2) = 'Hi';\n\n -- `@name2` is VARCHAR(10) and will be truncated\nSELECT ISNULL(@name1, @name2);\n\n -- `@name3` is VARCHAR(2) as `@name1` and will not be truncated\nSELECT ISNULL(@name1, @name3);'", - "markdown": "Reports truncations of string arguments in ISNULL functions.\n\nThe ISNULL syntax is `ISNULL(check_expression, replacement_value)`.\n\nAccording to [ISNULL at\ndocs.microsoft.com](https://docs.microsoft.com/en-us/sql/t-sql/functions/isnull-transact-sql), `replacement_value` will be truncated if `replacement_value` is longer than\n`check_expression`.\n\nExample (Microsoft SQL Server):\n\n DECLARE @name1 VARCHAR(2) = NULL;\n DECLARE @name2 VARCHAR(10) = 'Example';\n DECLARE @name3 VARCHAR(2) = 'Hi';\n\n -- `@name2` is VARCHAR(10) and will be truncated\n SELECT ISNULL(@name1, @name2);\n\n -- `@name3` is VARCHAR(2) as `@name1` and will not be truncated\n SELECT ISNULL(@name1, @name3);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MssqlBuiltin", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL server", - "index": 60, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlTriggerTransitionInspection", - "shortDescription": { - "text": "Suspicious code in triggers" - }, - "fullDescription": { - "text": "Reports incorrect usages of transition table variables in triggers. Example (HSQLDB): 'CREATE TABLE foo(a INT);\n\nCREATE TRIGGER trg\n AFTER DELETE ON foo\nBEGIN\n SELECT * FROM NEW;\nEND;\n\nCREATE TRIGGER trig AFTER INSERT ON foo\n REFERENCING OLD ROW AS newrow\n FOR EACH ROW WHEN (a > 1)\n INSERT INTO foo VALUES (1)' In HSQLDB, DELETE triggers may be used only with the OLD state while INSERT triggers may have only the NEW state. So, in the previous example, NEW in 'SELECT * FROM NEW;' will be highlighted as well as OLD in 'REFERENCING OLD ROW AS newrow'.", - "markdown": "Reports incorrect usages of transition table variables in triggers.\n\nExample (HSQLDB):\n\n CREATE TABLE foo(a INT);\n\n CREATE TRIGGER trg\n AFTER DELETE ON foo\n BEGIN\n SELECT * FROM NEW;\n END;\n\n CREATE TRIGGER trig AFTER INSERT ON foo\n REFERENCING OLD ROW AS newrow\n FOR EACH ROW WHEN (a > 1)\n INSERT INTO foo VALUES (1)\n\nIn HSQLDB, DELETE triggers may be used only with the OLD state while INSERT triggers may have only the NEW state. So, in the previous\nexample, NEW in `SELECT * FROM NEW;` will be highlighted as well as OLD in `REFERENCING OLD ROW AS newrow`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlTriggerTransition", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlNamedArgumentsInspection", - "shortDescription": { - "text": "Named arguments should be used" - }, - "fullDescription": { - "text": "Reports arguments that are used without names in routine calls. By default, this inspection is disabled. For more information about the difference between named and unnamed parameters, see Binding Parameters by Name (Named Parameters) at docs.microsoft.com . Example (Microsoft SQL Server): 'CREATE FUNCTION foo(n INT, m INT) RETURNS INT AS\nBEGIN\n RETURN n + m;\nEND;\n\nCREATE PROCEDURE test AS\nBEGIN\n foo n = 1, m = 2;\n\n--- The following call misses parameter names and will be highlighted\n foo 1, 2;\nEND;' Parameters '1, 2' in the 'foo 1, 2;' call are highlighted because they miss names.", - "markdown": "Reports arguments that are used without names in routine calls. By default, this inspection is disabled.\n\nFor more information about the difference between named and unnamed parameters, see [Binding Parameters by Name (Named Parameters) at docs.microsoft.com](https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/binding-parameters-by-name-named-parameters).\n\nExample (Microsoft SQL Server):\n\n CREATE FUNCTION foo(n INT, m INT) RETURNS INT AS\n BEGIN\n RETURN n + m;\n END;\n\n CREATE PROCEDURE test AS\n BEGIN\n foo n = 1, m = 2;\n\n --- The following call misses parameter names and will be highlighted\n foo 1, 2;\n END;\n\nParameters `1, 2` in the `foo 1, 2;` call are highlighted because they miss names." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlNamedArguments", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlMultipleLimitClausesInspection", - "shortDescription": { - "text": "Multiple row limiting/offset clauses in queries" - }, - "fullDescription": { - "text": "Reports usages of multiple row limiting clauses in a single query. Example (Microsoft SQL Server): 'create table foo(a int);\nselect top 1 * from foo order by a offset 10 rows fetch next 20 rows only;' The SELECT TOP clause is used to specify that only 1 record must be returned. The FETCH clause specifies the number of rows to return after the OFFSET clause has been processed. But as we already have the SELECT TOP limiting clause, the FETCH clause might be redundant.", - "markdown": "Reports usages of multiple row limiting clauses in a single query.\n\nExample (Microsoft SQL Server):\n\n create table foo(a int);\n select top 1 * from foo order by a offset 10 rows fetch next 20 rows only;\n\nThe SELECT TOP clause is used to specify that only 1 record must be\nreturned. The FETCH clause specifies the number of rows to return after the OFFSET\nclause has been processed. But as we already have the SELECT TOP limiting clause, the FETCH clause might be redundant." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlMultipleLimitClauses", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlCaseVsCoalesceInspection", - "shortDescription": { - "text": "Using CASE instead of COALESCE function and vice versa" - }, - "fullDescription": { - "text": "Reports situations when CASE and COALESCE calls are interchangeable. This inspection has the following intention actions: Replace with 'COALESCE' call and the opposite one Replace with CASE expression. Example (MySQL): 'SELECT\n -- this CASE may be replaced by COALESCE\n\tCASE\n\t\tWHEN C1 IS NOT NULL THEN C1\n\t\tELSE 0\n\t\tEND\nFROM dual;' In the example, the CASE statement can be replaced with 'SELECT COALESCE(C1, 0)' that produces the same output. If you prefer using CASE expressions, select the Prefer CASE expressions over COALESCE function option on the inspection page.", - "markdown": "Reports situations when CASE and COALESCE calls are interchangeable. This inspection has the following intention actions: **Replace\nwith 'COALESCE' call** and the opposite one **Replace with CASE expression** .\n\nExample (MySQL):\n\n SELECT\n -- this CASE may be replaced by COALESCE\n \tCASE\n \t\tWHEN C1 IS NOT NULL THEN C1\n \t\tELSE 0\n \t\tEND\n FROM dual;\n\nIn the example, the CASE statement can be replaced with `SELECT COALESCE(C1, 0)` that produces the same output.\n\nIf you prefer using CASE expressions, select the **Prefer CASE expressions over COALESCE function** option on\nthe inspection page." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlCaseVsCoalesce", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlIdentifierInspection", - "shortDescription": { - "text": "Identifier should be quoted" - }, - "fullDescription": { - "text": "Reports situations when you use SQL reserved keywords as identifier names in your query. Example (Microsoft SQL Server): 'CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);' We use 'select', 'identity', and 'order' as table and column names. But they are also reserved keywords in Microsoft SQL Server. Therefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the Quote identifier quick-fix. After the quick-fix is applied: 'CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);'", - "markdown": "Reports situations when you use SQL reserved keywords as identifier names in your query.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE select (identity INT IDENTITY NOT NULL, order INT NOT NULL);\n\nWe use `select`, `identity`, and `order` as table and column names.\nBut they are also reserved keywords in Microsoft SQL Server.\nTherefore, in order to use them as object names in the query, you must quote these identifiers. To quote them, you can use the\n**Quote identifier** quick-fix.\n\nAfter the quick-fix is applied:\n\n CREATE TABLE [select] ([identity] INT IDENTITY NOT NULL, [order] INT NOT NULL);\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlIdentifier", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlRedundantAliasInspection", - "shortDescription": { - "text": "Redundant alias expressions" - }, - "fullDescription": { - "text": "Reports alias expressions that duplicate names of columns in tables and might be redundant. Example (PostgreSQL): 'CREATE TABLE foo(a INT, b INT);\n\nSELECT * FROM foo foo(a, b);\nSELECT * FROM foo foo(a);\nSELECT * FROM foo foo(x);\nSELECT * FROM foo foo(x, y);' The first two aliases use the same column names as in the 'foo' table. They are considered redundant because they column names are identical.", - "markdown": "Reports alias expressions that duplicate names of columns in tables and might be redundant.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT, b INT);\n\n SELECT * FROM foo foo(a, b);\n SELECT * FROM foo foo(a);\n SELECT * FROM foo foo(x);\n SELECT * FROM foo foo(x, y);\n\nThe first two aliases use the same column names as in the `foo` table. They are considered redundant because they\ncolumn names are identical." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlRedundantAlias", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlTransactionStatementInTriggerInspection", - "shortDescription": { - "text": "Use of transaction management statements in triggers" - }, - "fullDescription": { - "text": "Reports usages of transaction management statements like COMMIT or ROLLBACK in trigger bodies. With COMMIT or ROLLBACK statements in a trigger body, the trigger will not compile. The fail happens because triggers start during transactions. When the trigger starts the current transaction is still not complete. As COMMIT terminates a transaction, both statements (COMMIT and ROLLBACK) would lead to an exception. Changes that are executed in a trigger should be committed (or rolled back) by the owning transaction that started the trigger. Example (Oracle): 'CREATE TABLE employee_audit\n(\n id INT NOT NULL,\n update_date DATE NOT NULL,\n old_name VARCHAR2(100),\n new_name VARCHAR2(100)\n);\n\nCREATE TABLE employees\n(\n id INT NOT NULL,\n name VARCHAR2(100) NOT NULL\n);\n\nCREATE OR REPLACE TRIGGER trig_commit\n AFTER UPDATE OF name\n ON employees\n FOR EACH ROW\nBEGIN\n INSERT INTO employee_audit VALUES (:old.id, SYSDATE, :old.name, :new.name);\n COMMIT;\nEND;\n\nCREATE OR REPLACE TRIGGER trig_rollback\n AFTER UPDATE OF name\n ON employees\n FOR EACH ROW\nBEGIN\n INSERT INTO employee_audit VALUES (:old.id, SYSDATE, :old.name, :new.name);\n ROLLBACK;\nEND;'", - "markdown": "Reports usages of transaction management statements like COMMIT or ROLLBACK in trigger bodies.\n\nWith COMMIT or ROLLBACK statements in a trigger body, the trigger will not compile.\nThe fail happens because triggers start during transactions. When the trigger starts the current transaction is still not complete. As\nCOMMIT\nterminates a transaction, both statements (COMMIT and ROLLBACK) would lead to an exception.\nChanges that are executed in a trigger should be committed (or rolled back) by the owning transaction that started the trigger.\n\nExample (Oracle):\n\n CREATE TABLE employee_audit\n (\n id INT NOT NULL,\n update_date DATE NOT NULL,\n old_name VARCHAR2(100),\n new_name VARCHAR2(100)\n );\n\n CREATE TABLE employees\n (\n id INT NOT NULL,\n name VARCHAR2(100) NOT NULL\n );\n\n CREATE OR REPLACE TRIGGER trig_commit\n AFTER UPDATE OF name\n ON employees\n FOR EACH ROW\n BEGIN\n INSERT INTO employee_audit VALUES (:old.id, SYSDATE, :old.name, :new.name);\n COMMIT;\n END;\n\n CREATE OR REPLACE TRIGGER trig_rollback\n AFTER UPDATE OF name\n ON employees\n FOR EACH ROW\n BEGIN\n INSERT INTO employee_audit VALUES (:old.id, SYSDATE, :old.name, :new.name);\n ROLLBACK;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlTransactionStatementInTrigger", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlRedundantCodeInCoalesceInspection", - "shortDescription": { - "text": "Redundant code in COALESCE call" - }, - "fullDescription": { - "text": "Reports all the arguments except for the first expression that does not evaluate to NULL in COALESCE functions. Example (MySQL): 'SELECT COALESCE(NULL, NULL, NULL, 42, NULL, 'string') as a;' The first NOT NULL argument is '42', all other arguments will be grayed out.", - "markdown": "Reports all the arguments except for the first expression that does not evaluate to NULL in COALESCE functions.\n\nExample (MySQL):\n\n SELECT COALESCE(NULL, NULL, NULL, 42, NULL, 'string') as a;\n\nThe first NOT NULL argument is `42`, all other arguments will be grayed out." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlRedundantCodeInCoalesce", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlStorageInspection", - "shortDescription": { - "text": "SQL source modification detection" - }, - "fullDescription": { - "text": "Reports situations when source code of a database object has been changed. The inspection is triggered when you perform database or object introspection. The introspection is run when you open source code of an object, run statements, and perform code refactoring. Also, you can run introspection by right-clicking an object and selecting Refresh. The inspection covers the following situations: Object source code was changed in the database but code in the editor was not updated. Works in PostgreSQL, Microsoft SQL Server, Oracle, and Sybase ASE. You changed the object source code, introspected the database, but source code has been already changed by someone else. The database introspector was updated in the IDE and you need to download new object properties that were missing in the previous introspector version.", - "markdown": "Reports situations when source code of a database object has been changed.\n\nThe inspection is triggered when you perform database or object introspection. The introspection is run when you open source code of an\nobject, run statements, and perform code refactoring.\nAlso, you can run introspection by right-clicking an object and selecting **Refresh**.\n\nThe inspection covers the following situations:\n\n* Object source code was changed in the database but code in the editor was not updated. Works in PostgreSQL, Microsoft SQL Server, Oracle, and Sybase ASE.\n* You changed the object source code, introspected the database, but source code has been already changed by someone else.\n* The database introspector was updated in the IDE and you need to download new object properties that were missing in the previous introspector version." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlStorageInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MsOrderByInspection", - "shortDescription": { - "text": "ORDER BY in queries" - }, - "fullDescription": { - "text": "Reports usages when the 'ORDER BY' clause is used without 'TOP', 'OFFSET', or 'FOR XML' in views, inline functions, derived tables, subqueries, and common table expressions. For more information about usages of 'ORDER BY', see SELECT - ORDER BY Clause (Transact-SQL) at docs.microsoft.com. Example (Microsoft SQL server): 'CREATE TABLE foo (a INT NOT NULL, b INT NOT NULL);\n\nSELECT *\nFROM (SELECT a, b\nFROM foo A\nWHERE a < 89\nORDER BY b) ALIAS;' In a subquery, ORDER BY will be highlighted as an error. You can add TOP, OFFSET, or FOR XML to a subquery. Alternatively, use the Delete element quick-fix to delete the ORDER BY section. After the quick-fix is applied: 'SELECT *\nFROM (SELECT a, b\nFROM foo A\nWHERE a < 89) ALIAS;'", - "markdown": "Reports usages when the `ORDER BY` clause is used without `TOP`, `OFFSET`, or `FOR XML` in views, inline functions, derived tables, subqueries, and common table expressions.\n\nFor more information about usages of `ORDER BY`, see [SELECT - ORDER BY Clause (Transact-SQL) at\ndocs.microsoft.com](https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql).\n\nExample (Microsoft SQL server):\n\n CREATE TABLE foo (a INT NOT NULL, b INT NOT NULL);\n\n SELECT *\n FROM (SELECT a, b\n FROM foo A\n WHERE a < 89\n ORDER BY b) ALIAS;\n\nIn a subquery, ORDER BY will be highlighted as an error. You can add TOP, OFFSET, or FOR XML to a subquery.\nAlternatively, use the **Delete element** quick-fix to delete the ORDER BY section.\n\nAfter the quick-fix is applied:\n\n SELECT *\n FROM (SELECT a, b\n FROM foo A\n WHERE a < 89) ALIAS;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "MsOrderBy", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "SQL server", - "index": 60, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlSignatureInspection", - "shortDescription": { - "text": "Function signature" - }, - "fullDescription": { - "text": "Reports signature issues for built-in functions. The inspection will report a wrong number of arguments, invalid keywords, wrong data types, and other issues. Example (MySQL): 'CREATE TABLE foo (a INT, b INT, c INT)\n\nSELECT IFNULL() FROM foo; -- error\nSELECT IFNULL(a) FROM foo; -- error\nSELECT IFNULL(a, b) FROM foo; -- OK\nSELECT IFNULL(a, b, c) FROM foo; -- error' In MySQL, the 'IFNULL()' function accepts strictly two arguments. So, only the 'SELECT IFNULL(a, b) FROM foo;' query is correct.", - "markdown": "Reports signature issues for built-in functions.\n\nThe inspection will report a wrong number of arguments, invalid keywords, wrong data types, and other issues.\n\nExample (MySQL):\n\n CREATE TABLE foo (a INT, b INT, c INT)\n\n SELECT IFNULL() FROM foo; -- error\n SELECT IFNULL(a) FROM foo; -- error\n SELECT IFNULL(a, b) FROM foo; -- OK\n SELECT IFNULL(a, b, c) FROM foo; -- error\n\nIn MySQL, the `IFNULL()` function accepts strictly two arguments. So, only the `SELECT IFNULL(a, b) FROM foo;`\nquery is correct." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlSignature", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlRedundantOrderingDirectionInspection", - "shortDescription": { - "text": "Redundant ordering direction" - }, - "fullDescription": { - "text": "Reports redundant ordering directions like ASC and DESC in ORDER BY clauses. Example (MySQL): 'CREATE TABLE foo(a INT, b INT, c INT);\nSELECT * FROM foo ORDER BY a ASC, b DESC, c ASC;' The ORDER BY keyword sorts the records in the ascending order by default. So, the 'ASC' keyword for 'a' and 'c' columns is redundant.", - "markdown": "Reports redundant ordering directions like ASC and DESC in ORDER BY clauses.\n\nExample (MySQL):\n\n CREATE TABLE foo(a INT, b INT, c INT);\n SELECT * FROM foo ORDER BY a ASC, b DESC, c ASC;\n\nThe ORDER BY keyword sorts the records in the ascending order by default. So, the `ASC` keyword for `a` and\n`c` columns is redundant." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlRedundantOrderingDirection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlDeprecateTypeInspection", - "shortDescription": { - "text": "Deprecated type" - }, - "fullDescription": { - "text": "Reports usages of types that are deprecated and might disappear in future versions of DBMS. Reported types: LONG in Oracle (see Deprecated and Desupported Features at docs.oracle.com). TEXT, NTEXT, and IMAGE in Microsoft SQL Server (see Deprecated Database Engine Features in SQL Server 2016 at docs.microsoft.com). Example (Oracle): 'CREATE TABLE ot.foo(\na NUMBER GENERATED BY DEFAULT AS IDENTITY,\nb LONG NOT NULL\n);'", - "markdown": "Reports usages of types that are deprecated and might disappear in future versions of DBMS.\n\nReported types:\n\n* LONG in Oracle (see [Deprecated\n and Desupported Features at docs.oracle.com](https://docs.oracle.com/cd/A91202_01/901_doc/server.901/a90120/ch4_dep.htm#6690)).\n* TEXT, NTEXT, and IMAGE in Microsoft SQL Server (see [Deprecated Database Engine Features in SQL Server 2016 at docs.microsoft.com](https://docs.microsoft.com/en-us/sql/database-engine/deprecated-database-engine-features-in-sql-server-2016?view=sql-server-ver15)).\n\nExample (Oracle):\n\n CREATE TABLE ot.foo(\n a NUMBER GENERATED BY DEFAULT AS IDENTITY,\n b LONG NOT NULL\n );\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlDeprecateType", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlAggregatesInspection", - "shortDescription": { - "text": "Aggregate-related problems" - }, - "fullDescription": { - "text": "Reports invalid usages of SQL aggregate functions. The following situations are considered: Columns that are used in HAVING and ORDER BY clauses but are missed in GROUP BY clauses. 'CREATE TABLE foo(id INT PRIMARY KEY, a INT, b INT);\nSELECT a, MAX(b) FROM foo GROUP BY a HAVING b > 0;\nSELECT * FROM foo GROUP BY a ORDER BY b;' This rule does not apply when grouping is made by the primary key. 'SELECT * FROM foo GROUP BY id ORDER BY b;' Aggregate functions in a wrong context. Usually, you can use aggregate functions in the following contexts: a list of expressions in SELECT; in HAVING and ORDER BY sections; and other dialect-specific cases. The following queries will display an error. 'SELECT a FROM foo WHERE MAX(b) > 0;\nSELECT a FROM foo GROUP BY MAX(a);' Nested calls of aggregate functions. 'SELECT MAX(SUM(a)) FROM foo GROUP BY a;' This rule does not apply to analytic functions. The following query is valid and correct. 'SELECT MAX(SUM(a) OVER ()) FROM foo;' Usages of HAVING without aggregate functions. In this case, consider rewriting your code using the WHERE section. 'SELECT a, MAX(b) FROM foo GROUP BY a HAVING a > 0;'", - "markdown": "Reports invalid usages of SQL aggregate functions.\n\nThe following situations are considered:\n\n* Columns that are used in HAVING and ORDER BY clauses but are missed in GROUP BY clauses.\n\n CREATE TABLE foo(id INT PRIMARY KEY, a INT, b INT);\n SELECT a, MAX(b) FROM foo GROUP BY a HAVING b > 0;\n SELECT * FROM foo GROUP BY a ORDER BY b;\n\n This rule does not apply when grouping is made by the primary key.\n\n SELECT * FROM foo GROUP BY id ORDER BY b;\n\n* Aggregate functions in a wrong context. Usually, you can use aggregate functions in the following contexts: a list of expressions in\n SELECT; in HAVING and ORDER BY sections; and other dialect-specific cases. The following queries will display an error.\n\n SELECT a FROM foo WHERE MAX(b) > 0;\n SELECT a FROM foo GROUP BY MAX(a);\n\n* Nested calls of aggregate functions.\n\n SELECT MAX(SUM(a)) FROM foo GROUP BY a;\n\n This rule does not apply to analytic functions. The following query is valid and correct.\n\n SELECT MAX(SUM(a) OVER ()) FROM foo;\n\n* Usages of HAVING without aggregate functions. In this case, consider rewriting your code using the WHERE section.\n\n SELECT a, MAX(b) FROM foo GROUP BY a HAVING a > 0;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlAggregates", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlConstantExpressionInspection", - "shortDescription": { - "text": "Constant expression" - }, - "fullDescription": { - "text": "Reports conditions and expressions that are always true, false or null. Example (MySQL): 'CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\nSELECT a FROM t1 WHERE 'Cat' = 'Cat';\nSELECT a FROM t1 WHERE 'Cat' = null;' The ''Cat' = 'Cat'' is always true and will be reported. The ''Cat' = null' is always null and will be reported.", - "markdown": "Reports conditions and expressions that are always true, false or null.\n\nExample (MySQL):\n\n CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\n SELECT a FROM t1 WHERE 'Cat' = 'Cat';\n SELECT a FROM t1 WHERE 'Cat' = null;\n\nThe `'Cat' = 'Cat'` is always true and will be reported.\n\nThe `'Cat' = null` is always null and will be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlConstantExpression", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlMissingColumnAliasesInspection", - "shortDescription": { - "text": "Missing column aliases" - }, - "fullDescription": { - "text": "Reports queries without explicit aliases in output expressions (for example, in the SELECT statement). Example (PostgreSQL): 'CREATE TABLE foo(a INT, b INT);\n\nSELECT 1, a + 1 AS A2, MAX(b) AS M\nFROM foo;'", - "markdown": "Reports queries without explicit aliases in output expressions (for example, in the SELECT statement).\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT, b INT);\n\n SELECT 1, a + 1 AS A2, MAX(b) AS M\n FROM foo;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlMissingColumnAliases", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlAddNotNullColumnInspection", - "shortDescription": { - "text": "Adding not null column without default value" - }, - "fullDescription": { - "text": "Reports attempts to create NOT NULL columns without DEFAULT values. Example (Microsoft SQL Server): 'CREATE TABLE foo (a INT, b INT)\n\nALTER TABLE foo ADD c INT NOT NULL;' By default, a column holds NULL values. In the example, we use the NOT NULL constraint that enforces a column not to accept NULL values. If we prohibit to use NULL values, we must set the DEFAULT value that SQL can use when we create a new record. 'ALTER TABLE foo ADD c INT NOT NULL DEFAULT 42;' You can quickly add the DEFAULT value by using the Add DEFAULT value quick-fix.", - "markdown": "Reports attempts to create NOT NULL columns without DEFAULT values.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE foo (a INT, b INT)\n\n ALTER TABLE foo ADD c INT NOT NULL;\n\nBy default, a column holds NULL values. In the example, we use the NOT NULL constraint that enforces a column not to accept NULL values.\nIf we prohibit to use NULL values, we must set the DEFAULT value that SQL can use when we create a new record.\n\n ALTER TABLE foo ADD c INT NOT NULL DEFAULT 42;\n\nYou can quickly add the DEFAULT value by using the **Add DEFAULT value** quick-fix." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlAddNotNullColumn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "OraOverloadInspection", - "shortDescription": { - "text": "Overloading errors" - }, - "fullDescription": { - "text": "Reports invalid cases of subprogram overloading in Oracle. Example (Oracle): 'DECLARE\n SUBTYPE fff IS BINARY_INTEGER;\n SUBTYPE ggg IS NATURAL;\n PROCEDURE foo (a IN ggg) IS BEGIN NULL; END;\n PROCEDURE foo (a IN fff) IS BEGIN NULL; END;\nBEGIN\n NULL;\nEND;' You cannot overload subprograms which parameters differ only in subtypes. For example, you cannot overload procedures where one accepts a BINARY INTEGER parameter and the other accepts a NATURAL parameter. For more information about restrictions on procedure overloading, see Restrictions on Overloading at docs.oracle.com.", - "markdown": "Reports invalid cases of subprogram overloading in Oracle.\n\nExample (Oracle):\n\n DECLARE\n SUBTYPE fff IS BINARY_INTEGER;\n SUBTYPE ggg IS NATURAL;\n PROCEDURE foo (a IN ggg) IS BEGIN NULL; END;\n PROCEDURE foo (a IN fff) IS BEGIN NULL; END;\n BEGIN\n NULL;\n END;\n\nYou cannot overload subprograms which parameters differ only in subtypes. For example, you cannot overload procedures where one accepts a\nBINARY INTEGER parameter and the other accepts a NATURAL parameter. For more information about restrictions on procedure overloading,\nsee [Restrictions on Overloading at docs.oracle.com](https://docs.oracle.com/cd/B19306_01/appdev.102/b14261/subprograms.htm)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlOverload", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Oracle", - "index": 63, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "OraMissingBodyInspection", - "shortDescription": { - "text": "Missing body for package/object type specification" - }, - "fullDescription": { - "text": "Reports package and object type specifications that are missing body declarations. Package specifications and object types that declare routines as well as package specifications with cursors must have body declarations where those routines and cursors are implemented. Absence of a body leads to a runtime error when routines or cursors are invoked in program code. Example (Oracle): 'CREATE OR REPLACE PACKAGE ppp IS\n FUNCTION foo(a INT) RETURN INT;\nEND;'", - "markdown": "Reports package and object type specifications that are missing body declarations.\n\nPackage specifications and object types that declare routines as well as package specifications with cursors must have body\ndeclarations where those routines and cursors are implemented. Absence of a body leads to a runtime error when routines or cursors are\ninvoked in program code.\n\nExample (Oracle):\n\n CREATE OR REPLACE PACKAGE ppp IS\n FUNCTION foo(a INT) RETURN INT;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlMissingBody", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Oracle", - "index": 63, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "OraUnmatchedForwardDeclarationInspection", - "shortDescription": { - "text": "Forward declaration without definition" - }, - "fullDescription": { - "text": "Reports declarations of procedures and functions that are missing their implementation in code. In Oracle, you can declare a procedure or a function without its body, and write the implementation later. The inspection will report names of such procedures or functions that are left without implementation. Example (Oracle): 'DECLARE PROCEDURE foo(a int, b varchar2);\nBEGIN\n NULL;\nEND;' The 'foo' procedure is declared but is missing implementation. We can add the implementation to get rid of the error. 'DECLARE PROCEDURE foo(a int, b varchar2);\n PROCEDURE foo(a int, b varchar2) IS\nBEGIN\n NULL;\nEND;\nBEGIN\n NULL;\nEND;'", - "markdown": "Reports declarations of procedures and functions that are missing their implementation in code.\n\nIn Oracle, you can declare a procedure or a function without its body, and write the implementation later. The inspection will report names\nof such procedures or functions that are left without implementation.\n\nExample (Oracle):\n\n DECLARE PROCEDURE foo(a int, b varchar2);\n BEGIN\n NULL;\n END;\n\nThe `foo` procedure is declared but is missing implementation. We can add the implementation to get rid of the error.\n\n DECLARE PROCEDURE foo(a int, b varchar2);\n PROCEDURE foo(a int, b varchar2) IS\n BEGIN\n NULL;\n END;\n BEGIN\n NULL;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "SqlUnmatchedForwardDeclaration", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "Oracle", - "index": 63, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlGotoInspection", - "shortDescription": { - "text": "Usages of GOTO statements" - }, - "fullDescription": { - "text": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop. The extensive use of GOTO statements is generally not recommended. For details, see GOTO statement in SQL procedures at ibm.com. Instead of jumping back to a previous statement using GOTO, consider using a loop. Instead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK). Example (Oracle): 'CREATE PROCEDURE test(n INT) AS\nDECLARE\n x INT;\nBEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\nEND;'", - "markdown": "Reports usages of backward GOTO statements and GOTO statements used to exit a loop.\n\nThe extensive use of GOTO statements is generally\nnot recommended. For details, see [GOTO statement in\nSQL\nprocedures at ibm.com](https://www.ibm.com/docs/no/db2/11.5?topic=procedures-goto-statement-in-sql).\n\nInstead of jumping back to a previous statement using GOTO, consider using a loop.\n\nInstead of exiting the WHILE loop with GOTO, consider using other control-of-flow statements (for example, RETURN or BREAK).\n\nExample (Oracle):\n\n CREATE PROCEDURE test(n INT) AS\n DECLARE\n x INT;\n BEGIN\n x := 0;\n GOTO a;\n <> x := 1;\n IF (n = 0) THEN\n GOTO a;\n END IF;\n WHILE TRUE\n LOOP\n GOTO b;\n END LOOP;\n <> x := 3;\n END;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlGoto", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MongoJSExtResolveInspection", - "shortDescription": { - "text": "Resolution problems" - }, - "fullDescription": { - "text": "Reports unresolved references in MongoDB and JavaScript code.", - "markdown": "Reports unresolved references in MongoDB and JavaScript code." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSResolve", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlWithoutWhereInspection", - "shortDescription": { - "text": "Delete or update statement without where clauses" - }, - "fullDescription": { - "text": "Reports usages of DELETE or UPDATE statements without WHERE clauses. Without WHERE clauses, DELETE drops all the data from the table, and UPDATE overwrites values for all the table rows. Example (MySQL): 'CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\nupdate t1 set a = 'Smith';\ndelete from t1;'", - "markdown": "Reports usages of DELETE or UPDATE statements without WHERE clauses.\n\nWithout WHERE clauses, DELETE drops all the data from the table, and UPDATE overwrites values for all the table rows.\n\nExample (MySQL):\n\n CREATE TABLE t1 (a TEXT, b INT, c BOOLEAN);\n update t1 set a = 'Smith';\n delete from t1;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlWithoutWhere", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlAmbiguousColumnInspection", - "shortDescription": { - "text": "Ambiguous reference" - }, - "fullDescription": { - "text": "Reports columns that have identical names but belong to different tables. Example (MySQL): 'CREATE TABLE foo(id INT PRIMARY KEY);\nCREATE TABLE bar(id INT PRIMARY KEY);\n\nSELECT foo.id, bar.id FROM foo, bar WHERE id > 0;' The 'id' column appears in 'foo' and 'bar' tables. You need to qualify the column name to make the query correct. 'SELECT foo.id, bar.id FROM foo, bar WHERE foo.id > 0;'", - "markdown": "Reports columns that have identical names but belong to different tables.\n\nExample (MySQL):\n\n CREATE TABLE foo(id INT PRIMARY KEY);\n CREATE TABLE bar(id INT PRIMARY KEY);\n\n SELECT foo.id, bar.id FROM foo, bar WHERE id > 0;\n\nThe `id` column appears in `foo` and `bar` tables. You need to qualify the column name to\nmake the query correct.\n\n SELECT foo.id, bar.id FROM foo, bar WHERE foo.id > 0;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlAmbiguousColumn", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlUnusedCteInspection", - "shortDescription": { - "text": "Unused common table expression" - }, - "fullDescription": { - "text": "Reports unused common table expressions (CTE) inside the query. Example (PostgreSQL): 'CREATE TABLE foo(a INT);\n\nWITH a AS (SELECT 1 AS x FROM foo)\nSELECT 1 + 2 FROM foo;' By using WITH, we create a temporary named result set with the name 'a', also known as a common table expression (CTE). But we do not use this CTE later in the code. The unused CTE is greyed out.", - "markdown": "Reports unused common table expressions (CTE) inside the query.\n\nExample (PostgreSQL):\n\n CREATE TABLE foo(a INT);\n\n WITH a AS (SELECT 1 AS x FROM foo)\n SELECT 1 + 2 FROM foo;\n\nBy using WITH, we create a temporary named result set with the name `a`, also known as a common table expression (CTE). But\nwe do not use this CTE later in the code. The unused CTE is greyed out." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlUnusedCte", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "MongoJSResolveInspection", - "shortDescription": { - "text": "Resolution problems" - }, - "fullDescription": { - "text": "Reports unresolved references in MongoDB and JavaScript code. Example: 'db\nuse foo\n -- a reference to a non-existing collection\ndb.non_existing_collection\ndb['non_existing_collection']\ndb['non_existing_collection'].find().hasNext()' The 'non_existing_collection' collection does not exist in the database and will be reported.", - "markdown": "Reports unresolved references in MongoDB and JavaScript code.\n\nExample:\n\n db\n use foo\n -- a reference to a non-existing collection\n db.non_existing_collection\n db['non_existing_collection']\n db['non_existing_collection'].find().hasNext()\n\nThe `non_existing_collection` collection does not exist in the database and will be reported." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "MongoJSResolve", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "MongoJS", - "index": 10, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "SqlNullComparisonInspection", - "shortDescription": { - "text": "Null comparison" - }, - "fullDescription": { - "text": "Reports comparisons with NULL that can be replaced with IS NULL or IS NOT NULL operators. Example (Microsoft SQL Server): 'CREATE TABLE foo ( id int );\n\nSELECT * FROM foo WHERE NULL = NULL;\nSELECT * FROM foo WHERE NULL != NULL;' The 'NULL = NULL' can be replaced with 'IS NULL', the 'NULL != NULL' comparison with 'IS NOT NULL'. To do this replacement, you can use Use IS NULL operator or Use IS NOT NULL operator quick-fixes. 'SELECT * FROM foo WHERE NULL IS NULL;\nSELECT * FROM foo WHERE NULL IS NOT NULL;'", - "markdown": "Reports comparisons with NULL that can be replaced with IS NULL or IS NOT NULL operators.\n\nExample (Microsoft SQL Server):\n\n CREATE TABLE foo ( id int );\n\n SELECT * FROM foo WHERE NULL = NULL;\n SELECT * FROM foo WHERE NULL != NULL;\n\nThe `NULL = NULL` can be replaced with `IS NULL`, the `NULL != NULL` comparison\nwith `IS NOT NULL`. To do this replacement, you can use **Use IS NULL operator** or **Use IS NOT NULL operator**\nquick-fixes.\n\n SELECT * FROM foo WHERE NULL IS NULL;\n SELECT * FROM foo WHERE NULL IS NOT NULL;\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "SqlNullComparison", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "SQL", - "index": 32, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.intellij.properties", - "version": "232.9876", - "rules": [ - { - "id": "DuplicatePropertyInspection", - "shortDescription": { - "text": "Duplicate property" - }, - "fullDescription": { - "text": "Reports duplicate property keys with different values, duplicate keys, or duplicate property values. Example: 'property1=value;\nproperty2=value;' The Options list allows selecting the area in which the inspection should search for duplicates.", - "markdown": "Reports duplicate property keys with different values, duplicate keys, or duplicate property values.\n\nExample:\n\n\n property1=value;\n property2=value;\n\nThe **Options** list allows selecting the area in which the inspection should search for duplicates." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DuplicatePropertyInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UseEllipsisInPropertyInspection", - "shortDescription": { - "text": "Three dot characters instead of the ellipsis" - }, - "fullDescription": { - "text": "Reports three \"dot\" characters which are used instead of the ellipsis character for UTF-8 properties files.", - "markdown": "Reports three \"dot\" characters which are used instead of the ellipsis character for UTF-8 properties files." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UseEllipsisInPropertyInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "AlphaUnsortedPropertiesFile", - "shortDescription": { - "text": "Properties file or resource bundle is alphabetically unsorted" - }, - "fullDescription": { - "text": "Reports alphabetically unsorted resource bundles or .properties files.", - "markdown": "Reports alphabetically unsorted resource bundles or .properties files." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "AlphaUnsortedPropertiesFile", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "TrailingSpacesInProperty", - "shortDescription": { - "text": "Trailing spaces in property" - }, - "fullDescription": { - "text": "Reports properties whose keys or values end with a whitespace.", - "markdown": "Reports properties whose keys or values end with a whitespace." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "TrailingSpacesInProperty", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "UnusedProperty", - "shortDescription": { - "text": "Unused property" - }, - "fullDescription": { - "text": "Reports properties that are not referenced outside of the .properties file they are contained in.", - "markdown": "Reports properties that are not referenced outside of the .properties file they are contained in." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "UnusedProperty", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "WrongPropertyKeyValueDelimiter", - "shortDescription": { - "text": "Property key/value delimiter doesn't match code style settings" - }, - "fullDescription": { - "text": "Reports properties in which key or value delimiters do not match code style settings.", - "markdown": "Reports properties in which key or value delimiters do not match code style settings." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "WrongPropertyKeyValueDelimiter", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Properties files", - "index": 14, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "HtmlTools", - "version": "232.9876", - "rules": [ - { - "id": "HtmlRequiredAltAttribute", - "shortDescription": { - "text": "Missing required 'alt' attribute" - }, - "fullDescription": { - "text": "Reports a missing 'alt' attribute in a 'img' or 'applet' tag or in a 'area' element of an image map. Suggests adding a required attribute with a text alternative for the contents of the tag. Based on WCAG 2.0: H24, H35, H36, H37.", - "markdown": "Reports a missing `alt` attribute in a `img` or `applet` tag or in a `area` element of an image map. Suggests adding a required attribute with a text alternative for the contents of the tag. Based on WCAG 2.0: [H24](https://www.w3.org/TR/WCAG20-TECHS/H24.html), [H35](https://www.w3.org/TR/WCAG20-TECHS/H35.html), [H36](https://www.w3.org/TR/WCAG20-TECHS/H36.html), [H37](https://www.w3.org/TR/WCAG20-TECHS/H37.html)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlRequiredAltAttribute", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlFormInputWithoutLabel", - "shortDescription": { - "text": "Missing associated label" - }, - "fullDescription": { - "text": "Reports a form element ('input', 'textarea', or 'select') without an associated label. Suggests creating a new label. Based on WCAG 2.0: H44.", - "markdown": "Reports a form element (`input`, `textarea`, or `select`) without an associated label. Suggests creating a new label. Based on WCAG 2.0: [H44](https://www.w3.org/TR/WCAG20-TECHS/H44.html). " - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlFormInputWithoutLabel", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlRequiredTitleAttribute", - "shortDescription": { - "text": "Missing required 'title' attribute" - }, - "fullDescription": { - "text": "Reports a missing title attribute 'frame', 'iframe', 'dl', and 'a' tags. Suggests adding a title attribute. Based on WCAG 2.0: H33, H40, and H64.", - "markdown": "Reports a missing title attribute `frame`, `iframe`, `dl`, and `a` tags. Suggests adding a title attribute. Based on WCAG 2.0: [H33](https://www.w3.org/TR/WCAG20-TECHS/H33.html), [H40](https://www.w3.org/TR/WCAG20-TECHS/H40.html), and [H64](https://www.w3.org/TR/WCAG20-TECHS/H64.html)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "HtmlRequiredTitleAttribute", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlDeprecatedTag", - "shortDescription": { - "text": "Obsolete tag" - }, - "fullDescription": { - "text": "Reports an obsolete HTML5 tag. Suggests replacing the obsolete tag with a CSS or another tag.", - "markdown": "Reports an obsolete HTML5 tag. Suggests replacing the obsolete tag with a CSS or another tag." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlDeprecatedTag", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckImageSize", - "shortDescription": { - "text": "Mismatched image size" - }, - "fullDescription": { - "text": "Reports a 'width' and 'height' attribute value of a 'img' tag that is different from the actual width and height of the referenced image.", - "markdown": "Reports a `width` and `height` attribute value of a `img` tag that is different from the actual width and height of the referenced image." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CheckImageSize", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlRequiredSummaryAttribute", - "shortDescription": { - "text": "Missing required 'summary' attribute" - }, - "fullDescription": { - "text": "Reports a missing 'summary' attribute in a 'table' tag. Suggests adding a'summary' attribute. Based on WCAG 2.0: H73.", - "markdown": "Reports a missing `summary` attribute in a `table` tag. Suggests adding a`summary` attribute. Based on WCAG 2.0: [H73](https://www.w3.org/TR/WCAG20-TECHS/H73.html)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "HtmlRequiredSummaryAttribute", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlRequiredLangAttribute", - "shortDescription": { - "text": "Missing required 'lang' attribute" - }, - "fullDescription": { - "text": "Reports a missing 'lang' (or 'xml:lang') attribute in a 'html' tag. Suggests adding a required attribute to state the default language of the document. Based on WCAG 2.0: H57.", - "markdown": "Reports a missing `lang` (or `xml:lang`) attribute in a `html` tag. Suggests adding a required attribute to state the default language of the document. Based on WCAG 2.0: [H57](https://www.w3.org/TR/WCAG20-TECHS/H57.html)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlRequiredLangAttribute", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlNonExistentInternetResource", - "shortDescription": { - "text": "Unresolved web link" - }, - "fullDescription": { - "text": "Reports an unresolved web link. Works by making network requests in the background.", - "markdown": "Reports an unresolved web link. Works by making network requests in the background." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlNonExistentInternetResource", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlRequiredTitleElement", - "shortDescription": { - "text": "Missing required 'title' element" - }, - "fullDescription": { - "text": "Reports a missing 'title' element inside a 'head' section. Suggests adding a 'title' element. The title should describe the document. Based on WCAG 2.0: H25.", - "markdown": "Reports a missing `title` element inside a `head` section. Suggests adding a `title` element. The title should describe the document. Based on WCAG 2.0: [H25](https://www.w3.org/TR/WCAG20-TECHS/H25.html)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlRequiredTitleElement", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML/Accessibility", - "index": 25, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlDeprecatedAttribute", - "shortDescription": { - "text": "Obsolete attribute" - }, - "fullDescription": { - "text": "Reports an obsolete HTML5 attribute.", - "markdown": "Reports an obsolete HTML5 attribute." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "HtmlDeprecatedAttribute", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "HtmlPresentationalElement", - "shortDescription": { - "text": "Presentational tag" - }, - "fullDescription": { - "text": "Reports a presentational HTML tag. Suggests replacing the presentational tag with a CSS or another tag.", - "markdown": "Reports a presentational HTML tag. Suggests replacing the presentational tag with a CSS or another tag." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "HtmlPresentationalElement", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "HTML", - "index": 18, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.intellij.css", - "version": "232.9876", - "rules": [ - { - "id": "CssInvalidHtmlTagReference", - "shortDescription": { - "text": "Invalid type selector" - }, - "fullDescription": { - "text": "Reports a CSS type selector that matches an unknown HTML element.", - "markdown": "Reports a CSS [type selector](https://developer.mozilla.org/en-US/docs/Web/CSS/Type_selectors) that matches an unknown HTML element." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssInvalidHtmlTagReference", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidFunction", - "shortDescription": { - "text": "Invalid function" - }, - "fullDescription": { - "text": "Reports an unknown CSS function or an incorrect function parameter.", - "markdown": "Reports an unknown [CSS function](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions) or an incorrect function parameter." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssInvalidFunction", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssMissingSemicolon", - "shortDescription": { - "text": "Missing semicolon" - }, - "fullDescription": { - "text": "Reports a missing semicolon at the end of a declaration.", - "markdown": "Reports a missing semicolon at the end of a declaration." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssMissingSemicolon", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Code style issues", - "index": 41, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssRedundantUnit", - "shortDescription": { - "text": "Redundant measure unit" - }, - "fullDescription": { - "text": "Reports a measure unit of a zero value where units are not required by the specification. Example: 'width: 0px'", - "markdown": "Reports a measure unit of a zero value where units are not required by the specification.\n\n**Example:**\n\n width: 0px\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssRedundantUnit", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Code style issues", - "index": 41, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssMissingComma", - "shortDescription": { - "text": "Missing comma in selector list" - }, - "fullDescription": { - "text": "Reports a multi-line selector. Most likely this means that several single-line selectors are actually intended but a comma is missing at the end of one or several lines. Example: 'input /* comma has probably been forgotten */\n.button {\n margin: 1px;\n}'", - "markdown": "Reports a multi-line selector. Most likely this means that several single-line selectors are actually intended but a comma is missing at the end of one or several lines.\n\n**Example:**\n\n\n input /* comma has probably been forgotten */\n .button {\n margin: 1px;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssMissingComma", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Probable bugs", - "index": 49, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidPropertyValue", - "shortDescription": { - "text": "Invalid property value" - }, - "fullDescription": { - "text": "Reports an incorrect CSS property value.", - "markdown": "Reports an incorrect CSS property value." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssInvalidPropertyValue", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssBrowserCompatibilityForProperties", - "shortDescription": { - "text": "Property is incompatible with selected browsers" - }, - "fullDescription": { - "text": "Reports a CSS property that is not supported by the specified browsers. Based on the MDN Compatibility Data.", - "markdown": "Reports a CSS property that is not supported by the specified browsers. Based on the [MDN Compatibility Data](https://github.com/mdn/browser-compat-data)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssBrowserCompatibilityForProperties", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssConvertColorToHexInspection", - "shortDescription": { - "text": "Color could be replaced with #-hex" - }, - "fullDescription": { - "text": "Reports an 'rgb()', 'hsl()', or other color function. Suggests replacing a color function with an equivalent hexadecimal notation. Example: 'rgb(12, 15, 255)' After the quick-fix is applied: '#0c0fff'.", - "markdown": "Reports an `rgb()`, `hsl()`, or other color function.\n\nSuggests replacing a color function with an equivalent hexadecimal notation.\n\n**Example:**\n\n rgb(12, 15, 255)\n\nAfter the quick-fix is applied:\n\n #0c0fff.\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssConvertColorToHexInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssReplaceWithShorthandUnsafely", - "shortDescription": { - "text": "Properties may probably be replaced with a shorthand" - }, - "fullDescription": { - "text": "Reports a set of longhand CSS properties and suggests replacing an incomplete set of longhand CSS properties with a shorthand form, which is however not 100% equivalent in this case. For example, 2 properties: 'outline-color' and 'outline-style' may be replaced with a single 'outline'. Such replacement is not 100% equivalent because shorthands reset all omitted sub-values to their initial states. In this example, switching to the 'outline' shorthand means that 'outline-width' is also set to its initial value, which is 'medium'. This inspection doesn't handle full sets of longhand properties (when switching to shorthand is 100% safe). For such cases see the 'Properties may be safely replaced with a shorthand' inspection instead.", - "markdown": "Reports a set of longhand CSS properties and suggests replacing an incomplete set of longhand CSS properties with a shorthand form, which is however not 100% equivalent in this case.\n\n\nFor example, 2 properties: `outline-color` and `outline-style` may be replaced with a single `outline`.\nSuch replacement is not 100% equivalent because shorthands reset all omitted sub-values to their initial states.\nIn this example, switching to the `outline` shorthand means that `outline-width` is also set to its initial value,\nwhich is `medium`.\n\n\nThis inspection doesn't handle full sets of longhand properties (when switching to shorthand is 100% safe).\nFor such cases see the 'Properties may be safely replaced with a shorthand' inspection instead." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "CssReplaceWithShorthandUnsafely", - "ideaSeverity": "INFORMATION", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnknownUnit", - "shortDescription": { - "text": "Unknown unit" - }, - "fullDescription": { - "text": "Reports an unknown unit", - "markdown": "Reports an unknown unit" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssUnknownUnit", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidMediaFeature", - "shortDescription": { - "text": "Invalid media feature" - }, - "fullDescription": { - "text": "Reports an unknown CSS media feature or an incorrect media feature value.", - "markdown": "Reports an unknown [CSS media feature](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) or an incorrect media feature value." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssInvalidMediaFeature", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssConvertColorToRgbInspection", - "shortDescription": { - "text": "Color could be replaced with rgb()" - }, - "fullDescription": { - "text": "Reports an 'hsl()' or 'hwb()' color function or a hexadecimal color notation. Suggests replacing such color value with an equivalent 'rgb()' or 'rgba()' color function. Example: '#0c0fff' After the quick-fix is applied: 'rgb(12, 15, 255)'.", - "markdown": "Reports an `hsl()` or `hwb()` color function or a hexadecimal color notation.\n\nSuggests replacing such color value with an equivalent `rgb()` or `rgba()` color function.\n\n**Example:**\n\n #0c0fff\n\nAfter the quick-fix is applied:\n\n rgb(12, 15, 255).\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssConvertColorToRgbInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnusedSymbol", - "shortDescription": { - "text": "Unused selector" - }, - "fullDescription": { - "text": "Reports a CSS class or an element IDs that appears in selectors but is not used in HTML. Note that complete inspection results are available only when running it via Code | Inspect Code or Code | Analyze Code | Run Inspection by Name. Due to performance reasons, style sheet files are not inspected on the fly.", - "markdown": "Reports a CSS class or an element IDs that appears in selectors but is not used in HTML.\n\n\nNote that complete inspection results are available only when running it via **Code \\| Inspect Code** or\n**Code \\| Analyze Code \\| Run Inspection by Name**.\nDue to performance reasons, style sheet files are not inspected on the fly." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssUnusedSymbol", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssDeprecatedValue", - "shortDescription": { - "text": "Deprecated value" - }, - "fullDescription": { - "text": "Reports a deprecated CSS value. Suggests replacing the deprecated value with valid equivalent.", - "markdown": "Reports a deprecated CSS value. Suggests replacing the deprecated value with valid equivalent." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssDeprecatedValue", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssNonIntegerLengthInPixels", - "shortDescription": { - "text": "Non-integer length in pixels" - }, - "fullDescription": { - "text": "Reports a non-integer length in pixels. Example: 'width: 3.14px'", - "markdown": "Reports a non-integer length in pixels.\n\n**Example:**\n\n width: 3.14px\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "CssNonIntegerLengthInPixels", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Probable bugs", - "index": 49, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidImport", - "shortDescription": { - "text": "Misplaced @import" - }, - "fullDescription": { - "text": "Reports a misplaced '@import' statement. According to the specification, '@import' rules must precede all other types of rules, except '@charset' rules.", - "markdown": "Reports a misplaced `@import` statement.\n\n\nAccording to the [specification](https://developer.mozilla.org/en-US/docs/Web/CSS/@import),\n`@import` rules must precede all other types of rules, except `@charset` rules." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssInvalidImport", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidAtRule", - "shortDescription": { - "text": "Unknown at-rule" - }, - "fullDescription": { - "text": "Reports an unknown CSS at-rule.", - "markdown": "Reports an unknown [CSS at-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssInvalidAtRule", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnresolvedCustomProperty", - "shortDescription": { - "text": "Unresolved custom property" - }, - "fullDescription": { - "text": "Reports an unresolved reference to a custom property among the arguments of the 'var()' function.", - "markdown": "Reports an unresolved reference to a [custom property](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) among the arguments of the `var()` function." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssUnresolvedCustomProperty", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssOverwrittenProperties", - "shortDescription": { - "text": "Overwritten property" - }, - "fullDescription": { - "text": "Reports a duplicated CSS property within a ruleset. Respects shorthand properties. Example: '.foo {\n margin-bottom: 1px;\n margin-bottom: 1px; /* duplicates margin-bottom */\n margin: 0; /* overrides margin-bottom */\n}'", - "markdown": "Reports a duplicated CSS property within a ruleset. Respects shorthand properties.\n\n**Example:**\n\n\n .foo {\n margin-bottom: 1px;\n margin-bottom: 1px; /* duplicates margin-bottom */\n margin: 0; /* overrides margin-bottom */\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssOverwrittenProperties", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnknownTarget", - "shortDescription": { - "text": "Unresolved file reference" - }, - "fullDescription": { - "text": "Reports an unresolved file reference, for example, an incorrect path in an '@import' statement.", - "markdown": "Reports an unresolved file reference, for example, an incorrect path in an `@import` statement." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssUnknownTarget", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssNegativeValue", - "shortDescription": { - "text": "Negative property value" - }, - "fullDescription": { - "text": "Reports a negative value of a CSS property that is not expected to be less than zero, for example, object width or height.", - "markdown": "Reports a negative value of a CSS property that is not expected to be less than zero, for example, object width or height." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssNegativeValue", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssNoGenericFontName", - "shortDescription": { - "text": "Missing generic font family name" - }, - "fullDescription": { - "text": "Verifies that the 'font-family' property contains a generic font family name as a fallback alternative. Generic font family names are: 'serif', 'sans-serif', 'cursive', 'fantasy', and 'monospace'.", - "markdown": "Verifies that the [font-family](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family) property contains a generic font family name as a fallback alternative.\n\n\nGeneric font family names are: `serif`, `sans-serif`, `cursive`, `fantasy`,\nand `monospace`." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssNoGenericFontName", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Probable bugs", - "index": 49, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnresolvedClassInComposesRule", - "shortDescription": { - "text": "Unresolved class in 'composes' rule" - }, - "fullDescription": { - "text": "Reports a CSS class reference in the 'composes' rule that cannot be resolved to any valid target. Example: '.className {/* ... */}\n\n .otherClassName {\n composes: className;\n }'", - "markdown": "Reports a CSS class reference in the ['composes'](https://github.com/css-modules/css-modules#composition) rule that cannot be resolved to any valid target.\n\n**Example:**\n\n\n .className {/* ... */}\n\n .otherClassName {\n composes: className;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssUnresolvedClassInComposesRule", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidCharsetRule", - "shortDescription": { - "text": "Misplaced or incorrect @charset" - }, - "fullDescription": { - "text": "Reports a misplaced '@charset' at-rule or an incorrect charset value.", - "markdown": "Reports a misplaced `@charset` at-rule or an incorrect charset value." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssInvalidCharsetRule", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssReplaceWithShorthandSafely", - "shortDescription": { - "text": "Properties may be safely replaced with a shorthand" - }, - "fullDescription": { - "text": "Reports a set of longhand properties. Suggests replacing a complete set of longhand CSS properties with an equivalent shorthand form. For example, 4 properties: 'padding-top', 'padding-right', 'padding-bottom', and 'padding-left' can be safely replaced with a single 'padding' property. Note that this inspection doesn't show up if the set of longhand properties is incomplete (e.g. only 3 'padding-xxx' properties in a ruleset) because switching to a shorthand may change the result. For such cases consider the 'Properties may probably be replaced with a shorthand' inspection.", - "markdown": "Reports a set of longhand properties. Suggests replacing a complete set of longhand CSS properties with an equivalent shorthand form.\n\n\nFor example, 4 properties: `padding-top`, `padding-right`, `padding-bottom`, and\n`padding-left`\ncan be safely replaced with a single `padding` property.\n\n\nNote that this inspection doesn't show up if the set of longhand properties is incomplete\n(e.g. only 3 `padding-xxx` properties in a ruleset)\nbecause switching to a shorthand may change the result.\nFor such cases consider the 'Properties may probably be replaced with a shorthand'\ninspection." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "CssReplaceWithShorthandSafely", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "CSS", - "index": 30, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssUnknownProperty", - "shortDescription": { - "text": "Unknown property" - }, - "fullDescription": { - "text": "Reports an unknown CSS property or a property used in a wrong context. Add the unknown property to the 'Custom CSS properties' list to skip validation.", - "markdown": "Reports an unknown CSS property or a property used in a wrong context.\n\nAdd the unknown property to the 'Custom CSS properties' list to skip validation." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssUnknownProperty", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidPseudoSelector", - "shortDescription": { - "text": "Invalid pseudo-selector" - }, - "fullDescription": { - "text": "Reports an incorrect CSS pseudo-class pseudo-element.", - "markdown": "Reports an incorrect CSS [pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes) [pseudo-element](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "CssInvalidPseudoSelector", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CssInvalidNestedSelector", - "shortDescription": { - "text": "Invalid nested selector" - }, - "fullDescription": { - "text": "Reports a nested selector starting with an identifier or a functional notation.", - "markdown": "Reports a nested selector starting with an identifier or a functional notation." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CssInvalidNestedSelector", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "CSS/Invalid elements", - "index": 31, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.intellij.plugins.dependencyAnalysis", - "version": "232.9876", - "rules": [ - { - "id": "CheckThirdPartySoftwareList", - "shortDescription": { - "text": "Check third party software list" - }, - "fullDescription": { - "text": "Check project for possible problems: user's third party software list does not match the collected project metadata", - "markdown": "Check project for possible problems: user's third party software list does not match the collected project metadata" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CheckThirdPartySoftwareList", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Dependency analysis", - "index": 36, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckDependencyLicenses", - "shortDescription": { - "text": "Check dependency licenses" - }, - "fullDescription": { - "text": "Check dependencies licenses for possible problems: missing or prohibited licenses, or other compliance issues", - "markdown": "Check dependencies licenses for possible problems: missing or prohibited licenses, or other compliance issues" - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "CheckDependencyLicenses", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Dependency analysis", - "index": 36, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "CheckModuleLicenses", - "shortDescription": { - "text": "Check module licenses" - }, - "fullDescription": { - "text": "Check module licenses for possible problems: missing licenses or other compliance issues", - "markdown": "Check module licenses for possible problems: missing licenses or other compliance issues" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "CheckModuleLicenses", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Dependency analysis", - "index": 36, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.jetbrains.plugins.yaml", - "version": "232.9876", - "rules": [ - { - "id": "YAMLSchemaValidation", - "shortDescription": { - "text": "Validation by JSON Schema" - }, - "fullDescription": { - "text": "Reports inconsistencies between a YAML file and a JSON Schema if the schema is specified. Scheme example: '{\n \"properties\": {\n \"SomeNumberProperty\": {\n \"type\": \"number\"\n }\n }\n }' The following is an example with the corresponding warning: 'SomeNumberProperty: hello world'", - "markdown": "Reports inconsistencies between a YAML file and a JSON Schema if the schema is specified.\n\n**Scheme example:**\n\n\n {\n \"properties\": {\n \"SomeNumberProperty\": {\n \"type\": \"number\"\n }\n }\n }\n\n**The following is an example with the corresponding warning:**\n\n\n SomeNumberProperty: hello world\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "YAMLSchemaValidation", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLIncompatibleTypes", - "shortDescription": { - "text": "Suspicious type mismatch" - }, - "fullDescription": { - "text": "Reports a mismatch between a scalar value type in YAML file and types of the values in the similar positions. Example: 'myElements:\n - value1\n - value2\n - false # <- reported, because it is a boolean value, while other values are strings'", - "markdown": "Reports a mismatch between a scalar value type in YAML file and types of the values in the similar positions.\n\n**Example:**\n\n\n myElements:\n - value1\n - value2\n - false # <- reported, because it is a boolean value, while other values are strings\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "YAMLIncompatibleTypes", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLUnresolvedAlias", - "shortDescription": { - "text": "Unresolved alias" - }, - "fullDescription": { - "text": "Reports unresolved aliases in YAML files. Example: 'some_key: *unknown_alias'", - "markdown": "Reports unresolved aliases in YAML files.\n\n**Example:**\n\n\n some_key: *unknown_alias\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "YAMLUnresolvedAlias", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLSchemaDeprecation", - "shortDescription": { - "text": "Deprecated YAML key" - }, - "fullDescription": { - "text": "Reports deprecated keys in YAML files. Deprecation is checked only if there exists a JSON schema associated with the corresponding YAML file. Note that the deprecation mechanism is not defined in the JSON Schema specification yet, and this inspection uses a non-standard 'deprecationMessage' extension. Scheme deprecation example: '{\n \"properties\": {\n \"SomeDeprecatedProperty\": {\n \"deprecationMessage\": \"Baz\",\n \"description\": \"Foo bar\"\n }\n }\n }' The following is an example with the corresponding warning: 'SomeDeprecatedProperty: some value'", - "markdown": "Reports deprecated keys in YAML files.\n\nDeprecation is checked only if there exists a JSON schema associated with the corresponding YAML file.\n\nNote that the deprecation mechanism is not defined in the JSON Schema specification yet,\nand this inspection uses a non-standard `deprecationMessage` extension.\n\n**Scheme deprecation example:**\n\n\n {\n \"properties\": {\n \"SomeDeprecatedProperty\": {\n \"deprecationMessage\": \"Baz\",\n \"description\": \"Foo bar\"\n }\n }\n }\n\n**The following is an example with the corresponding warning:**\n\n\n SomeDeprecatedProperty: some value\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "YAMLSchemaDeprecation", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLRecursiveAlias", - "shortDescription": { - "text": "Recursive alias" - }, - "fullDescription": { - "text": "Reports recursion in YAML aliases. Alias can't be recursive and be used inside the data referenced by a corresponding anchor. Example: 'some_key: &some_anchor\n sub_key1: value1\n sub_key2: *some_anchor'", - "markdown": "Reports recursion in YAML aliases.\n\nAlias can't be recursive and be used inside the data referenced by a corresponding anchor.\n\n**Example:**\n\n\n some_key: &some_anchor\n sub_key1: value1\n sub_key2: *some_anchor\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "YAMLRecursiveAlias", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLDuplicatedKeys", - "shortDescription": { - "text": "Duplicated YAML keys" - }, - "fullDescription": { - "text": "Reports duplicated keys in YAML files. Example: 'same_key: some value\n same_key: another value'", - "markdown": "Reports duplicated keys in YAML files.\n\n**Example:**\n\n\n same_key: some value\n same_key: another value\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "YAMLDuplicatedKeys", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "YAMLUnusedAnchor", - "shortDescription": { - "text": "Unused anchor" - }, - "fullDescription": { - "text": "Reports unused anchors. Example: 'some_key: &some_anchor\n key1: value1'", - "markdown": "Reports unused anchors.\n\n**Example:**\n\n\n some_key: &some_anchor\n key1: value1\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "YAMLUnusedAnchor", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "YAML", - "index": 37, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.jetbrains.security.package-checker", - "version": "232.9876", - "rules": [ - { - "id": "VulnerableLibrariesGlobal", - "shortDescription": { - "text": "Vulnerable imported dependency" - }, - "fullDescription": { - "text": "Reports vulnerabilities in Gradle and Maven dependencies imported into your project. A full list of Gradle and Maven dependencies is shown in the Project tool window under External Libraries. Fixing the reported problems helps prevent your software from being compromised by an attacker. To solve a problem, you can update to a version where the vulnerability is fixed (if available) or switch to a dependency that doesn't have the vulnerability. The quick-fixes available may suggest updating to a safe version or visiting the Checkmarx website to learn more about a particular vulnerability. Vulnerability data provided by Checkmarx (c).", - "markdown": "Reports vulnerabilities in Gradle and Maven dependencies imported into your project.\nA full list of Gradle and Maven dependencies is shown in the Project tool window under External Libraries.\n\nFixing the reported problems helps prevent your software from being compromised by an attacker.\n\nTo solve a problem, you can update to a version where the vulnerability is fixed (if available) or switch to a dependency that doesn't have the vulnerability.\n\nThe quick-fixes available may suggest updating to a safe version or visiting the Checkmarx website to learn more about a particular vulnerability.\n\nVulnerability data provided by [Checkmarx](https://checkmarx.com/) (c)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VulnerableLibrariesGlobal", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Security", - "index": 40, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VulnerableLibrariesLocal", - "shortDescription": { - "text": "Vulnerable declared dependency" - }, - "fullDescription": { - "text": "Reports vulnerabilities in Gradle, Maven, NPM and PyPI dependencies declared in your project. A full list of Gradle and Maven dependencies is shown in the Project tool window under External Libraries. Fixing the reported problems helps prevent your software from being compromised by an attacker. To solve a problem, you can update to a version where the vulnerability is fixed (if available) or switch to a dependency that doesn't have the vulnerability. The quick-fixes available may suggest updating to a safe version or visiting the Checkmarx website to learn more about a particular vulnerability. Vulnerability data provided by Checkmarx (c).", - "markdown": "Reports vulnerabilities in Gradle, Maven, NPM and PyPI dependencies declared in your project.\nA full list of Gradle and Maven dependencies is shown in the Project tool window under External Libraries.\n\nFixing the reported problems helps prevent your software from being compromised by an attacker.\n\nTo solve a problem, you can update to a version where the vulnerability is fixed (if available) or switch to a dependency that doesn't have the vulnerability.\n\nThe quick-fixes available may suggest updating to a safe version or visiting the Checkmarx website to learn more about a particular vulnerability.\n\nVulnerability data provided by [Checkmarx](https://checkmarx.com/) (c)." - }, - "defaultConfiguration": { - "enabled": true, - "level": "warning", - "parameters": { - "suppressToolId": "VulnerableLibrariesLocal", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Security", - "index": 40, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.jetbrains.plugins.less", - "version": "232.9876", - "rules": [ - { - "id": "LessUnresolvedMixin", - "shortDescription": { - "text": "Unresolved mixin" - }, - "fullDescription": { - "text": "Reports a reference to a Less mixin that is not resolved. Example: '* {\n .unknown-mixin();\n}'", - "markdown": "Reports a reference to a [Less mixin](http://lesscss.org/features/#mixins-feature) that is not resolved.\n\n**Example:**\n\n\n * {\n .unknown-mixin();\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LessUnresolvedMixin", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Less", - "index": 42, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LessUnresolvedVariable", - "shortDescription": { - "text": "Unresolved variable" - }, - "fullDescription": { - "text": "Reports a reference to a Less variable that is not resolved. Example: '* {\n margin: @unknown-var;\n}'", - "markdown": "Reports a reference to a [Less variable](http://lesscss.org/features/#variables-feature) that is not resolved.\n\n**Example:**\n\n\n * {\n margin: @unknown-var;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LessUnresolvedVariable", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Less", - "index": 42, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "LessResolvedByNameOnly", - "shortDescription": { - "text": "Missing import" - }, - "fullDescription": { - "text": "Reports a reference to a variable or mixin that is declared in another file, which is not explicitly imported in the current file. Example: '* {\n margin: @var-in-other-file;\n}'", - "markdown": "Reports a reference to a variable or mixin that is declared in another file, which is not explicitly [imported](http://lesscss.org/features/#import-atrules-feature) in the current file.\n\n**Example:**\n\n\n * {\n margin: @var-in-other-file;\n }\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "LessResolvedByNameOnly", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Less", - "index": 42, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.intellij.intelliLang", - "version": "232.9876", - "rules": [ - { - "id": "InjectedReferences", - "shortDescription": { - "text": "Injected references" - }, - "fullDescription": { - "text": "Reports unresolved references injected by Language Injections. Example: '@Language(\"file-reference\")\n String fileName = \"/home/user/nonexistent.file\"; // highlighted if file doesn't exist'", - "markdown": "Reports unresolved references injected by [Language Injections](https://www.jetbrains.com/help/idea/using-language-injections.html).\n\nExample:\n\n\n @Language(\"file-reference\")\n String fileName = \"/home/user/nonexistent.file\"; // highlighted if file doesn't exist\n" - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "InjectedReferences", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "General", - "index": 24, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.jetbrains.plugins.vue", - "version": "232.9876", - "rules": [ - { - "id": "VueDataFunction", - "shortDescription": { - "text": "Data function" - }, - "fullDescription": { - "text": "Reports a Vue component data property that is not a function. Suggests wrapping an object literal with a function. When defining a component, 'data' must be declared as a function that returns the initial data object, because the same definition will be used for creating numerous instances. If a plain object is still used for 'data', that very object will be shared by reference across all instances created! With a 'data' function, every time a new instance is created we can simply call it to return a fresh copy of the initial data.", - "markdown": "Reports a Vue component [data](https://vuejs.org/v2/api/#data) property that is not a function. Suggests wrapping an object literal with a function.\n\nWhen defining a component, `data` must be declared as a function that returns the initial data object, because the same definition will be used for creating numerous instances. If a plain object is still used for `data`, that very object will be shared by reference across all instances created! With a `data` function, every time a new instance is created we can simply call it to return a fresh copy of the initial data." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VueDataFunction", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VueUnrecognizedSlot", - "shortDescription": { - "text": "Unrecognized slot" - }, - "fullDescription": { - "text": "Reports an unrecognized Vue slot.", - "markdown": "Reports an unrecognized Vue slot." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "VueUnrecognizedSlot", - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VueMissingComponentImportInspection", - "shortDescription": { - "text": "Missing component import" - }, - "fullDescription": { - "text": "Reports Vue components, which require to be imported in Vue templates. It provides a quick fix to add the missing import.", - "markdown": "Reports Vue components, which require to be imported in Vue templates. It provides a quick fix to add the missing import." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VueMissingComponentImportInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VueUnrecognizedDirective", - "shortDescription": { - "text": "Unrecognized directive" - }, - "fullDescription": { - "text": "Reports an unrecognized Vue directive.", - "markdown": "Reports an unrecognized Vue directive." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VueUnrecognizedDirective", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VueDuplicateTag", - "shortDescription": { - "text": "Duplicate template/script tag" - }, - "fullDescription": { - "text": "Reports multiple usages of the 'template' or 'script' tag in a Vue file. Vue Component specification indicates that each '*.vue' file can contain at most one 'template' or 'script' block at a time.", - "markdown": "Reports multiple usages of the `template` or `script` tag in a Vue file.\n\n[Vue Component specification](https://vue-loader.vuejs.org/spec.html) indicates that each `*.vue` file can contain at most one `template` or `script` block at a time." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VueDuplicateTag", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "VueDeprecatedSymbol", - "shortDescription": { - "text": "Deprecated symbol" - }, - "fullDescription": { - "text": "Reports a deprecated Vue symbol.", - "markdown": "Reports a deprecated Vue symbol." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "VueDeprecatedSymbol", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Vue", - "index": 44, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "com.jetbrains.plugins.ini4idea", - "version": "232.9876", - "rules": [ - { - "id": "DuplicateKeyInSection", - "shortDescription": { - "text": "Duplicate directive in section" - }, - "fullDescription": { - "text": "Reports duplicate properties in the 'ini' file section.", - "markdown": "Reports duplicate properties in the `ini` file section." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DuplicateKeyInSection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Ini files", - "index": 46, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "DuplicateSectionInFile", - "shortDescription": { - "text": "Duplicate section in file" - }, - "fullDescription": { - "text": "Reports duplicate sections in the 'ini' file.", - "markdown": "Reports duplicate sections in the `ini` file." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "DuplicateSectionInFile", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Ini files", - "index": 46, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "org.intellij.qodana", - "version": "232.9876", - "rules": [ - { - "id": "JsCoverageInspection", - "shortDescription": { - "text": "Check JavaScript and TypeScript source code coverage" - }, - "fullDescription": { - "text": "Reports methods, classes and files whose coverage is below a certain threshold.", - "markdown": "Reports methods, classes and files whose coverage is below a certain threshold." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "JsCoverageInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Code Coverage", - "index": 55, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "QodanaSanity", - "shortDescription": { - "text": "Sanity" - }, - "fullDescription": { - "text": "Reports issues essential to this file like syntax errors, unresolved methods and variables, etc...", - "markdown": "Reports issues essential to this file like syntax errors, unresolved methods and variables, etc..." - }, - "defaultConfiguration": { - "enabled": false, - "level": "error", - "parameters": { - "suppressToolId": "QodanaSanity", - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - "relationships": [ - { - "target": { - "id": "Qodana", - "index": 61, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "intellij.webpack", - "version": "232.9876", - "rules": [ - { - "id": "WebpackConfigHighlighting", - "shortDescription": { - "text": "Webpack config compliance with JSON Schema" - }, - "fullDescription": { - "text": "Validates options in webpack config files (which name should start with `webpack`, e.g. `webpack.config.js`) against webpack options schema. Disable this inspection to turn off validation and code completion inside the configuration object.", - "markdown": "Validates options in webpack config files (which name should start with \\`webpack\\`, e.g. \\`webpack.config.js\\`) against [webpack options schema](https://github.com/webpack/webpack/blob/master/schemas/WebpackOptions.json). \n\nDisable this inspection to turn off validation and code completion inside the configuration object." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "WebpackConfigHighlighting", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "JavaScript and TypeScript/General", - "index": 11, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - }, - { - "name": "tanvd.grazi", - "version": "232.9876", - "rules": [ - { - "id": "LanguageDetectionInspection", - "shortDescription": { - "text": "Natural language detection" - }, - "fullDescription": { - "text": "Detects natural languages and suggests enabling corresponding grammar and spelling checks.", - "markdown": "Detects natural languages and suggests enabling corresponding grammar and spelling checks." - }, - "defaultConfiguration": { - "enabled": false, - "level": "warning", - "parameters": { - "suppressToolId": "LanguageDetectionInspection", - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - "relationships": [ - { - "target": { - "id": "Proofreading", - "index": 56, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - }, - { - "id": "GrazieInspection", - "shortDescription": { - "text": "Grammar" - }, - "fullDescription": { - "text": "Reports grammar mistakes in your text. You can configure the inspection in Settings | Editor | Natural Languages | Grammar.", - "markdown": "Reports grammar mistakes in your text. You can configure the inspection in [Settings \\| Editor \\| Natural Languages \\| Grammar](settings://reference.settingsdialog.project.grazie)." - }, - "defaultConfiguration": { - "enabled": false, - "level": "note", - "parameters": { - "suppressToolId": "GrazieInspection", - "ideaSeverity": "GRAMMAR_ERROR", - "qodanaSeverity": "Info" - } - }, - "relationships": [ - { - "target": { - "id": "Proofreading", - "index": 56, - "toolComponent": { - "name": "QDPY" - } - }, - "kinds": [ - "superset" - ] - } - ] - } - ], - "language": "en-US", - "contents": [ - "localizedData", - "nonLocalizedData" - ], - "isComprehensive": false - } - ] - }, - "invocations": [ - { - "exitCode": 0, - "toolExecutionNotifications": [ - { - "message": { - "text": "Reporting from [\"Sanity\", \"Unresolved references\", \"An invalid interpreter\"] 'sanity' inspections was suspended due to high problems count." - }, - "level": "error" - } - ], - "executionSuccessful": true - } - ], - "language": "en-US", - "versionControlProvenance": [ - { - "repositoryUri": "https://github.com/Pale-Blue-Dot-97/Minerva.git", - "revisionId": "7a23092940ae572c0dd637d13478238d83406d13", - "branch": "downstream-tasks-module", - "properties": { - "repoUrl": "https://github.com/Pale-Blue-Dot-97/Minerva.git", - "lastAuthorName": "Harry Baker", - "vcsType": "Git", - "lastAuthorEmail": "hjbaker97@gmail.com" - } - } - ], - "results": [ - { - "ruleId": "PyBroadExceptionInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Too broad exception clause", - "markdown": "Too broad exception clause" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 527, - "startColumn": 5, - "charOffset": 17438, - "charLength": 6, - "snippet": { - "text": "except" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 525, - "startColumn": 1, - "charOffset": 17350, - "charLength": 160, - "snippet": { - "text": " if \"VSCODE_PID\" in os.environ: # pragma: no cover\n return False\n except: # noqa: E722\n return False\n else: # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "fde4c482b4e89a58866efaf001419f5699512eb5fb724aa6a5fcc17be3b212ca" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Down' object is not callable", - "markdown": "'Down' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 304, - "startColumn": 14, - "charOffset": 11040, - "charLength": 14, - "snippet": { - "text": "self.down1(x1)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 302, - "startColumn": 1, - "charOffset": 11001, - "charLength": 109, - "snippet": { - "text": "\n x1 = self.inc(x)\n x2 = self.down1(x1)\n x3 = self.down2(x2)\n x4 = self.down3(x3)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0cfbe9d7ccf76fb41f5af230bc6347765d98d670b8c13c420a289669188ac30e" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'MinervaModel' object is not callable", - "markdown": "'MinervaModel' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/siamese.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 344, - "startColumn": 50, - "charOffset": 13820, - "charLength": 16, - "snippet": { - "text": "self.backbone(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 342, - "startColumn": 1, - "charOffset": 13677, - "charLength": 246, - "snippet": { - "text": " and the detached embedding vector from the :attr:`~SimSiam.backbone`.\n \"\"\"\n z: Tensor = self.proj_head(torch.flatten(self.backbone(x)[0], start_dim=1)) # type: ignore[attr-defined]\n\n p: Tensor = self.predictor(z)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "1124cb52fa27182bfe0d832719e866db8aba5dea12d071eabced0693717c3b4e" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 311, - "startColumn": 13, - "charOffset": 11209, - "charLength": 15, - "snippet": { - "text": "self.up3(x, x2)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 309, - "startColumn": 1, - "charOffset": 11140, - "charLength": 113, - "snippet": { - "text": " x = self.up1(x5, x4)\n x = self.up2(x, x3)\n x = self.up3(x, x2)\n x = self.up4(x, x1)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "19e9359ca0b65319572b3fc72959eab94319896d99d1d252aa159854c5b2f8b5" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Down' object is not callable", - "markdown": "'Down' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 305, - "startColumn": 14, - "charOffset": 11068, - "charLength": 14, - "snippet": { - "text": "self.down2(x2)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 303, - "startColumn": 1, - "charOffset": 11002, - "charLength": 136, - "snippet": { - "text": " x1 = self.inc(x)\n x2 = self.down1(x1)\n x3 = self.down2(x2)\n x4 = self.down3(x3)\n x5 = self.down4(x4)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "27886b4f7b6655da490b80a2e4525266277f52f45e0049fdc9d30bfaf390f78d" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 312, - "startColumn": 13, - "charOffset": 11237, - "charLength": 15, - "snippet": { - "text": "self.up4(x, x1)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 310, - "startColumn": 1, - "charOffset": 11169, - "charLength": 122, - "snippet": { - "text": " x = self.up2(x, x3)\n x = self.up3(x, x2)\n x = self.up4(x, x1)\n\n logits: Tensor = self.outc(x)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "29217e81ab4172cbd4de13417bd9876b3d19336b469daa3e72617f9931959dca" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'OutConv' object is not callable", - "markdown": "'OutConv' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 314, - "startColumn": 26, - "charOffset": 11279, - "charLength": 12, - "snippet": { - "text": "self.outc(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 312, - "startColumn": 1, - "charOffset": 11225, - "charLength": 109, - "snippet": { - "text": " x = self.up4(x, x1)\n\n logits: Tensor = self.outc(x)\n\n assert isinstance(logits, Tensor)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2973e889f0f0c4b04929a4ce406e83a3b0ab23dbf0ded97e9c092e698f3cfdc7" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'DoubleConv' object is not callable", - "markdown": "'DoubleConv' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 202, - "startColumn": 13, - "charOffset": 7415, - "charLength": 12, - "snippet": { - "text": "self.conv(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 200, - "startColumn": 1, - "charOffset": 7333, - "charLength": 132, - "snippet": { - "text": " x = torch.cat([x2, x1], dim=1) # type: ignore[attr-defined]\n\n x = self.conv(x)\n\n assert isinstance(x, Tensor)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2a6ba49ce0574fbe4fda6fe3da1cdb172a6a09c4461a48b9330affc60bec875c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 310, - "startColumn": 13, - "charOffset": 11181, - "charLength": 15, - "snippet": { - "text": "self.up2(x, x3)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 308, - "startColumn": 1, - "charOffset": 11139, - "charLength": 113, - "snippet": { - "text": "\n x = self.up1(x5, x4)\n x = self.up2(x, x3)\n x = self.up3(x, x2)\n x = self.up4(x, x1)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2f52edd21b1b317aa3302a88c4cb770c199dc102639203709019207fc569a96d" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Down' object is not callable", - "markdown": "'Down' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 307, - "startColumn": 14, - "charOffset": 11124, - "charLength": 14, - "snippet": { - "text": "self.down4(x4)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 305, - "startColumn": 1, - "charOffset": 11055, - "charLength": 113, - "snippet": { - "text": " x3 = self.down2(x2)\n x4 = self.down3(x3)\n x5 = self.down4(x4)\n\n x = self.up1(x5, x4)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4156f68b4071f98d60b2328a569f63ba89af1044feaf2a78bfde60bf7dad82c2" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'ResNet' object is not callable", - "markdown": "'ResNet' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/resnet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 448, - "startColumn": 75, - "charOffset": 20639, - "charLength": 37, - "snippet": { - "text": "self.network(\n x\n )" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 446, - "startColumn": 1, - "charOffset": 20440, - "charLength": 291, - "snippet": { - "text": " :class:`~torch.Tensor` of the likelihoods the network places on the input ``x`` being of each class.\n \"\"\"\n z: Union[Tensor, Tuple[Tensor, Tensor, Tensor, Tensor, Tensor]] = self.network(\n x\n )\n if isinstance(z, Tensor):\n return z" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4a8283fabacca2bd59d508e1a5bc0ff67c9c106d3a45865f3183262470786be8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'DCN' object is not callable", - "markdown": "'DCN' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/fcn.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 152, - "startColumn": 13, - "charOffset": 6798, - "charLength": 15, - "snippet": { - "text": "self.decoder(z)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 150, - "startColumn": 1, - "charOffset": 6745, - "charLength": 106, - "snippet": { - "text": " \"\"\"\n z = self.backbone(x)\n z = self.decoder(z)\n\n assert isinstance(z, Tensor)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5378765acbfd976ef1ad530652c010dd7c2d59d87b199c4b0c6554b0f5b04c37" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'MinervaModel' object is not callable", - "markdown": "'MinervaModel' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/siamese.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 205, - "startColumn": 35, - "charOffset": 8400, - "charLength": 16, - "snippet": { - "text": "self.backbone(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 203, - "startColumn": 1, - "charOffset": 8247, - "charLength": 225, - "snippet": { - "text": " :attr:`~SimCLR.proj_head` and the detached embedding vector from the :attr:`~SimCLR.backbone`.\n \"\"\"\n f: Tensor = torch.flatten(self.backbone(x)[0], start_dim=1)\n g: Tensor = self.proj_head(f)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "58f4dd0802f21949ca466a580bca8b85d0a8a0161d3f92e7889c275a2256c515" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'MinervaModel' object is not callable", - "markdown": "'MinervaModel' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 424, - "startColumn": 30, - "charOffset": 16362, - "charLength": 16, - "snippet": { - "text": "self.backbone(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 422, - "startColumn": 1, - "charOffset": 16256, - "charLength": 182, - "snippet": { - "text": " \"\"\"\n # Output tensors from the residual blocks of the resnet.\n x4, x3, x2, x1, x0 = self.backbone(x)\n\n # Concats and upsamples the outputs of the resnet." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "709fffd3eb539717db9da87f2252888a58796d8a570f4426017061193319f525" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 429, - "startColumn": 13, - "charOffset": 16508, - "charLength": 15, - "snippet": { - "text": "self.up3(x, x1)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 427, - "startColumn": 1, - "charOffset": 16439, - "charLength": 193, - "snippet": { - "text": " x = self.up1(x4, x3)\n x = self.up2(x, x2)\n x = self.up3(x, x1)\n\n # Add the upsampled and deconv tensor to the output of the input convolutional layer of the resnet." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c39bcc4eac07fa5be31a5a11c2e704a28f811eb2b1b764498e1ea09321c4a29f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 309, - "startColumn": 13, - "charOffset": 11152, - "charLength": 16, - "snippet": { - "text": "self.up1(x5, x4)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 307, - "startColumn": 1, - "charOffset": 11111, - "charLength": 113, - "snippet": { - "text": " x5 = self.down4(x4)\n\n x = self.up1(x5, x4)\n x = self.up2(x, x3)\n x = self.up3(x, x2)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "d29e93ca2da1f0c64e309da75d884c11af7817ff50ffdee484067d575b7f8bde" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'OutConv' object is not callable", - "markdown": "'OutConv' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 440, - "startColumn": 26, - "charOffset": 16919, - "charLength": 12, - "snippet": { - "text": "self.outc(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 438, - "startColumn": 1, - "charOffset": 16808, - "charLength": 166, - "snippet": { - "text": "\n # Reduces the latent channels to the number of classes for the ouput tensor.\n logits: Tensor = self.outc(x)\n\n assert isinstance(logits, Tensor)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "d6edff456930d9ea6b9bc84ab152366e42ceb540838dedd5d583275cc9ef3d33" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'MinervaModel' object is not callable", - "markdown": "'MinervaModel' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/fcn.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 151, - "startColumn": 13, - "charOffset": 6769, - "charLength": 16, - "snippet": { - "text": "self.backbone(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 149, - "startColumn": 1, - "charOffset": 6689, - "charLength": 125, - "snippet": { - "text": " each pixel input ``x`` being of that class.\n \"\"\"\n z = self.backbone(x)\n z = self.decoder(z)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "db121cb249d30be27814564a42308ed2077ad10460c975599510489c634aee58" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Down' object is not callable", - "markdown": "'Down' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 306, - "startColumn": 14, - "charOffset": 11096, - "charLength": 14, - "snippet": { - "text": "self.down3(x3)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 304, - "startColumn": 1, - "charOffset": 11027, - "charLength": 112, - "snippet": { - "text": " x2 = self.down1(x1)\n x3 = self.down2(x2)\n x4 = self.down3(x3)\n x5 = self.down4(x4)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "df19ec32894eb48db2bf351124ea3f28443a9df187cb1f57b31d8f07dc64f956" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 428, - "startColumn": 13, - "charOffset": 16480, - "charLength": 15, - "snippet": { - "text": "self.up2(x, x2)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 426, - "startColumn": 1, - "charOffset": 16380, - "charLength": 144, - "snippet": { - "text": " # Concats and upsamples the outputs of the resnet.\n x = self.up1(x4, x3)\n x = self.up2(x, x2)\n x = self.up3(x, x1)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "edd8949249b4ff954ccacb43d845a8811386abd74838851febf3160a381cab40" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Up' object is not callable", - "markdown": "'Up' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 427, - "startColumn": 13, - "charOffset": 16451, - "charLength": 16, - "snippet": { - "text": "self.up1(x4, x3)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 425, - "startColumn": 1, - "charOffset": 16379, - "charLength": 144, - "snippet": { - "text": "\n # Concats and upsamples the outputs of the resnet.\n x = self.up1(x4, x3)\n x = self.up2(x, x2)\n x = self.up3(x, x1)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "eeb2adda823e89a8c681570e1e5d6566d3a72a5990da2c441e924af12994b11a" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyCallingNonCallableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'DoubleConv' object is not callable", - "markdown": "'DoubleConv' object is not callable" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 303, - "startColumn": 14, - "charOffset": 11015, - "charLength": 11, - "snippet": { - "text": "self.inc(x)" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 301, - "startColumn": 1, - "charOffset": 10989, - "charLength": 93, - "snippet": { - "text": " \"\"\"\n\n x1 = self.inc(x)\n x2 = self.down1(x1)\n x3 = self.down2(x2)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "fbd1c342346ff42318114b84df313d0fedf950c924a671057522c14aa4d58876" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyIncorrectDocstringInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Missing parameter cls in docstring", - "markdown": "Missing parameter cls in docstring" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 303, - "startColumn": 17, - "charOffset": 10758, - "charLength": 3, - "snippet": { - "text": "cls" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 301, - "startColumn": 1, - "charOffset": 10740, - "charLength": 182, - "snippet": { - "text": "\n\ndef tg_to_torch(cls, keys: Optional[Sequence[str]] = None):\n \"\"\"Ensures wrapped transform can handle both :class:`~torch.Tensor` and :mod:`torchgeo` style :class:`dict` inputs.\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8f20ea2c64e63a5d997c22f139e2a79159327a2890354344a12b4194164fe8d0" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyIncorrectDocstringInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Missing parameter _testing in docstring", - "markdown": "Missing parameter _testing in docstring" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1648, - "startColumn": 5, - "charOffset": 57090, - "charLength": 22, - "snippet": { - "text": "_testing: bool = False" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1646, - "startColumn": 1, - "charOffset": 57021, - "charLength": 182, - "snippet": { - "text": " env_name: str = \"env\",\n host_num: Union[str, int] = 6006,\n _testing: bool = False,\n) -> Optional[int]:\n \"\"\"Runs the :mod:`TensorBoard` logs and hosts on a local webpage." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "ecc48a2ba0d041faaba2b7cbd6a334047d3a874d7b346ea1487866137449397c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "CamelCase variable imported as constant", - "markdown": "CamelCase variable imported as constant" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 50, - "startColumn": 58, - "charOffset": 2439, - "charLength": 3, - "snippet": { - "text": "DDP" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 48, - "startColumn": 1, - "charOffset": 2293, - "charLength": 188, - "snippet": { - "text": "from inputimeout import TimeoutOccurred, inputimeout\nfrom torch.nn.modules import Module\nfrom torch.nn.parallel import DistributedDataParallel as DDP\n\nif TYPE_CHECKING: # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "61309292db3ee6fe81a69b91a9fa4dbe99cb27784f7083f58845873760156a62" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Lowercase variable imported as non-lowercase", - "markdown": "Lowercase variable imported as non-lowercase" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/unet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 57, - "startColumn": 31, - "charOffset": 2346, - "charLength": 1, - "snippet": { - "text": "F" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 55, - "startColumn": 1, - "charOffset": 2302, - "charLength": 100, - "snippet": { - "text": "\nimport torch\nimport torch.nn.functional as F\nimport torch.nn.modules as nn\nfrom torch import Tensor" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8fd630246011f5a0c017663c439dbc7f6e1a7453b09421c90330187aa0484199" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyPep8NamingInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Lowercase variable imported as non-lowercase", - "markdown": "Lowercase variable imported as non-lowercase" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 168, - "startColumn": 36, - "charOffset": 5971, - "charLength": 1, - "snippet": { - "text": "F" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 166, - "startColumn": 1, - "charOffset": 5869, - "charLength": 171, - "snippet": { - "text": "from tabulate import tabulate\nfrom torch import LongTensor, Tensor\nfrom torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c9821a4400d8da88d2822ddc6d87338c1d2f2c52820fc45717d148bb349686f8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 468, - "startColumn": 19, - "charOffset": 23647, - "charLength": 22, - "snippet": { - "text": "utils._optional_import" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 466, - "startColumn": 1, - "charOffset": 23591, - "charLength": 133, - "snippet": { - "text": " package=\"onnx\",\n )\n convert = utils._optional_import(\n \"onnx2torch\",\n name=\"convert\"," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0349e9710547309113fb65590b35837ba470f08228b62165be7fc8f5adc261b6" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _api of a class", - "markdown": "Access to a protected member _api of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/resnet.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 55, - "startColumn": 6, - "charOffset": 2352, - "charLength": 23, - "snippet": { - "text": "torchvision.models._api" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 53, - "startColumn": 1, - "charOffset": 2286, - "charLength": 179, - "snippet": { - "text": "from torch import Tensor\nfrom torch.nn.modules import Module\nfrom torchvision.models._api import WeightsEnum\nfrom torchvision.models.resnet import BasicBlock, Bottleneck, conv1x1\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0472c2c74b7833a451026d4b481a6631f9280b669e00a4f94029b634e200a889" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 78, - "startColumn": 26, - "charOffset": 3467, - "charLength": 22, - "snippet": { - "text": "utils._optional_import" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 76, - "startColumn": 1, - "charOffset": 3388, - "charLength": 174, - "snippet": { - "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "220477eebf686f2e357a93574f4dc131e22d41a7e23cec1c45ac8cd72cd904ab" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _device of a class", - "markdown": "Access to a protected member _device of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 170, - "startColumn": 25, - "charOffset": 6033, - "charLength": 7, - "snippet": { - "text": "_device" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 168, - "startColumn": 1, - "charOffset": 5936, - "charLength": 202, - "snippet": { - "text": "from torch.nn import functional as F\nfrom torch.nn.modules import Module\nfrom torch.types import _device\nfrom torchgeo.datasets.utils import BoundingBox\nfrom urllib3.exceptions import NewConnectionError" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "358613aa9ea51d004c3d7b4cf758a94fb478784a99aa8c3068caa4d491dfb13c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _print_banner of a module", - "markdown": "Access to a protected member _print_banner of a module" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/MinervaExp.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 84, - "startColumn": 5, - "charOffset": 3249, - "charLength": 19, - "snippet": { - "text": "utils._print_banner" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 82, - "startColumn": 1, - "charOffset": 3216, - "charLength": 97, - "snippet": { - "text": "\n # Print Minerva banner.\n utils._print_banner()\n\n with runner.WandbConnectionManager():" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6164e8df1c5babd87fb4edb7e111aede2178ed7ff0f793fa8712c350d3b268e4" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _api of a class", - "markdown": "Access to a protected member _api of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/core.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 74, - "startColumn": 6, - "charOffset": 2705, - "charLength": 23, - "snippet": { - "text": "torchvision.models._api" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 72, - "startColumn": 1, - "charOffset": 2598, - "charLength": 194, - "snippet": { - "text": "from torch.nn.parallel import DataParallel, DistributedDataParallel\nfrom torch.optim import Optimizer\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.utils.utils import func_by_str" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8b51e20bf8f917d419736322b28dabc097341417ece59c6496a2e5c02233c33f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _to_tuple of a class", - "markdown": "Access to a protected member _to_tuple of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/samplers.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 51, - "startColumn": 37, - "charOffset": 2452, - "charLength": 9, - "snippet": { - "text": "_to_tuple" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 49, - "startColumn": 1, - "charOffset": 2297, - "charLength": 222, - "snippet": { - "text": "from torchgeo.datasets.utils import BoundingBox\nfrom torchgeo.samplers import BatchGeoSampler, RandomGeoSampler, Units\nfrom torchgeo.samplers.utils import _to_tuple, get_random_bounding_box\n\nfrom minerva.utils import utils" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b2c2959ec4e8ff08e68ad8c76689f48f42da52cfabcc7c68f67f75d05cd40b9f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 463, - "startColumn": 21, - "charOffset": 23522, - "charLength": 22, - "snippet": { - "text": "utils._optional_import" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 461, - "startColumn": 1, - "charOffset": 23436, - "charLength": 154, - "snippet": { - "text": " MinervaModel: Loaded model ready for use.\n \"\"\"\n onnx_load = utils._optional_import(\n \"onnx\",\n name=\"load\"," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "cc57de3a4fc5dd2a258e7a94baeb7a63d0083b96e9832dfda42e397fd373b3e8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _api of a class", - "markdown": "Access to a protected member _api of a class" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/TorchWeightDownloader.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 41, - "startColumn": 6, - "charOffset": 1766, - "charLength": 23, - "snippet": { - "text": "torchvision.models._api" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 39, - "startColumn": 1, - "charOffset": 1732, - "charLength": 122, - "snippet": { - "text": "from typing import Optional\n\nfrom torchvision.models._api import WeightsEnum\n\nfrom minerva.models import get_torch_weights" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e1858e4087549f5d60c37a7259b7e8301a75bb755f8fc63ba58a31bb4d092d6b" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyProtectedMemberInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Access to a protected member _optional_import of a module", - "markdown": "Access to a protected member _optional_import of a module" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/logger/steplog.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 85, - "startColumn": 26, - "charOffset": 3307, - "charLength": 22, - "snippet": { - "text": "utils._optional_import" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 83, - "startColumn": 1, - "charOffset": 3228, - "charLength": 174, - "snippet": { - "text": "TENSORBOARD_WRITER: Optional[Callable[..., Any]]\ntry:\n TENSORBOARD_WRITER = utils._optional_import(\n \"torch.utils.tensorboard.writer\",\n name=\"SummaryWriter\"," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e9a177ffdac094aa30ddf0bec186799e43e246ed7166c521f50ba49712687c28" - }, - "baselineState": "new", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared 'step' defined above without usage", - "markdown": "Redeclared 'step' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/core.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 168, - "startColumn": 9, - "charOffset": 6547, - "charLength": 4, - "snippet": { - "text": "step" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 166, - "startColumn": 1, - "charOffset": 6506, - "charLength": 79, - "snippet": { - "text": " ... # pragma: no cover\n\n def step(\n self,\n x: Tensor," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "08c240f31814bdcdc137428c4ade3faa0078881a4d4e76f8dad5504c8db774ac" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared 'mask_transform' defined above without usage", - "markdown": "Redeclared 'mask_transform' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1143, - "startColumn": 5, - "charOffset": 38548, - "charLength": 14, - "snippet": { - "text": "mask_transform" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1141, - "startColumn": 1, - "charOffset": 38542, - "charLength": 98, - "snippet": { - "text": "\n\ndef mask_transform(\n array: Union[NDArray[Any, Int], LongTensor],\n matrix: Dict[int, int]," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "1fecd676ba08b11a2c6e99fc0980bee6d0bbada5926f4cc8cb3b7b7496f3458f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared 'transform_coordinates' defined above without usage", - "markdown": "Redeclared 'transform_coordinates' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 709, - "startColumn": 5, - "charOffset": 22699, - "charLength": 21, - "snippet": { - "text": "transform_coordinates" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 707, - "startColumn": 1, - "charOffset": 22693, - "charLength": 104, - "snippet": { - "text": "\n\ndef transform_coordinates(\n x: Union[Sequence[float], float],\n y: Union[Sequence[float], float]," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7cb06c2202498c1088fc2cfd03472ebfd9a00f67026ce05e55aa13a73ca90885" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared '__init__' defined above without usage", - "markdown": "Redeclared '__init__' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/paired.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 95, - "startColumn": 9, - "charOffset": 3968, - "charLength": 8, - "snippet": { - "text": "__init__" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 93, - "startColumn": 1, - "charOffset": 3927, - "charLength": 127, - "snippet": { - "text": " ... # pragma: no cover\n\n def __init__(\n self,\n dataset: Union[Callable[..., GeoDataset], GeoDataset]," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a00682d1db8abcf9858e9e8ff6058bc3c35d337bdcb30e738edfe1cff9c1091f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared '__call__' defined above without usage", - "markdown": "Redeclared '__call__' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 337, - "startColumn": 13, - "charOffset": 12000, - "charLength": 8, - "snippet": { - "text": "__call__" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 335, - "startColumn": 1, - "charOffset": 11951, - "charLength": 202, - "snippet": { - "text": " ... # pragma: no cover\n\n def __call__(self, batch: Union[Dict[str, Any], Tensor]) -> Dict[str, Any]:\n if isinstance(batch, Tensor):\n return self.wrap(batch)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b9030b8d90b23ca06f2e5f3a19e314f37e4efe03209eae54395987d450b4dd59" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared '_optional_import' defined above without usage", - "markdown": "Redeclared '_optional_import' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 468, - "startColumn": 5, - "charOffset": 15571, - "charLength": 16, - "snippet": { - "text": "_optional_import" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 466, - "startColumn": 1, - "charOffset": 15565, - "charLength": 145, - "snippet": { - "text": "\n\ndef _optional_import(\n module: str, *, name: Optional[str] = None, package: Optional[str] = None\n) -> Union[ModuleType, Callable[..., Any]]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c50875a96215277454107f37d08aa0b7cb99f53a51a16e33b5f100410984e723" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyRedeclarationInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Redeclared '__call__' defined above without usage", - "markdown": "Redeclared '__call__' defined above without usage" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 491, - "startColumn": 9, - "charOffset": 17125, - "charLength": 8, - "snippet": { - "text": "__call__" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 489, - "startColumn": 1, - "charOffset": 17084, - "charLength": 142, - "snippet": { - "text": " ... # pragma: no cover\n\n def __call__(\n self, sample: Union[Tensor, Dict[str, Any]]\n ) -> Union[Tensor, Dict[str, Any]]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "d593716f8b2680b54c5d806f5ab4c7351c2a7b480dc3b449711dc4d5dba05408" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyShadowingNamesInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Shadows name 'transform_params' from outer scope", - "markdown": "Shadows name 'transform_params' from outer scope" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 716, - "startColumn": 13, - "charOffset": 25555, - "charLength": 16, - "snippet": { - "text": "transform_params" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 714, - "startColumn": 1, - "charOffset": 25529, - "charLength": 213, - "snippet": { - "text": "\n Example:\n >>> transform_params = {\n >>> \"CenterCrop\": {\"module\": \"torchvision.transforms\", \"size\": 128},\n >>> \"RandomHorizontalFlip\": {\"module\": \"torchvision.transforms\", \"p\": 0.7}" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5d191e4788335efc4f0b23e3edc3ef7e567f0837bdb4be55c7f5f598bbf38e2a" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyShadowingNamesInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Shadows name 'name' from outer scope", - "markdown": "Shadows name 'name' from outer scope" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 683, - "startColumn": 13, - "charOffset": 24218, - "charLength": 4, - "snippet": { - "text": "name" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 681, - "startColumn": 1, - "charOffset": 24192, - "charLength": 175, - "snippet": { - "text": "\n Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7f4f024ca4fd5e9fdcd319c015fe15bed5a26395c1cc94eff00b59e4632e74ab" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyShadowingNamesInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Shadows name 'transform' from outer scope", - "markdown": "Shadows name 'transform' from outer scope" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 685, - "startColumn": 13, - "charOffset": 24328, - "charLength": 9, - "snippet": { - "text": "transform" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 683, - "startColumn": 1, - "charOffset": 24206, - "charLength": 174, - "snippet": { - "text": " >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n\n Raises:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "d9f46f829599ac3e9053a875980a65bd188091c26d51bcc2d14eba71bfe81480" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyShadowingNamesInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Shadows name 'err' from outer scope", - "markdown": "Shadows name 'err' from outer scope" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/trainer.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 358, - "startColumn": 44, - "charOffset": 19450, - "charLength": 3, - "snippet": { - "text": "err" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 356, - "startColumn": 1, - "charOffset": 19293, - "charLength": 278, - "snippet": { - "text": " input_to_model=torch.rand(*input_size, device=self.device),\n )\n except RuntimeError as err: # pragma: no cover\n print(err)\n print(\"ABORT adding graph to writer\")" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "df986ba126c6307961f1dee6d13c08fa37ee1914f2e018cbb8e41c70fb4acc77" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyShadowingNamesInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Shadows name 'params' from outer scope", - "markdown": "Shadows name 'params' from outer scope" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 684, - "startColumn": 13, - "charOffset": 24257, - "charLength": 6, - "snippet": { - "text": "params" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 682, - "startColumn": 1, - "charOffset": 24193, - "charLength": 175, - "snippet": { - "text": " Example:\n >>> name = \"RandomResizedCrop\"\n >>> params = {\"module\": \"torchvision.transforms\", \"size\": 128}\n >>> transform = get_transform(name, params)\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "fee3860681fcdc20774c711da4a5c00a144128b6fbd1d3f3cc96af41216afb4a" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyTypeHintsInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/factory.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 134, - "startColumn": 41, - "charOffset": 5793, - "charLength": 8, - "snippet": { - "text": "\"params\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 132, - "startColumn": 1, - "charOffset": 5661, - "charLength": 221, - "snippet": { - "text": " dataset_class: Callable[..., GeoDataset],\n paths: Union[str, Iterable[str]],\n subdataset_params: Dict[Literal[\"params\"], Dict[str, Any]],\n _transformations: Optional[Any],\n ) -> GeoDataset:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "11ea8b82ea3e295e1035d00a8abc2ea947c0c1de5462c2ba54a8ff716fb26f4b" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyTypeHintsInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/fcn.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 97, - "startColumn": 30, - "charOffset": 4620, - "charLength": 15, - "snippet": { - "text": "\"32\", \"16\", \"8\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 95, - "startColumn": 1, - "charOffset": 4554, - "charLength": 108, - "snippet": { - "text": "\n backbone_name: str = \"ResNet18\"\n decoder_variant: Literal[\"32\", \"16\", \"8\"] = \"32\"\n\n def __init__(" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2ed1d866d5dc3cc75fe869d8c8ea49dff49475d2a419726cad763c145bf34970" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyTypeHintsInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/fcn.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 205, - "startColumn": 31, - "charOffset": 9905, - "charLength": 15, - "snippet": { - "text": "\"32\", \"16\", \"8\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 203, - "startColumn": 1, - "charOffset": 9805, - "charLength": 170, - "snippet": { - "text": " ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)\n self.variant: Literal[\"32\", \"16\", \"8\"] = variant\n\n assert type(self.n_classes) is int" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "52dbedae57240155661b7fedbef3b3e41329c899cf5cc6acdc8f005e9b6ba49e" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyTypeHintsInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/fcn.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 202, - "startColumn": 26, - "charOffset": 9780, - "charLength": 15, - "snippet": { - "text": "\"32\", \"16\", \"8\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 200, - "startColumn": 1, - "charOffset": 9695, - "charLength": 179, - "snippet": { - "text": " in_channel: int = 512,\n n_classes: int = 21,\n variant: Literal[\"32\", \"16\", \"8\"] = \"32\",\n ) -> None:\n super(DCN, self).__init__(n_classes=n_classes)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5b5e41b16a5159a0fe9b280d34b360c02051b9d096ba831c6b6f961a4e2a0b17" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyTypeHintsInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types", - "markdown": "'Literal' may be parameterized with literal ints, byte and unicode strings, bools, Enum values, None, other literal types, or type aliases to other literal types" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/transforms.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 704, - "startColumn": 53, - "charOffset": 24978, - "charLength": 5, - "snippet": { - "text": "False" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 702, - "startColumn": 1, - "charOffset": 24899, - "charLength": 217, - "snippet": { - "text": "\ndef make_transformations(\n transform_params: Union[Dict[str, Any], Literal[False]], key: Optional[str] = None\n) -> Optional[Any]:\n \"\"\"Constructs a transform or series of transforms based on parameters provided." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5c14208f93acb01973367275b33371a643e9a93d4e4c6df1f18a4cd57d9443fb" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnboundLocalVariableInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "Local variable 'exit_code' might be referenced before assignment", - "markdown": "Local variable 'exit_code' might be referenced before assignment" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/MinervaPipe.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 70, - "startColumn": 22, - "charOffset": 2859, - "charLength": 9, - "snippet": { - "text": "exit_code" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 68, - "startColumn": 1, - "charOffset": 2758, - "charLength": 143, - "snippet": { - "text": " print(err)\n print(f\"Error in {key} experiment -> ABORT\")\n sys.exit(exit_code) # type: ignore\n\n print(" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "59d72ba075e94cd3afb2368d96297a36606c76a4537d2a5da1e1385e0efeb9fa" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 463, - "startColumn": 5, - "charOffset": 15506, - "charLength": 12, - "snippet": { - "text": "package: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 461, - "startColumn": 1, - "charOffset": 15478, - "charLength": 86, - "snippet": { - "text": " module: str,\n *,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0ccb2b1ad737ad1a758e57d541cc964c386f300d3cb018304f0051e581f3a63d" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 704, - "startColumn": 15, - "charOffset": 22594, - "charLength": 8, - "snippet": { - "text": "y: float" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 702, - "startColumn": 1, - "charOffset": 22543, - "charLength": 149, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0e6d691a6fcc89de66729c329c83c134a5693f62dddd79e565952d51bb9c6c52" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 412, - "startColumn": 5, - "charOffset": 14792, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 410, - "startColumn": 1, - "charOffset": 14756, - "charLength": 71, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "25f9601039ddbd9925e1890f8f020fa9da57541f24df7424645dfd44944fb3a6" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'matrix' value is not used", - "markdown": "Parameter 'matrix' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1133, - "startColumn": 31, - "charOffset": 38350, - "charLength": 22, - "snippet": { - "text": "matrix: Dict[int, int]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1131, - "startColumn": 1, - "charOffset": 38290, - "charLength": 134, - "snippet": { - "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2c0301eb97cfa9d99d4574a6dd2bac6f52e5ace5f2f4ade1fdfe86ac64ed16ff" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'signum' value is not used", - "markdown": "Parameter 'signum' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/runner.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 335, - "startColumn": 21, - "charOffset": 10550, - "charLength": 6, - "snippet": { - "text": "signum" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 333, - "startColumn": 1, - "charOffset": 10528, - "charLength": 75, - "snippet": { - "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "32baad8869101a640b5894c953f3344efbcd7fa51518461329717f9aa28d02bb" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 675, - "startColumn": 5, - "charOffset": 22013, - "charLength": 18, - "snippet": { - "text": "y: Sequence[float]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 673, - "startColumn": 1, - "charOffset": 21958, - "charLength": 118, - "snippet": { - "text": "def transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "378efc50864fec16c13df7d0a2f9a5ccdd6bdb21750ed5b75b843ad371926c31" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'dataset' value is not used", - "markdown": "Parameter 'dataset' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/paired.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 88, - "startColumn": 24, - "charOffset": 3748, - "charLength": 34, - "snippet": { - "text": "dataset: Callable[..., GeoDataset]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 86, - "startColumn": 1, - "charOffset": 3710, - "charLength": 132, - "snippet": { - "text": "\n @overload\n def __init__(self, dataset: Callable[..., GeoDataset], *args, **kwargs) -> None:\n ... # pragma: no cover\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "47bc364dfb4accd24c034021659be26811e1262ebfd7c2a6b1956455712c66f5" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Local variable 'auto_norm' value is not used", - "markdown": "Local variable 'auto_norm' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/factory.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 247, - "startColumn": 21, - "charOffset": 10517, - "charLength": 9, - "snippet": { - "text": "auto_norm" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 245, - "startColumn": 1, - "charOffset": 10454, - "charLength": 158, - "snippet": { - "text": "\n # Reset back to None.\n auto_norm = None\n else:\n raise TypeError( # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4840abd8e2d0d74c9efcab96a0ae80a1ff7baefc5e3c1a965c3422a9fff1e534" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'kwargs' value is not used", - "markdown": "Parameter 'kwargs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/logger/steplog.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 309, - "startColumn": 9, - "charOffset": 11940, - "charLength": 8, - "snippet": { - "text": "**kwargs" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 307, - "startColumn": 1, - "charOffset": 11861, - "charLength": 158, - "snippet": { - "text": " model_type: str = \"\",\n n_classes: Optional[int] = None,\n **kwargs,\n ) -> None:\n super(SupervisedGeoStepLogger, self).__init__(" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "48c4e289e3b9406f5eb0bd9991c5f4a1a9e8e8253ac16ce7d4097513fa0a102e" - }, - "baselineState": "new", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'dataset' value is not used", - "markdown": "Parameter 'dataset' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/paired.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 92, - "startColumn": 24, - "charOffset": 3880, - "charLength": 19, - "snippet": { - "text": "dataset: GeoDataset" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 90, - "startColumn": 1, - "charOffset": 3842, - "charLength": 117, - "snippet": { - "text": "\n @overload\n def __init__(self, dataset: GeoDataset, *args, **kwargs) -> None:\n ... # pragma: no cover\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4dbb7b4295b76445852c21652ba823b131eef4603a391deda0c1ce06b14efc54" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'kwargs' value is not used", - "markdown": "Parameter 'kwargs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/modelio.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 191, - "startColumn": 5, - "charOffset": 7713, - "charLength": 8, - "snippet": { - "text": "**kwargs" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 189, - "startColumn": 1, - "charOffset": 7636, - "charLength": 271, - "snippet": { - "text": " device: torch.device, # type: ignore[name-defined]\n train: bool,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], None, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a self-supervised Siamese model using :mod:`torchgeo` datasets." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4f2f60dbc5f54eec99c2a5c005b0a83bd5dbfea5de68c38aa9830e3ec5a2cfd8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 452, - "startColumn": 5, - "charOffset": 15356, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 450, - "startColumn": 1, - "charOffset": 15320, - "charLength": 70, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5aba4ff84f223fa54030174f2039f4279ea51e6dfa9107ea49c9b1e94178d3bc" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'frame' value is not used", - "markdown": "Parameter 'frame' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/runner.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 327, - "startColumn": 29, - "charOffset": 10349, - "charLength": 5, - "snippet": { - "text": "frame" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 325, - "startColumn": 1, - "charOffset": 10139, - "charLength": 351, - "snippet": { - "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5c7339871121f24a4922b8c5b4e3ff15d2357395d48ccd376e5b072b5a637912" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 435, - "startColumn": 5, - "charOffset": 15113, - "charLength": 13, - "snippet": { - "text": "package: None" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 433, - "startColumn": 1, - "charOffset": 15086, - "charLength": 86, - "snippet": { - "text": " *,\n name: None,\n package: None,\n) -> ModuleType:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "64e64ee08f93e1d6dc03ae32174accc103bd1a6d8bc834280d08781d1c5844d6" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 696, - "startColumn": 5, - "charOffset": 22427, - "charLength": 12, - "snippet": { - "text": "src_crs: CRS" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 694, - "startColumn": 1, - "charOffset": 22385, - "charLength": 127, - "snippet": { - "text": " x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6a4ccae8c4b809a248742941055f326415e5b9091f2ec35d539946359b8d1583" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 694, - "startColumn": 5, - "charOffset": 22389, - "charLength": 8, - "snippet": { - "text": "x: float" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 692, - "startColumn": 1, - "charOffset": 22348, - "charLength": 92, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6bb85e879cb7d60a2ab29a04efbd6c09120fcc354cbe3806eff5db51587b5805" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 677, - "startColumn": 5, - "charOffset": 22055, - "charLength": 20, - "snippet": { - "text": "new_crs: CRS = WGS84" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 675, - "startColumn": 1, - "charOffset": 22009, - "charLength": 141, - "snippet": { - "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6d5f1aafce9ce228179668bc91ba7209fe1876a8e6ff85defe0262939f2ea8fc" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 704, - "startColumn": 39, - "charOffset": 22618, - "charLength": 20, - "snippet": { - "text": "new_crs: CRS = WGS84" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 702, - "startColumn": 1, - "charOffset": 22543, - "charLength": 149, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "786127917f20d41dcba824f94644007d75294845ce04d30ec72a139f746583b1" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 425, - "startColumn": 5, - "charOffset": 14968, - "charLength": 12, - "snippet": { - "text": "package: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 423, - "startColumn": 1, - "charOffset": 14942, - "charLength": 92, - "snippet": { - "text": " *,\n name: str,\n package: str,\n) -> Callable[..., Any]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7cab6aa90bcc70bffd0fbc103039845e944e948b238656f65792d6666ee38fa0" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 461, - "startColumn": 5, - "charOffset": 15482, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 459, - "startColumn": 1, - "charOffset": 15446, - "charLength": 73, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n package: str," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7e08346269a9a6f80d28500b3907d0c8c1f42af9ea787557d4554e7ae9aa7a22" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 432, - "startColumn": 5, - "charOffset": 15073, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 430, - "startColumn": 1, - "charOffset": 15037, - "charLength": 71, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: None," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7ecf619bafd6e12ee257c28bfceb77e07d3124647dec0022081b57262419975b" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 434, - "startColumn": 5, - "charOffset": 15097, - "charLength": 10, - "snippet": { - "text": "name: None" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 432, - "startColumn": 1, - "charOffset": 15069, - "charLength": 75, - "snippet": { - "text": " module: str,\n *,\n name: None,\n package: None,\n) -> ModuleType:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "85cb9a5f41c2c05067d30c19294bb17c22a4ce96cc3f9221ae0fe0b16fa2a0cc" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 422, - "startColumn": 5, - "charOffset": 14929, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 420, - "startColumn": 1, - "charOffset": 14893, - "charLength": 70, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8a686852cb451c1739e933ccc39d7c61a5c1da48ef83544d116dc9574e999033" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'signum' value is not used", - "markdown": "Parameter 'signum' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/runner.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 327, - "startColumn": 21, - "charOffset": 10341, - "charLength": 6, - "snippet": { - "text": "signum" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 325, - "startColumn": 1, - "charOffset": 10139, - "charLength": 351, - "snippet": { - "text": "# METHODS\n# =====================================================================================================================\ndef _handle_sigusr1(signum, frame) -> None: # pragma: no cover\n subprocess.Popen( # nosec B602\n shlex.split(f'scontrol requeue {os.getenv(\"SLURM_JOB_ID\")}')," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8add16ba65f135bd2af3a910af293b125373b67d97709a4db09b45bb17a9efce" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Local variable 'weights' value is not used", - "markdown": "Local variable 'weights' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/core.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 410, - "startColumn": 5, - "charOffset": 15448, - "charLength": 7, - "snippet": { - "text": "weights" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 408, - "startColumn": 1, - "charOffset": 15317, - "charLength": 261, - "snippet": { - "text": " :meth:`~torchvision.models._api.WeightsEnum.get_state_dict` to download the weights (if not already in cache).\n \"\"\"\n weights: Optional[WeightsEnum] = None\n try:\n weights = torch.hub.load(\"pytorch/vision\", \"get_weight\", name=weights_name)" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "9e026761be74f2e19e5bc01b1b687b5e85b4c6764f9bed0c686eb9df81c080e6" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'kwargs' value is not used", - "markdown": "Parameter 'kwargs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/modelio.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 61, - "startColumn": 5, - "charOffset": 2784, - "charLength": 8, - "snippet": { - "text": "**kwargs" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 59, - "startColumn": 1, - "charOffset": 2707, - "charLength": 260, - "snippet": { - "text": " device: torch.device, # type: ignore[name-defined]\n train: bool,\n **kwargs,\n) -> Tuple[Tensor, Union[Tensor, Tuple[Tensor, ...]], Tensor, Sequence[BoundingBox]]:\n \"\"\"Provides IO functionality for a supervised model using :mod:`torchgeo` datasets." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a0c91bcdf4f3702bccef1c710b61a66f3ee5375d230aff5117e4d8e97a25a84a" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 454, - "startColumn": 5, - "charOffset": 15380, - "charLength": 9, - "snippet": { - "text": "name: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 452, - "startColumn": 1, - "charOffset": 15352, - "charLength": 91, - "snippet": { - "text": " module: str,\n *,\n name: str,\n) -> Callable[..., Any]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a548ae33426bea46235ff7f5a73418dbc2c9284d10ce4de5509d4efdd757ddd3" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 444, - "startColumn": 5, - "charOffset": 15235, - "charLength": 9, - "snippet": { - "text": "name: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 442, - "startColumn": 1, - "charOffset": 15207, - "charLength": 82, - "snippet": { - "text": " module: str,\n *,\n name: str,\n package: None,\n) -> Callable[..., Any]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a83b11a3bab18108d41eab9010628a01f46a4845c006af930bdf803b5743a9d8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 686, - "startColumn": 5, - "charOffset": 22232, - "charLength": 12, - "snippet": { - "text": "src_crs: CRS" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 684, - "startColumn": 1, - "charOffset": 22190, - "charLength": 127, - "snippet": { - "text": " x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "aa450f73f32b590538897e881ae65fb2cca39a91f2d0bf197ff975eddfb2c919" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'frame' value is not used", - "markdown": "Parameter 'frame' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/runner.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 335, - "startColumn": 29, - "charOffset": 10558, - "charLength": 5, - "snippet": { - "text": "frame" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 333, - "startColumn": 1, - "charOffset": 10528, - "charLength": 75, - "snippet": { - "text": "\n\ndef _handle_sigterm(signum, frame) -> None: # pragma: no cover\n pass\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "aac2d2995f82d30eceaaf4fdc987bcf42180f54116528d862084b4b6e065026c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 695, - "startColumn": 5, - "charOffset": 22403, - "charLength": 18, - "snippet": { - "text": "y: Sequence[float]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 693, - "startColumn": 1, - "charOffset": 22358, - "charLength": 108, - "snippet": { - "text": "def transform_coordinates(\n x: float,\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "af0e634ac1edfffe767615c2dd7397f4860f73adb7173e6992aa3cc89b33e635" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'y' value is not used", - "markdown": "Parameter 'y' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 685, - "startColumn": 5, - "charOffset": 22218, - "charLength": 8, - "snippet": { - "text": "y: float" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 683, - "startColumn": 1, - "charOffset": 22163, - "charLength": 108, - "snippet": { - "text": "def transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b118ec1d809147828b5577498d5200f9457b7148502a603aa5b6f32b721bb7f2" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 687, - "startColumn": 5, - "charOffset": 22250, - "charLength": 20, - "snippet": { - "text": "new_crs: CRS = WGS84" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 685, - "startColumn": 1, - "charOffset": 22214, - "charLength": 131, - "snippet": { - "text": " y: float,\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b26014ed1202aeb4cb4c62f63adc833bc07058f9547863429b4c19ce8f28d9dd" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 676, - "startColumn": 5, - "charOffset": 22037, - "charLength": 12, - "snippet": { - "text": "src_crs: CRS" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 674, - "startColumn": 1, - "charOffset": 21985, - "charLength": 137, - "snippet": { - "text": " x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b577bce01690db5f522ed23e521b31264aa8ce1b7017842fb92a5d6d69187309" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'matrix' value is not used", - "markdown": "Parameter 'matrix' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1139, - "startColumn": 39, - "charOffset": 38475, - "charLength": 22, - "snippet": { - "text": "matrix: Dict[int, int]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1137, - "startColumn": 1, - "charOffset": 38426, - "charLength": 116, - "snippet": { - "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b86ca79c588e33e10834bcabf19dad1d48702078ec339d918fa72f67054b9b00" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'module' value is not used", - "markdown": "Parameter 'module' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 442, - "startColumn": 5, - "charOffset": 15211, - "charLength": 11, - "snippet": { - "text": "module: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 440, - "startColumn": 1, - "charOffset": 15175, - "charLength": 70, - "snippet": { - "text": "@overload\ndef _optional_import(\n module: str,\n *,\n name: str," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b8c0735d7a73f2f52fb58c58561c19d7bedcc10bc205009f8560f27522edbed6" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 424, - "startColumn": 5, - "charOffset": 14953, - "charLength": 9, - "snippet": { - "text": "name: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 422, - "startColumn": 1, - "charOffset": 14925, - "charLength": 81, - "snippet": { - "text": " module: str,\n *,\n name: str,\n package: str,\n) -> Callable[..., Any]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c3c9bca9d8a2a236385bce82494a4d9ececc296c46a83681e867653e0fa2d2d3" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'new_crs' value is not used", - "markdown": "Parameter 'new_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 697, - "startColumn": 5, - "charOffset": 22445, - "charLength": 20, - "snippet": { - "text": "new_crs: CRS = WGS84" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 695, - "startColumn": 1, - "charOffset": 22399, - "charLength": 141, - "snippet": { - "text": " y: Sequence[float],\n src_crs: CRS,\n new_crs: CRS = WGS84,\n) -> Tuple[Sequence[float], Sequence[float]]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "dd749fc39b4e3f4355f3b0b3e77e7dbf05735bb21a0d1b6fc102220760c5a6c9" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'name' value is not used", - "markdown": "Parameter 'name' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 414, - "startColumn": 5, - "charOffset": 14816, - "charLength": 10, - "snippet": { - "text": "name: None" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 412, - "startColumn": 1, - "charOffset": 14788, - "charLength": 74, - "snippet": { - "text": " module: str,\n *,\n name: None,\n package: str,\n) -> ModuleType:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "df2541a088a6fbc804c8254ef2696dcbba28bb4ccd938552c25289fe6c8f825a" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'src_crs' value is not used", - "markdown": "Parameter 'src_crs' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 704, - "startColumn": 25, - "charOffset": 22604, - "charLength": 12, - "snippet": { - "text": "src_crs: CRS" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 702, - "startColumn": 1, - "charOffset": 22543, - "charLength": 149, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e4bc34f0ae2bf9fe1a5a2b83bbab61fd3c30dbe93397efd612fdde9299b609d8" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 445, - "startColumn": 5, - "charOffset": 15250, - "charLength": 13, - "snippet": { - "text": "package: None" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 443, - "startColumn": 1, - "charOffset": 15224, - "charLength": 93, - "snippet": { - "text": " *,\n name: str,\n package: None,\n) -> Callable[..., Any]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e732c0177eb72bea99131b565c9d4cad8309cc57ede7e421db666e551eb62d13" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'array' value is not used", - "markdown": "Parameter 'array' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1139, - "startColumn": 20, - "charOffset": 38456, - "charLength": 17, - "snippet": { - "text": "array: LongTensor" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1137, - "startColumn": 1, - "charOffset": 38426, - "charLength": 116, - "snippet": { - "text": "\n@overload\ndef mask_transform(array: LongTensor, matrix: Dict[int, int]) -> LongTensor:\n ... # pragma: no cover\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e7b5cecf2d3557712dbe2b5787dc4c9520d2860c143458550263a68cfe27f3c7" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 704, - "startColumn": 5, - "charOffset": 22584, - "charLength": 8, - "snippet": { - "text": "x: float" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 702, - "startColumn": 1, - "charOffset": 22543, - "charLength": 149, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: float, y: float, src_crs: CRS, new_crs: CRS = WGS84\n) -> Tuple[float, float]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "ed2df92b1da501c28d0aace7fadd5d3c3a6593d93977e6333ce6c377545bbc87" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'array' value is not used", - "markdown": "Parameter 'array' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1133, - "startColumn": 5, - "charOffset": 38324, - "charLength": 24, - "snippet": { - "text": "array: NDArray[Any, Int]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1131, - "startColumn": 1, - "charOffset": 38290, - "charLength": 134, - "snippet": { - "text": "@overload\ndef mask_transform(\n array: NDArray[Any, Int], matrix: Dict[int, int]\n) -> NDArray[Any, Int]:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "efa3c5fd8da16b2c8b794c8033ebb3602585732758cd8f67c42f2e90a826708c" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'package' value is not used", - "markdown": "Parameter 'package' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 415, - "startColumn": 5, - "charOffset": 14832, - "charLength": 12, - "snippet": { - "text": "package: str" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 413, - "startColumn": 1, - "charOffset": 14805, - "charLength": 85, - "snippet": { - "text": " *,\n name: None,\n package: str,\n) -> ModuleType:\n ... # pragma: no cover" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "f7d794e4a4f3e2d8cd92c3ca2137781714e71604d396464db16d7dfc0843690f" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 684, - "startColumn": 5, - "charOffset": 22194, - "charLength": 18, - "snippet": { - "text": "x: Sequence[float]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 682, - "startColumn": 1, - "charOffset": 22153, - "charLength": 92, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: float,\n src_crs: CRS," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "f83215cf4705664e835d8d9fde8ae1284013127cfebaef1990341b6fed675bb4" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - }, - { - "ruleId": "PyUnusedLocalInspection", - "kind": "fail", - "level": "note", - "message": { - "text": "Parameter 'x' value is not used", - "markdown": "Parameter 'x' value is not used" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 674, - "startColumn": 5, - "charOffset": 21989, - "charLength": 18, - "snippet": { - "text": "x: Sequence[float]" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 672, - "startColumn": 1, - "charOffset": 21948, - "charLength": 102, - "snippet": { - "text": "@overload\ndef transform_coordinates(\n x: Sequence[float],\n y: Sequence[float],\n src_crs: CRS," - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "f9a05a4244e1f0d968ad07f3fb3e2c2fd2d73392a80bf588249185bd133e879d" - }, - "baselineState": "unchanged", - "properties": { - "ideaSeverity": "WEAK WARNING", - "qodanaSeverity": "Moderate", - "tags": [ - "Python" - ] - } - } - ], - "automationDetails": { - "id": "project/qodana/2023-10-15", - "guid": "8bb680b6-435c-4c0d-8314-313e1ae2ab67", - "properties": { - "jobUrl": "" - } - }, - "newlineSequences": [ - "\r\n", - "\n" - ], - "properties": { - "qodana.sanity.results": [ - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "notebooks/Torchgeo_FCN_Demo.ipynb", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 17, - "snippet": { - "text": "{\n \"cells\": [\n {" - }, - "sourceLanguage": "JupyterPython" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 67, - "snippet": { - "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," - }, - "sourceLanguage": "Jupyter" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "042d0651789556a4ea7954680e6f2953e047138ee0cd895e14a63ebd2306efc5" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/TorchWeightDownloader.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0a3de853e0b5c7ff5bc742bb39b847b3f81db91742115c1cd17a7f7f06668232" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/RunTensorBoard.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "275a608e61e946495fd6a91fac263e8fb5ab62b79bb09ceab7753567f758c08e" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "notebooks/Visualise_Siamese_Pair.ipynb", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 17, - "snippet": { - "text": "{\n \"cells\": [\n {" - }, - "sourceLanguage": "JupyterPython" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 67, - "snippet": { - "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," - }, - "sourceLanguage": "Jupyter" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2ae4fb3229bfe29d8f9ca86cf390e91e296eaafbd8b0d50dd49e0d5c34afcf44" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/ManifestMake.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "3ae834c0f52337350db07c7a74ad5da1d5b21891dbb86af7b4e8f24d10e7b3ba" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "docs/conf.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 84, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 191, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Configuration file for the Sphinx documentation builder.\n#\n# This file only contains a selection of the most common options. For a full\n# list see the documentation:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "4c9a5c329324331f237c44237a2a87856dcefc34a00a7ad7152d3c2995c37219" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "setup.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 53, - "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 92, - "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n\nif __name__ == \"__main__\":\n setup()" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "532128b27875bd9e13d222179b2cc5ba0d2e7c00d65e3993dbff3dd845d66acd" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/loss.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "7c99b46c2793349e3f91bfdc4e2c6e3b0c5abf0b4261245fd142c3cf54ac0cac" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/__testing.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8205367766df33c2c9ae21b8bd36128a72582f0ca1e930b8ec0bd437481266ce" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/ssl4eos12.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "88f6ad5763bda0b0b70862a483b49abf864ca86f906b5ddc67e87362da38a43e" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "notebooks/SSL4EO-S12_Demo.ipynb", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 17, - "snippet": { - "text": "{\n \"cells\": [\n {" - }, - "sourceLanguage": "JupyterPython" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 67, - "snippet": { - "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," - }, - "sourceLanguage": "Jupyter" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "91720f3562a83119f396cd420ad41fe69fcb6764c4491a09d2ccf33d686654d8" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/pytorchtools.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 39, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 81, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n#\n# Copyright (c) 2018 Bjarte Mehus Sunde\n#" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "93c6dddb1802b35907705fd939a3882bfbd0df1d59574f856753c7fabd95adc8" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "notebooks/Torchgeo_FCN_Full.ipynb", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 17, - "snippet": { - "text": "{\n \"cells\": [\n {" - }, - "sourceLanguage": "JupyterPython" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 67, - "snippet": { - "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," - }, - "sourceLanguage": "Jupyter" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a2bda517bc615db1d93069b7d2262eb029e6650b9255bc2510f45773bd4b649e" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "notebooks/Torchgeo_FCN_Small.ipynb", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 17, - "snippet": { - "text": "{\n \"cells\": [\n {" - }, - "sourceLanguage": "JupyterPython" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 67, - "snippet": { - "text": "{\n \"cells\": [\n {\n \"attachments\": {},\n \"cell_type\": \"markdown\"," - }, - "sourceLanguage": "Jupyter" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a35f92fcab4e87a6115924ef87387c657cf8a527096c85f3a01b2553b3f8358e" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 58, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 207, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify\n# it under the terms of the GNU Lesser General Public License as published by" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "a86c36d3707e420ba84dfb38ea35c8895859297d4539216a10698d11b48c82fc" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "b63a7f23434063cf31df35f36e1a5f936e2ecc9a7e40f1501c9d333e85ad00d6" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "ba6b058b5f2efdab64de212ecf163255f812d4e70344a49b19d81d1f04c899d3" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/datasets/naip.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "bcf537e802048819675f876b2873c91c01a50358a619720d70d9a7475656e963" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 58, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 92, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# flake8: noqa: F401\n# MIT License\n\n# Copyright (c) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c3450498e9c4c0c21cdaf8b368061f090414e65a54abd9cb664548176ab80ed5" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/MinervaClusterVis.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "c67085784466323080e7db9beb01a6febb849bf5f17e4d7d936ea0843417c844" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/MinervaExp.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 69, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 104, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# PYTHON_ARGCOMPLETE_OK\n# Copyright (C) 2023 Harry Baker\n#" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e7021da7e88face1abf929abb6d68772cb18a9187ad786891cac1dcfba950ba0" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/Torch_to_ONNX.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "e806b5be98f83b1cfc62b6344f0234545c7220ecafec96e4508ea9b234f34a3f" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/models/psp.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 38, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 72, - "snippet": { - "text": "# -*- coding: utf-8 -*-\n# MIT License\n\n# Copyright (c) 2023 Harry Baker\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "f5a136402840350a6212e9c4464c2f3b110d555e96ec9f4414a7c853796973bc" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyInterpreterInspection", - "kind": "fail", - "level": "warning", - "message": { - "text": "No Python interpreter configured for the project", - "markdown": "No Python interpreter configured for the project" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "scripts/MinervaPipe.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 78, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 151, - "snippet": { - "text": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright (C) 2023 Harry Baker\n#\n# This program is free software: you can redistribute it and/or modify" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "ff77cc71e33e8107b09b009c8082ed560773ce32f8bee6920e7baa7fb4685d7c" - }, - "properties": { - "ideaSeverity": "WARNING", - "qodanaSeverity": "High" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'pathlib'", - "markdown": "Unresolved reference 'pathlib'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 56, - "startColumn": 6, - "charOffset": 2613, - "charLength": 7, - "snippet": { - "text": "pathlib" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 54, - "startColumn": 1, - "charOffset": 2582, - "charLength": 79, - "snippet": { - "text": "import argparse\nimport os\nfrom pathlib import Path\nfrom typing import Optional\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "0c3ba3acc17f1bd0fef293e02127a47735186c261938019919a975b47debc4fd" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'setuptools'", - "markdown": "Unresolved reference 'setuptools'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "setup.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 2, - "startColumn": 6, - "charOffset": 29, - "charLength": 10, - "snippet": { - "text": "setuptools" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 80, - "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n\nif __name__ == \"__main__\":" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "13db64ad496b0f8f0fa00906eea7fe27e7b8aa2117fdc57f8a2c2151c202b79d" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "No module named 'sys'", - "markdown": "No module named 'sys'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "docs/conf.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 15, - "startColumn": 8, - "charOffset": 594, - "charLength": 3, - "snippet": { - "text": "sys" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 13, - "startColumn": 1, - "charOffset": 575, - "charLength": 74, - "snippet": { - "text": "#\nimport os\nimport sys\n\nsys.path.insert(0, os.path.abspath(\"../minerva/\"))" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "2318834aee2442ba2a937b70f66501e8f54aee41fb446c30a04024574f29e6c8" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'Path'", - "markdown": "Unresolved reference 'Path'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 56, - "startColumn": 21, - "charOffset": 2628, - "charLength": 4, - "snippet": { - "text": "Path" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 54, - "startColumn": 1, - "charOffset": 2582, - "charLength": 79, - "snippet": { - "text": "import argparse\nimport os\nfrom pathlib import Path\nfrom typing import Optional\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "276e302cc6c07a342581778042716faca5dd6e50b5f8cfaaf17f2d5933a6b8ba" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'Tensor'", - "markdown": "Unresolved reference 'Tensor'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/loss.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 41, - "startColumn": 19, - "charOffset": 2101, - "charLength": 6, - "snippet": { - "text": "Tensor" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 39, - "startColumn": 1, - "charOffset": 2065, - "charLength": 108, - "snippet": { - "text": "import importlib\n\nfrom torch import Tensor\nfrom urllib3.exceptions import MaxRetryError, NewConnectionError\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "36ccc0a709b5b2dc277c0e0a5d64640b5e5d0fc95ebfc975e0945a92b3441b2a" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "No module named 'os'", - "markdown": "No module named 'os'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 55, - "startColumn": 8, - "charOffset": 2605, - "charLength": 2, - "snippet": { - "text": "os" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 53, - "startColumn": 1, - "charOffset": 2462, - "charLength": 198, - "snippet": { - "text": "# =====================================================================================================================\nimport argparse\nimport os\nfrom pathlib import Path\nfrom typing import Optional" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "47ad835d567e7f1ec14ac969414d1d6b8e76e6bc5b74ea1b39f8d78838ae1bbc" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "No module named 'argparse'", - "markdown": "No module named 'argparse'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/__init__.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 54, - "startColumn": 8, - "charOffset": 2589, - "charLength": 8, - "snippet": { - "text": "argparse" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 52, - "startColumn": 1, - "charOffset": 2400, - "charLength": 232, - "snippet": { - "text": "# IMPORTS\n# =====================================================================================================================\nimport argparse\nimport os\nfrom pathlib import Path" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "5710478f4fd44f4be60689a886125d43b325c6547176579c463a7739fd131baf" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "No module named 'importlib'", - "markdown": "No module named 'importlib'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/loss.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 39, - "startColumn": 8, - "charOffset": 2072, - "charLength": 9, - "snippet": { - "text": "importlib" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 37, - "startColumn": 1, - "charOffset": 1883, - "charLength": 224, - "snippet": { - "text": "# IMPORTS\n# =====================================================================================================================\nimport importlib\n\nfrom torch import Tensor" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6a7e7d00b6d700b56cdba1ce62890fc1c27837690330acf32819b6bb0810acd8" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "No module named 'os'", - "markdown": "No module named 'os'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "docs/conf.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 14, - "startColumn": 8, - "charOffset": 584, - "charLength": 2, - "snippet": { - "text": "os" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 12, - "startColumn": 1, - "charOffset": 495, - "charLength": 103, - "snippet": { - "text": "# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\nimport os\nimport sys\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "725fc43ba77fd9afa7ec76fa4303d2423bc0c824fb866e218fbaeeddfba45251" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'urllib3'", - "markdown": "Unresolved reference 'urllib3'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/loss.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 42, - "startColumn": 6, - "charOffset": 2113, - "charLength": 7, - "snippet": { - "text": "urllib3" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 40, - "startColumn": 1, - "charOffset": 2082, - "charLength": 150, - "snippet": { - "text": "\nfrom torch import Tensor\nfrom urllib3.exceptions import MaxRetryError, NewConnectionError\n\n# Needed to avoid connection error when importing lightly." - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "9460e80b855a4940f932d6c41bd5547b07a3739649aa8fa75c1cb6a260113062" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'setup'", - "markdown": "Unresolved reference 'setup'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "setup.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 2, - "startColumn": 24, - "charOffset": 47, - "charLength": 5, - "snippet": { - "text": "setup" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1, - "startColumn": 1, - "charOffset": 0, - "charLength": 80, - "snippet": { - "text": "# -*- coding: utf-8 -*-\nfrom setuptools import setup\n\nif __name__ == \"__main__\":" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "bb7ee3469ad1ce9f28647da9c23358464c7b8f44229d593cf69da7281d421018" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "PyUnresolvedReferencesInspection", - "kind": "fail", - "level": "error", - "message": { - "text": "Unresolved reference 'torch'", - "markdown": "Unresolved reference 'torch'" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/loss.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 41, - "startColumn": 6, - "charOffset": 2088, - "charLength": 5, - "snippet": { - "text": "torch" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 39, - "startColumn": 1, - "charOffset": 2065, - "charLength": 108, - "snippet": { - "text": "import importlib\n\nfrom torch import Tensor\nfrom urllib3.exceptions import MaxRetryError, NewConnectionError\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "cd8d70a7ff4d51adfd3b74a01335ce7efa61f720fb1b0fb3e7375336a4255cad" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "QodanaSanity", - "kind": "fail", - "level": "error", - "message": { - "text": "Expression expected", - "markdown": "Expression expected" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 814, - "startColumn": 52, - "charOffset": 26580, - "charLength": 1, - "snippet": { - "text": "\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 812, - "startColumn": 1, - "charOffset": 26515, - "charLength": 130, - "snippet": { - "text": "\ndef dec2deg(\n dec_co: Union[Sequence[float], NDArray[Shape[\"*\"], Float]], # noqa: F722\n axis: str = \"lat\",\n) -> List[str]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "6d46cca07310dce9ac011497d3c5c8a3e436ca3a687aa5cc1778202518c2cd6e" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "QodanaSanity", - "kind": "fail", - "level": "error", - "message": { - "text": "Statement expected, found Py:MULT", - "markdown": "Statement expected, found Py:MULT" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 814, - "startColumn": 52, - "charOffset": 26580, - "charLength": 1, - "snippet": { - "text": "\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 812, - "startColumn": 1, - "charOffset": 26515, - "charLength": 130, - "snippet": { - "text": "\ndef dec2deg(\n dec_co: Union[Sequence[float], NDArray[Shape[\"*\"], Float]], # noqa: F722\n axis: str = \"lat\",\n) -> List[str]:" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "761fcc5ea04ad71ea6b166762d2ffe3344f30fa99d8a376d72b806815434c18b" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "QodanaSanity", - "kind": "fail", - "level": "error", - "message": { - "text": "Expression expected", - "markdown": "Expression expected" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1517, - "startColumn": 22, - "charOffset": 52075, - "charLength": 1, - "snippet": { - "text": "\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1515, - "startColumn": 1, - "charOffset": 51992, - "charLength": 162, - "snippet": { - "text": "def batch_flatten(\n x: Union[NDArray[Any, Any], ArrayLike]\n) -> NDArray[Shape[\"*\"], Any]: # noqa: F722\n \"\"\"Flattens the supplied array with :func:`numpy`.\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "79698a3050691a6a73104160fac2b6a73d5afa38b25ab8d34a6157eed482186f" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - }, - { - "ruleId": "QodanaSanity", - "kind": "fail", - "level": "error", - "message": { - "text": "Statement expected, found Py:MULT", - "markdown": "Statement expected, found Py:MULT" - }, - "locations": [ - { - "physicalLocation": { - "artifactLocation": { - "uri": "minerva/utils/utils.py", - "uriBaseId": "SRCROOT" - }, - "region": { - "startLine": 1517, - "startColumn": 22, - "charOffset": 52075, - "charLength": 1, - "snippet": { - "text": "\"" - }, - "sourceLanguage": "Python" - }, - "contextRegion": { - "startLine": 1515, - "startColumn": 1, - "charOffset": 51992, - "charLength": 162, - "snippet": { - "text": "def batch_flatten(\n x: Union[NDArray[Any, Any], ArrayLike]\n) -> NDArray[Shape[\"*\"], Any]: # noqa: F722\n \"\"\"Flattens the supplied array with :func:`numpy`.\n" - }, - "sourceLanguage": "Python" - } - }, - "logicalLocations": [ - { - "fullyQualifiedName": "project", - "kind": "module" - } - ] - } - ], - "partialFingerprints": { - "equalIndicator/v1": "8ba55c5a2d3af846d67abc6bd7cee1883a83e0d753fca74ab2599ffb5a13970a" - }, - "properties": { - "ideaSeverity": "ERROR", - "qodanaSeverity": "Critical" - } - } - ], - "configProfile": "absent", - "deviceId": "200820300000000-aeb8-7dfb-2319-e05a933d2f21" - } - } - ] -} diff --git a/qodana.yaml b/qodana.yaml deleted file mode 100644 index f88e174ac..000000000 --- a/qodana.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -version: '1.0' -linter: jetbrains/qodana-python:2023.2-eap -failThreshold: 10 -include: - - name: CheckDependencyLicenses