Question: Indexes.getunique() TypeError with pandas indexes I also just tested the method that you mentioned and maybe noticed a related issue here, which I'm not sure is wanted / expected. Taking the above dataset , accessing this function results in an error: However, for it works: Originally posted by in

"""         new_indexes = {}         new_index_vars = {}         for idx, coords in self.group_by_index():            if isinstance(idx, pd.Index):                convert_new_idx = True                dim = next(iter(coords.values())).dims[0]                if isinstance(idx, pd.MultiIndex):                    idx = PandasMultiIndex(idx, dim)                else:                    idx = PandasIndex(idx, dim)            else:                convert_new_idx = False             new_idx = idx.copy(deep=deep)             idx_vars = idx.create_variables(coords)            if convert_new_idx:                new_idx = cast(PandasIndex, new_idx).index             new_indexes.update({k: new_idx for k in coords})             new_index_vars.update(idx_vars)


Question: Broken state when using assigncoords with multiindex I was trying to assign coordinates on a dataset that had been created by using stack. After assigning the coordinates, the dataset was in a state where its length was coming out as less than zero, which caused all sorts of issues. I think the issue is with the updating of , perhaps in I expected to just be able to assign the coords and then print the array to see the result. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. Here's a test (I put it in but maybe there is a better spot) <detailsINSTALLED VERSIONS commit: python: 3.8.13 (default, Mar 25 2022, 06:04:14) [Clang 12.0.1 ] python-bits: 64 OS: Darwin OS-release: 21.5.0 machine: arm64 processor: arm byteorder: little LCALL: None LANG: enAU.UTF-8 LOCALE: ('enAU', 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.8.1 xarray: 0.1.dev4312+ge678a1d. pandas: 1.5.0 numpy: 1.22.4 scipy: 1.9.1 netCDF4: 1.6.1 pydap: installed h5netcdf: 1.0.2 h5py: 3.7.0 Nio: None zarr: 2.13.2 cftime: 1.6.2 nctimeaxis: 1.4.1 PseudoNetCDF: 3.2.2 rasterio: 1.3.1 cfgrib: 0.9.10.1 iris: 3.3.0 bottleneck: 1.3.5 dask: 2022.9.1 distributed: 2022.9.1 matplotlib: 3.6.0 cartopy: 0.21.0 seaborn: 0.12.0 numbagg: 0.2.1 fsspec: 2022.8.2 cupy: None pint: 0.19.2 sparse: 0.13.0 flox: 0.5.9 numpy_groupies: 0.9.19 setuptools: 65.4.0 pip: 22.2.2 conda: None pytest: 7.1.3 IPython: None sphinx: None </details

variables, indexes = drop_coords(             coords, self._data._variables, self._data.xindexes         )<ins>        self._data._coord_names.intersection_update(variables)</ins>         self._data._variables = variables         self._data._indexes = indexes


Question: Broken state when using assigncoords with multiindex I was trying to assign coordinates on a dataset that had been created by using stack. After assigning the coordinates, the dataset was in a state where its length was coming out as less than zero, which caused all sorts of issues. I think the issue is with the updating of , perhaps in I expected to just be able to assign the coords and then print the array to see the result. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. Here's a test (I put it in but maybe there is a better spot) <detailsINSTALLED VERSIONS commit: python: 3.8.13 (default, Mar 25 2022, 06:04:14) [Clang 12.0.1 ] python-bits: 64 OS: Darwin OS-release: 21.5.0 machine: arm64 processor: arm byteorder: little LCALL: None LANG: enAU.UTF-8 LOCALE: ('enAU', 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.8.1 xarray: 0.1.dev4312+ge678a1d. pandas: 1.5.0 numpy: 1.22.4 scipy: 1.9.1 netCDF4: 1.6.1 pydap: installed h5netcdf: 1.0.2 h5py: 3.7.0 Nio: None zarr: 2.13.2 cftime: 1.6.2 nctimeaxis: 1.4.1 PseudoNetCDF: 3.2.2 rasterio: 1.3.1 cfgrib: 0.9.10.1 iris: 3.3.0 bottleneck: 1.3.5 dask: 2022.9.1 distributed: 2022.9.1 matplotlib: 3.6.0 cartopy: 0.21.0 seaborn: 0.12.0 numbagg: 0.2.1 fsspec: 2022.8.2 cupy: None pint: 0.19.2 sparse: 0.13.0 flox: 0.5.9 numpy_groupies: 0.9.19 setuptools: 65.4.0 pip: 22.2.2 conda: None pytest: 7.1.3 IPython: None sphinx: None </details

f"other variables: {list(maybe_midx.index.names)!r}. "                 f"This will raise an error in the future. Use `.drop_vars({idx_coord_names!r})` before "                 "assigning new coordinate values.",                DeprecationWarning,                FutureWarning,                 stacklevel=4,             )             for k in idx_coord_names:


Question: Raise nicer error if passing a list of dimension names to transpose Hello, in xarray 0.20.1, I am getting the following error The expected result is No response No response No response <detailsINSTALLED VERSIONS commit: None python: 3.9.12 (main, Apr 5 2022, 06:56:58) [GCC 7.5.0] python-bits: 64 OS: Linux OS-release: 3.10.0-1160.42.2.el7.x8664 machine: x8664 processor: x8664 byteorder: little LCALL: None LANG: enUS LOCALE: ('enUS', 'ISO8859-1') libhdf5: 1.12.1 libnetcdf: 4.8.1 xarray: 0.20.1 pandas: 1.4.1 numpy: 1.21.5 scipy: 1.8.0 netCDF4: 1.5.7 pydap: None h5netcdf: 999 h5py: 3.6.0 Nio: None zarr: None cftime: 1.5.1.1 nctimeaxis: 1.4.0 PseudoNetCDF: None rasterio: None cfgrib: None iris: None bottleneck: 1.3.4 dask: 2022.02.1 distributed: 2022.2.1 matplotlib: 3.5.1 cartopy: 0.18.0 seaborn: 0.11.2 numbagg: None fsspec: 2022.02.0 cupy: None pint: 0.18 sparse: 0.13.0 setuptools: 61.2.0 pip: 21.2.4 conda: None pytest: None IPython: 8.2.0 sphinx: None </details

numpy.transpose         DataArray.transpose         """<ins>        # Raise error if list is passed as dims        if (len(dims) > 0) and (isinstance(dims[0], list)):            list_fix = [f"{repr(x)}" if isinstance(x, str) else f"{x}" for x in dims[0]]            raise TypeError(                f'transpose requires dims to be passed as multiple arguments. Expected `{", ".join(list_fix)}`. Received `{dims[0]}` instead'            )</ins>         # Use infix_dims to check once for missing dimensions         if len(dims) != 0:             _ = list(infix_dims(dims, self.dims, missing_dims))


Question: Time decoding error message does not include the problematic variable's name If any variable in a Dataset has times that cannot be represented as objects, an error message will be raised. However, this error message will not indicate the problematic variable's name. It would be nice if it did, because it would make it easier for users to determine the source of the error. cc: xref: Unidata/cftime This is a minimal example of the issue. The error message gives no indication that is the problem:

and v.ndim > 0             and stackable(v.dims[-1])         )        new_vars[k] = decode_cf_variable(            k,            v,            concat_characters=concat_characters,            mask_and_scale=mask_and_scale,            decode_times=decode_times,            stack_char_dim=stack_char_dim,            use_cftime=use_cftime,            decode_timedelta=decode_timedelta,        )        try:            new_vars[k] = decode_cf_variable(                k,                v,                concat_characters=concat_characters,                mask_and_scale=mask_and_scale,                decode_times=decode_times,                stack_char_dim=stack_char_dim,                use_cftime=use_cftime,                decode_timedelta=decode_timedelta,            )        except Exception as e:            raise type(e)(f"Failed to decode variable {k!r}: {e}")         if decode_coords in [True, "coordinates", "all"]:             var_attrs = new_vars[k].attrs             if "coordinates" in var_attrs:


Question: xarray.opendataset has issues if the dataset returned by the backend contains a multiindex As a follow up of this comment: I'm currently trying to implement a custom backend that allows me to also handle multiindices when loading a NetCDF dataset using . I'm using the following two functions to convert the dataset to a NetCDF compatible version and back again: Here is a small code example: While the manual patching for saving is currently still required, I tried to at least work around the function call in by creating a custom NetCDF Backend: but this works: So I'm guessing is performing some operation on the dataset returned by the backend, and one of those leads to a failure if there is a multiindex already contained. I expected that it doesn't matter wheter is called inside the backend or afterwards, and the same dataset will be returned each time. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. No response I'm also open to other suggestions how I could simplify the usage of multiindices, maybe there is an approach that doesn't require a custom backend at all? <detailsINSTALLED VERSIONS commit: None python: 3.8.10 (default, Jan 28 2022, 09:41:12) [GCC 9.3.0] python-bits: 64 OS: Linux OS-release: 5.10.102.1-microsoft-standard-WSL2 machine: x8664 processor: x8664 byteorder: little LCALL: None LANG: C.UTF-8 LOCALE: ('enUS', 'UTF-8') libhdf5: 1.10.5 libnetcdf: 4.6.3 xarray: 2022.9.0 pandas: 1.5.0 numpy: 1.23.3 scipy: 1.9.1 netCDF4: 1.5.4 pydap: None h5netcdf: None h5py: 3.7.0 Nio: None zarr: None cftime: 1.6.2 nctimeaxis: None PseudoNetCDF: None rasterio: 1.3.2 cfgrib: None iris: None bottleneck: None dask: None distributed: None matplotlib: 3.6.0 cartopy: 0.19.0.post1 seaborn: None numbagg: None fsspec: None cupy: None pint: None sparse: 0.13.0 flox: None numpy_groupies: None setuptools: 65.3.0 pip: 22.2.2 conda: None pytest: 7.1.3 IPython: 8.5.0 sphinx: 4.5.0 </details

def _protect_dataset_variables_inplace(dataset, cache):     for name, variable in dataset.variables.items():        if name not in variable.dims:        if name not in dataset._indexes:             # no need to protect IndexVariable objects             data = indexing.CopyOnWriteArray(variable._data)             if cache:


Question: Avoid loading any data for reprs For "small" datasets, we load in to memory when displaying the repr. For cloud backed datasets with large number of "small" variables, this can use a lot of time sequentially loading O(100) variables just for a repr. Fast reprs! This dataset has 48 "small" variables On this repr takes 36.4s If I comment the condition I get 6μs. [x] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [x] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [x] New issue — a search of GitHub Issues suggests this is not a duplicate. No response No response <detailsINSTALLED VERSIONS commit: None python: 3.10.4 (main, Mar 24 2022, 17:43:32) [Clang 12.0.1 ] python-bits: 64 OS: Darwin OS-release: 21.5.0 machine: x8664 processor: i386 byteorder: little LCALL: None LANG: enUS.UTF-8 LOCALE: ('enUS', 'UTF-8') libhdf5: None libnetcdf: None xarray: 2022.3.0 pandas: 1.4.2 numpy: 1.22.4 scipy: 1.8.1 netCDF4: None pydap: None h5netcdf: None h5py: None Nio: None zarr: 2.11.3 cftime: None nctime_axis: None PseudoNetCDF: None rasterio: 1.2.10 cfgrib: None iris: None bottleneck: None dask: 2022.05.2 distributed: None matplotlib: 3.5.2 cartopy: 0.20.2 seaborn: 0.11.2 numbagg: None fsspec: 2022.5.0 cupy: None pint: None sparse: None setuptools: 62.3.2 pip: 22.1.2 conda: None pytest: None IPython: 8.4.0 sphinx: 4.5.0 </details

return short_numpy_repr(array)     elif is_duck_array(internal_data):         return limit_lines(repr(array.data), limit=40)    elif array._in_memory or array.size < 1e5:    elif array._in_memory:         return short_numpy_repr(array)     else:         # internal xarray array type


Question: overwrites coordinate attributes had some unintended consequences for , where coordinate attributes are getting overwritten by variable attributes. I guess this has been broken since . Coordinate attributes should be preserved. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. I'm struggling to figure out how the simple change in brought this about. I tried tracing my way through the various merge functions but there are a lot of layers. Happy to submit a PR if someone has an idea for an obvious fix. <detailsINSTALLED VERSIONS commit: None python: 3.9.13 (main, May 27 2022, 16:56:21) [GCC 10.3.0] python-bits: 64 OS: Linux OS-release: 5.15.0-52-generic machine: x8664 processor: x8664 byteorder: little LCALL: None LANG: enUS.UTF-8 LOCALE: ('enUS', 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.8.1 xarray: 2022.10.0 pandas: 1.4.3 numpy: 1.23.4 scipy: 1.9.3 netCDF4: 1.6.1 pydap: None h5netcdf: 1.0.2 h5py: 3.7.0 Nio: None zarr: 2.13.3 cftime: 1.6.2 nctimeaxis: 1.4.1 PseudoNetCDF: None rasterio: 1.3.3 cfgrib: 0.9.10.2 iris: None bottleneck: 1.3.5 dask: 2022.10.0 distributed: 2022.10.0 matplotlib: 3.6.1 cartopy: 0.21.0 seaborn: None numbagg: None fsspec: 2022.10.0 cupy: None pint: 0.19.2 sparse: 0.13.0 flox: 0.6.1 numpy_groupies: 0.9.19 setuptools: 65.5.0 pip: 22.3 conda: None pytest: 7.1.3 IPython: 8.5.0 sphinx: None </details

Dataset.where, DataArray.where :         equivalent methods     """    from .dataset import Dataset     if keep_attrs is None:         keep_attrs = _get_keep_attrs(default=False)    if keep_attrs is True:        # keep the attributes of x, the second parameter, by default to        # be consistent with the `where` method of `DataArray` and `Dataset`        keep_attrs = lambda attrs, context: getattr(x, "attrs", {})      # alignment for three arguments is complicated, so don't support it yet    return apply_ufunc(    result = apply_ufunc(         duck_array_ops.where,         cond,         x,


Question: overwrites coordinate attributes had some unintended consequences for , where coordinate attributes are getting overwritten by variable attributes. I guess this has been broken since . Coordinate attributes should be preserved. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. I'm struggling to figure out how the simple change in brought this about. I tried tracing my way through the various merge functions but there are a lot of layers. Happy to submit a PR if someone has an idea for an obvious fix. <detailsINSTALLED VERSIONS commit: None python: 3.9.13 (main, May 27 2022, 16:56:21) [GCC 10.3.0] python-bits: 64 OS: Linux OS-release: 5.15.0-52-generic machine: x8664 processor: x8664 byteorder: little LCALL: None LANG: enUS.UTF-8 LOCALE: ('enUS', 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.8.1 xarray: 2022.10.0 pandas: 1.4.3 numpy: 1.23.4 scipy: 1.9.3 netCDF4: 1.6.1 pydap: None h5netcdf: 1.0.2 h5py: 3.7.0 Nio: None zarr: 2.13.3 cftime: 1.6.2 nctimeaxis: 1.4.1 PseudoNetCDF: None rasterio: 1.3.3 cfgrib: 0.9.10.2 iris: None bottleneck: 1.3.5 dask: 2022.10.0 distributed: 2022.10.0 matplotlib: 3.6.1 cartopy: 0.21.0 seaborn: None numbagg: None fsspec: 2022.10.0 cupy: None pint: 0.19.2 sparse: 0.13.0 flox: 0.6.1 numpy_groupies: 0.9.19 setuptools: 65.5.0 pip: 22.3 conda: None pytest: 7.1.3 IPython: 8.5.0 sphinx: None </details

keep_attrs=keep_attrs,     ) <ins>    # keep the attributes of x, the second parameter, by default to    # be consistent with the `where` method of `DataArray` and `Dataset`    # rebuild the attrs from x at each level of the output, which could be    # Dataset, DataArray, or Variable, and also handle coords    if keep_attrs is True:        if isinstance(y, Dataset) and not isinstance(x, Dataset):            # handle special case where x gets promoted to Dataset            result.attrs = {}            if getattr(x, "name", None) in result.data_vars:                result[x.name].attrs = getattr(x, "attrs", {})        else:            # otherwise, fill in global attrs and variable attrs (if they exist)            result.attrs = getattr(x, "attrs", {})            for v in getattr(result, "data_vars", []):                result[v].attrs = getattr(getattr(x, v, None), "attrs", {})        for c in getattr(result, "coords", []):            # always fill coord attrs of x            result[c].attrs = getattr(getattr(x, c, None), "attrs", {})    return result</ins>  @overload def polyval(


Question: ds.Coarsen.construct demotes non-dimensional coordinates to variables demotes non-dimensional coordinates to variables All variables that were coordinates before the coarsen.construct stay as coordinates afterwards. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. No response No response_

else:                 reshaped[key] = var         should_be_coords = set(window_dim) & set(self.obj.coords)        # should handle window_dim being unindexed        should_be_coords = (set(window_dim) & set(self.obj.coords)) | set(            self.obj.coords        )         result = reshaped.set_coords(should_be_coords)         if isinstance(self.obj, DataArray):             return self.obj._from_temp_dataset(result)


Question: assigncoords reset all dimension coords to default (pandas) index See should preserve the index of coordinates that are not updated or not part of a dropped multi-coordinate index. See [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. No response No response_ <detailsXarray version 2022.11.0 </details

for name, variable in mapping.items():             if isinstance(variable, DataArray):                coords = variable._coords.copy()  # use private API for speed                indexes = dict(variable._indexes)                coords_ = variable._coords.copy()  # use private API for speed                indexes_ = dict(variable._indexes)                 # explicitly overwritten variables should take precedence                coords.pop(name, None)                indexes.pop(name, None)                append_all(coords, indexes)                coords_.pop(name, None)                indexes_.pop(name, None)                append_all(coords_, indexes_)              variable = as_variable(variable, name=name)             if name in indexes:


Question: assigncoords reset all dimension coords to default (pandas) index See should preserve the index of coordinates that are not updated or not part of a dropped multi-coordinate index. See [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. No response No response_ <detailsXarray version 2022.11.0 </details

aligned = deep_align(         coerced, join=join, copy=False, indexes=indexes, fill_value=fill_value     )    collected = collect_variables_and_indexes(aligned)    collected = collect_variables_and_indexes(aligned, indexes=indexes)     prioritized = _get_priority_vars_and_indexes(aligned, priority_arg, compat=compat)     variables, out_indexes = merge_collected(collected, prioritized, compat=compat)     return variables, out_indexes


Question: binary ops ignore option When doing arithmetic operations on two Dataset operands, the option is ignored and therefore attributes not kept. Minimal example: This is not true for DataArrays/Variables which do take into account. Datasets to behave the same as DataArray/Variables, and keep attributes during binary operations when option is set. PR is inbound.

self, other = align(self, other, join=align_type, copy=False)  # type: ignore[assignment]         g = f if not reflexive else lambda x, y: f(y, x)         ds = self._calculate_binary_op(g, other, join=align_type)<ins>        keep_attrs = _get_keep_attrs(default=False)        if keep_attrs:            ds.attrs = self.attrs</ins>         return ds      def _inplace_binary_op(self: T_Dataset, other, f) -> T_Dataset:


Question: stack casts int32 dtype coordinate to int64 The code example below results in , because the data type of the coordinate is changed from 'i4' to 'i8'. I expect the result to be . Creating a MultiIndex should not change the data type of the Indexes from which it is built. [X] Minimal example — the example is as focused as reasonably possible to demonstrate the underlying issue in xarray. [X] Complete example — the example is self-contained, including all data and the text of any traceback. , returning the result. [X] New issue — a search of GitHub Issues suggests this is not a duplicate. No response No response <detailsINSTALLED VERSIONS commit: None python: 3.10.8 (main, Oct 13 2022, 10:17:43) [Clang 14.0.0 (clang-1400.0.29.102)] python-bits: 64 OS: Darwin OS-release: 21.6.0 machine: x8664 processor: i386 byteorder: little LCALL: None LANG: None LOCALE: (None, 'UTF-8') libhdf5: 1.12.2 libnetcdf: 4.9.0 xarray: 2022.10.0 pandas: 1.5.1 numpy: 1.23.4 scipy: 1.9.3 netCDF4: 1.6.1 pydap: None h5netcdf: None h5py: 3.7.0 Nio: None zarr: None cftime: 1.6.2 nctimeaxis: None PseudoNetCDF: None rasterio: None cfgrib: None iris: None bottleneck: None dask: 2022.10.2 distributed: None matplotlib: 3.6.1 cartopy: 0.21.0 seaborn: None numbagg: None fsspec: 2022.10.0 cupy: None pint: None sparse: None flox: None numpygroupies: None setuptools: 65.5.0 pip: 22.1.2 conda: None pytest: None IPython: 8.6.0 sphinx: None ("Setuptools is replacing distutils.") </details

self.level = level      def __array__(self, dtype: DTypeLike = None) -> np.ndarray:        if dtype is None:            dtype = self.dtype         if self.level is not None:            return self.array.get_level_values(self.level).values            return np.asarray(                self.array.get_level_values(self.level).values, dtype=dtype            )         else:             return super().__array__(dtype)


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

import pandas as pd  from xarray.core import dtypes, utilsfrom xarray.core.alignment import alignfrom xarray.core.alignment import align, reindex_variables from xarray.core.duck_array_ops import lazy_array_equiv from xarray.core.indexes import Index, PandasIndex from xarray.core.merge import (


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

elif opt == "all":                 concat_over.update(                    set(getattr(datasets[0], subset)) - set(datasets[0].dims)                    set().union(                        *list(set(getattr(d, subset)) - set(d.dims) for d in datasets)                    )                 )             elif opt == "minimal":                 pass


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

# determine dimensional coordinate names and a dict mapping name to DataArray def _parse_datasets(    datasets: Iterable[T_Dataset],) -> tuple[dict[Hashable, Variable], dict[Hashable, int], set[Hashable], set[Hashable]]:    datasets: list[T_Dataset],) -> tuple[    dict[Hashable, Variable],    dict[Hashable, int],    set[Hashable],    set[Hashable],    list[Hashable],]:     dims: set[Hashable] = set()     all_coord_names: set[Hashable] = set()     data_vars: set[Hashable] = set()  # list of data_vars     dim_coords: dict[Hashable, Variable] = {}  # maps dim name to variable     dims_sizes: dict[Hashable, int] = {}  # shared dimension sizes to expand variables    variables_order: dict[Hashable, Variable] = {}  # variables in order of appearance      for ds in datasets:         dims_sizes.update(ds.dims)         all_coord_names.update(ds.coords)         data_vars.update(ds.data_vars)        variables_order.update(ds.variables)          # preserves ordering of dimensions         for dim in ds.dims:


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

dim_coords[dim] = ds.coords[dim].variable         dims = dims | set(ds.dims)     return dim_coords, dims_sizes, all_coord_names, data_vars    return dim_coords, dims_sizes, all_coord_names, data_vars, list(variables_order)   def _dataset_concat(


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

coords: str | list[str],     compat: CompatOptions,     positions: Iterable[Iterable[int]] | None,    fill_value: object = dtypes.NA,    fill_value: Any = dtypes.NA,     join: JoinOptions = "outer",     combine_attrs: CombineAttrsOptions = "override", ) -> T_Dataset:


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

align(*datasets, join=join, copy=False, exclude=[dim], fill_value=fill_value)     )     dim_coords, dims_sizes, coord_names, data_names = _parse_datasets(datasets)    dim_coords, dims_sizes, coord_names, data_names, vars_order = _parse_datasets(        datasets    )     dim_names = set(dim_coords)     unlabeled_dims = dim_names - coord_names


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

# we've already verified everything is consistent; now, calculate     # shared dimension sizes so we can expand the necessary variables    def ensure_common_dims(vars):    def ensure_common_dims(vars, concat_dim_lengths):         # ensure each variable with the given name shares the same         # dimensions and the same shape for all of them except along the         # concat dimension


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

data = var.set_dims(dim).values                     yield PandasIndex(data, dim, coord_dtype=var.dtype)     # create concatenation index, needed for later reindexing    concat_index = list(range(sum(concat_dim_lengths)))     # stack up each variable and/or index to fill-out the dataset (in order)     # n.b. this loop preserves variable order, needed for groupby.    for name in datasets[0].variables:    for name in vars_order:         if name in concat_over and name not in result_indexes:            try:                vars = ensure_common_dims([ds[name].variable for ds in datasets])            except KeyError:                raise ValueError(f"{name!r} is not present in all datasets.")            # Try concatenate the indexes, concatenate the variables when no index            variables = []            variable_index = []            var_concat_dim_length = []            for i, ds in enumerate(datasets):                if name in ds.variables:                    variables.append(ds[name].variable)                    # add to variable index, needed for reindexing                    var_idx = [                        sum(concat_dim_lengths[:i]) + k                        for k in range(concat_dim_lengths[i])                    ]                    variable_index.extend(var_idx)                    var_concat_dim_length.append(len(var_idx))                else:                    # raise if coordinate not in all datasets                    if name in coord_names:                        raise ValueError(                            f"coordinate {name!r} not present in all datasets."                        )            vars = ensure_common_dims(variables, var_concat_dim_length)            # Try to concatenate the indexes, concatenate the variables when no index             # is found on all datasets.             indexes: list[Index] = list(get_indexes(name))             if indexes:


Question: Add defaults during concat 508 [x] [x] Tests [x] Passes [x] Fully documented, including for all changes and for new API Contined on issue by removing exception when concat two datasets with disjoint variables and instead add the missing variable with

combined_var = concat_vars(                     vars, dim, positions, combine_attrs=combine_attrs                 )<ins>                # reindex if variable is not present in all datasets                if len(variable_index) < len(concat_index):                    combined_var = reindex_variables(                        variables={name: combined_var},                        dim_pos_indexers={                            dim: pd.Index(variable_index).get_indexer(concat_index)                        },                        fill_value=fill_value,                    )[name]</ins>                 result_vars[name] = combined_var          elif name in result_vars:


Question: Pylint 2.7.0 seems to ignore the min-similarity-lines setting <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --two Python source files that share 8 common lines min-similarity-lines=40 in the pylint config pylint 2.7.0 on the source files Before pylint 2.7.0, the min-similarity-lines setting was honored and caused shorter similar lines to be accepted. Starting with pylint 2.7.0, the min-similarity-lines setting seems to be ignored and the common lines are always reported as an issue R0801, even when the min-similarity-lines setting is significantly larger than the number of common lines. The min-similarity-lines setting should be respected again as it was before pylint 2.7.0. pylint 2.7.0 astroid 2.5 Python 3.9.1 (default, Feb 1 2021, 20:41:56) [Clang 12.0.0 (clang-1200.0.32.29)] Pylint 2.7.0 seems to ignore the min-similarity-lines setting <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --two Python source files that share 8 common lines min-similarity-lines=40 in the pylint config pylint 2.7.0 on the source files Before pylint 2.7.0, the min-similarity-lines setting was honored and caused shorter similar lines to be accepted. Starting with pylint 2.7.0, the min-similarity-lines setting seems to be ignored and the common lines are always reported as an issue R0801, even when the min-similarity-lines setting is significantly larger than the number of common lines. The min-similarity-lines setting should be respected again as it was before pylint 2.7.0. pylint 2.7.0 astroid 2.5 Python 3.9.1 (default, Feb 1 2021, 20:41:56) [Clang 12.0.0 (clang-1200.0.32.29)]

pool.join()      _merge_mapreduce_data(linter, all_mapreduce_data)    linter.stats = _merge_stats(all_stats)    linter.stats = _merge_stats([linter.stats] + all_stats)      # Insert stats data to local checkers.     for checker in linter.get_checkers():


Question: Support output to a file to support tox on CI servers Currently , which means when running Pylint from within there seems to be no way to output the results to a single (for example HTML) file that a CI server can store for display. used to be close to what is needed, but it , and also created a different file for each module which is difficult to navigate. Here is the that relates to this. this feature for the same reason:

do_exit=UNUSED_PARAM_SENTINEL,     ):  # pylint: disable=redefined-builtin         self._rcfile = None<ins>        self._output = None</ins>         self._version_asked = False         self._plugins = []         self.verbose = None


Question: Support output to a file to support tox on CI servers Currently , which means when running Pylint from within there seems to be no way to output the results to a single (for example HTML) file that a CI server can store for display. used to be close to what is needed, but it , and also created a different file for each module which is difficult to navigate. Here is the that relates to this. this feature for the same reason:

"rcfile": (self.cb_set_rcfile, True),                     "load-plugins": (self.cb_add_plugins, True),                     "verbose": (self.cb_verbose_mode, False),<ins>                    "output": (self.cb_set_output, True),</ins>                 },             )         except ArgumentPreprocessingError as ex:


Question: Support output to a file to support tox on CI servers Currently , which means when running Pylint from within there seems to be no way to output the results to a single (for example HTML) file that a CI server can store for display. used to be close to what is needed, but it , and also created a different file for each module which is difficult to navigate. Here is the that relates to this. this feature for the same reason:

"help": "Specify a configuration file to load.",                     },                 ),<ins>                (                    "output",                    {                        "action": "callback",                        "callback": Run._return_one,                        "group": "Commands",                        "type": "string",                        "metavar": "<file>",                        "help": "Specify an output file.",                    },                ),</ins>                 (                     "init-hook",                     {


Question: Support output to a file to support tox on CI servers Currently , which means when running Pylint from within there seems to be no way to output the results to a single (for example HTML) file that a CI server can store for display. used to be close to what is needed, but it , and also created a different file for each module which is difficult to navigate. Here is the that relates to this. this feature for the same reason:

# load plugin specific configuration.         linter.load_plugin_configuration()         linter.check(args)        score_value = linter.generate_reports()        if self._output:            try:                with open(self._output, "w") as output:                    linter.reporter.set_output(output)                    linter.check(args)                    score_value = linter.generate_reports()            except OSError as ex:                print(ex, file=sys.stderr)                sys.exit(32)        else:            linter.check(args)            score_value = linter.generate_reports()          if do_exit is not UNUSED_PARAM_SENTINEL:             warnings.warn(


Question: Support output to a file to support tox on CI servers Currently , which means when running Pylint from within there seems to be no way to output the results to a single (for example HTML) file that a CI server can store for display. used to be close to what is needed, but it , and also created a different file for each module which is difficult to navigate. Here is the that relates to this. this feature for the same reason:

"""callback for option preprocessing (i.e. before option parsing)"""         self._rcfile = value <ins>    def cb_set_output(self, name, value):        """callback for option preprocessing (i.e. before option parsing)"""        self._output = value</ins>     def cb_add_plugins(self, name, value):         """callback for option preprocessing (i.e. before option parsing)"""         self._plugins.extend(utils._splitstrip(value))


Question: Add --fail-on option to always return error code if specific issues (or issue types) are found We're using pylint in CI with two primary goals: there are no error-category issues - this can be achieved by looking at the exit code the overall linting score doesn't deteriorate too much - this can be achieved by using However if is used, and the score is above that, then it passes even if there are error-category issues detected. Essentially it's acting as a "only throw fail (non-zero) codes if under this", instead of a "fail if under this, otherwise change nothing". Two possible solutions I can think of here are: a configuration option to prevent from consuming other exit statuses. I.e. a way to say "if score is under N, return error code X, regardless of all else, otherwise change nothing". a new option like which means that if there are any code (error-category) issues, or any issues, then fail, otherwise change nothing.

"help": "Specify a score threshold to be exceeded before program exits with error.",                 },             ),<ins>            (                "fail-on",                {                    "default": "",                    "type": "csv",                    "metavar": "<msg ids>",                    "help": "Return non-zero exit code if any of these messages/categories are detected,"                    " even if score is above --fail-under value. Syntax same as enable."                    " Messages specified are enabled, while categories only check already-enabled messages.",                },            ),</ins>             (                 "confidence",                 {


Question: Add --fail-on option to always return error code if specific issues (or issue types) are found We're using pylint in CI with two primary goals: there are no error-category issues - this can be achieved by looking at the exit code the overall linting score doesn't deteriorate too much - this can be achieved by using However if is used, and the score is above that, then it passes even if there are error-category issues detected. Essentially it's acting as a "only throw fail (non-zero) codes if under this", instead of a "fail if under this, otherwise change nothing". Two possible solutions I can think of here are: a configuration option to prevent from consuming other exit statuses. I.e. a way to say "if score is under N, return error code X, regardless of all else, otherwise change nothing". a new option like which means that if there are any code (error-category) issues, or any issues, then fail, otherwise change nothing.

self.current_name = None         self.current_file = None         self.stats = None<ins>        self.fail_on_symbols = []</ins>         # init options         self._external_opts = options         self.options = options + PyLinter.make_options()


Question: Add --fail-on option to always return error code if specific issues (or issue types) are found We're using pylint in CI with two primary goals: there are no error-category issues - this can be achieved by looking at the exit code the overall linting score doesn't deteriorate too much - this can be achieved by using However if is used, and the score is above that, then it passes even if there are error-category issues detected. Essentially it's acting as a "only throw fail (non-zero) codes if under this", instead of a "fail if under this, otherwise change nothing". Two possible solutions I can think of here are: a configuration option to prevent from consuming other exit statuses. I.e. a way to say "if score is under N, return error code X, regardless of all else, otherwise change nothing". a new option like which means that if there are any code (error-category) issues, or any issues, then fail, otherwise change nothing.

if not getattr(checker, "enabled", True):             self.disable(checker.name)     def enable_fail_on_messages(self):        """enable 'fail on' msgs        Convert values in config.fail_on (which might be msg category, msg id,        or symbol) to specific msgs, then enable and flag them for later.        """        fail_on_vals = self.config.fail_on        if not fail_on_vals:            return        fail_on_cats = set()        fail_on_msgs = set()        for val in fail_on_vals:            # If value is a cateogry, add category, else add message            if val in MSG_TYPES:                fail_on_cats.add(val)            else:                fail_on_msgs.add(val)        # For every message in every checker, if cat or msg flagged, enable check        for all_checkers in self._checkers.values():            for checker in all_checkers:                for msg in checker.messages:                    if msg.msgid in fail_on_msgs or msg.symbol in fail_on_msgs:                        # message id/symbol matched, enable and flag it                        self.enable(msg.msgid)                        self.fail_on_symbols.append(msg.symbol)                    elif msg.msgid[0] in fail_on_cats:                        # message starts with a cateogry value, flag (but do not enable) it                        self.fail_on_symbols.append(msg.symbol)    def any_fail_on_issues(self):        return any(x in self.fail_on_symbols for x in self.stats["by_msg"])     def disable_noerror_messages(self):         for msgcat, msgids in self.msgs_store._msgs_by_category.items():             # enable only messages with 'error' severity and above ('fatal')diff --git a/pylint/lint/run.py b/pylint/lint/run.py-- a/pylint/lint/run.py++ b/pylint/lint/run.py


Question: Add --fail-on option to always return error code if specific issues (or issue types) are found We're using pylint in CI with two primary goals: there are no error-category issues - this can be achieved by looking at the exit code the overall linting score doesn't deteriorate too much - this can be achieved by using However if is used, and the score is above that, then it passes even if there are error-category issues detected. Essentially it's acting as a "only throw fail (non-zero) codes if under this", instead of a "fail if under this, otherwise change nothing". Two possible solutions I can think of here are: a configuration option to prevent from consuming other exit statuses. I.e. a way to say "if score is under N, return error code X, regardless of all else, otherwise change nothing". a new option like which means that if there are any code (error-category) issues, or any issues, then fail, otherwise change nothing.

# load plugin specific configuration.         linter.load_plugin_configuration() <ins>        # Now that plugins are loaded, get list of all fail_on messages, and enable them        linter.enable_fail_on_messages()</ins>         if self._output:             try:                 with open(self._output, "w") as output:


Question: Add --fail-on option to always return error code if specific issues (or issue types) are found We're using pylint in CI with two primary goals: there are no error-category issues - this can be achieved by looking at the exit code the overall linting score doesn't deteriorate too much - this can be achieved by using However if is used, and the score is above that, then it passes even if there are error-category issues detected. Essentially it's acting as a "only throw fail (non-zero) codes if under this", instead of a "fail if under this, otherwise change nothing". Two possible solutions I can think of here are: a configuration option to prevent from consuming other exit statuses. I.e. a way to say "if score is under N, return error code X, regardless of all else, otherwise change nothing". a new option like which means that if there are any code (error-category) issues, or any issues, then fail, otherwise change nothing.

if linter.config.exit_zero:                 sys.exit(0)             else:                if score_value and score_value >= linter.config.fail_under:                if (                    score_value                    and score_value >= linter.config.fail_under                    # detected messages flagged by --fail-on prevent non-zero exit code                    and not linter.any_fail_on_issues()                ):                     sys.exit(0)                 sys.exit(self.linter.msg_status)


Question: Pylint 2.8.2 broke pylint-quotes <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --See See in attached Running this configuration on a file containing: results in an exception: should not throw exceptions, and instead generate report complaining about the use of double quotes () and illegal variable name . Result of output: Additional dependencies: seems to have just changed versioning scheme: broke this line:

# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/LICENSE<ins>from typing import Tuple</ins>  from pkg_resources import DistributionNotFound, get_distribution


Question: Pylint 2.8.2 broke pylint-quotes <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --See See in attached Running this configuration on a file containing: results in an exception: should not throw exceptions, and instead generate report complaining about the use of double quotes () and illegal variable name . Result of output: Additional dependencies: seems to have just changed versioning scheme: broke this line:

except DistributionNotFound:     __version__ = "2.8.2+" # Kept for compatibility reason, see https://github.com/PyCQA/pylint/issues/4399numversion = tuple(__version__.split("."))def get_numversion_from_version(v: str) -> Tuple:    """Kept for compatibility reason    See https://github.com/PyCQA/pylint/issues/4399    https://github.com/PyCQA/pylint/issues/4420,    """    v = v.replace("pylint-", "")    version = []    for n in v.split(".")[0:3]:        try:            version.append(int(n))        except ValueError:            num = ""            for c in n:                if c.isdigit():                    num += c                else:                    break            try:                version.append(int(num))            except ValueError:                version.append(0)    while len(version) != 3:        version.append(0)    return tuple(version)numversion = get_numversion_from_version(__version__)


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

return sys.stdin.read()  <ins>def _load_reporter_by_class(reporter_class: str) -> type:    qname = reporter_class    module_part = astroid.modutils.get_module_part(qname)    module = astroid.modutils.load_module_from_name(module_part)    class_name = qname.split(".")[-1]    return getattr(module, class_name)</ins> # Python Linter class #########################################################  MSGS = {


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

messages store / checkers / reporter / astroid manager"""         self.msgs_store = MessageDefinitionStore()         self.reporter = None        self._reporter_name = None        self._reporter_names = None         self._reporters = {}         self._checkers = collections.defaultdict(list)         self._pragma_lineno = {}


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

# Make sure to load the default reporter, because         # the option has been set before the plugins had been loaded.         if not self.reporter:            self._load_reporter()            self._load_reporters()      def load_plugin_modules(self, modnames):         """take a list of module names which are pylint plugins and load


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

if hasattr(module, "load_configuration"):                 module.load_configuration(self)     def _load_reporter(self):        name = self._reporter_name.lower()        if name in self._reporters:            self.set_reporter(self._reporters[name]())    def _load_reporters(self) -> None:        sub_reporters = []        output_files = []        with contextlib.ExitStack() as stack:            for reporter_name in self._reporter_names.split(","):                reporter_name, *reporter_output = reporter_name.split(":", 1)                reporter = self._load_reporter_by_name(reporter_name)                sub_reporters.append(reporter)                if reporter_output:                    (reporter_output,) = reporter_output                    # pylint: disable=consider-using-with                    output_file = stack.enter_context(open(reporter_output, "w"))                    reporter.set_output(output_file)                    output_files.append(output_file)            # Extend the lifetime of all opened output files            close_output_files = stack.pop_all().close        if len(sub_reporters) > 1 or output_files:            self.set_reporter(                reporters.MultiReporter(                    sub_reporters,                    close_output_files,                )            )         else:            try:                reporter_class = self._load_reporter_class()            except (ImportError, AttributeError) as e:                raise exceptions.InvalidReporterError(name) from e            else:                self.set_reporter(reporter_class())            self.set_reporter(sub_reporters[0])     def _load_reporter_class(self):        qname = self._reporter_name        module_part = astroid.modutils.get_module_part(qname)        module = astroid.modutils.load_module_from_name(module_part)        class_name = qname.split(".")[-1]        reporter_class = getattr(module, class_name)        return reporter_class    def _load_reporter_by_name(self, reporter_name: str) -> reporters.BaseReporter:        name = reporter_name.lower()        if name in self._reporters:            return self._reporters[name]()        try:            reporter_class = _load_reporter_by_class(reporter_name)        except (ImportError, AttributeError) as e:            raise exceptions.InvalidReporterError(name) from e        else:            return reporter_class()      def set_reporter(self, reporter):         """set the reporter used to display messages and reports"""


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

meth(value)                 return  # no need to call set_option, disable/enable methods do it         elif optname == "output-format":            self._reporter_name = value            self._reporter_names = value             # If the reporters are already available, load             # the reporter class.             if self._reporters:                self._load_reporter()                self._load_reporters()          try:             checkers.BaseTokenChecker.set_option(self, optname, value, action, optdict)diff --git a/pylint/reporters/__init__.py b/pylint/reporters/__init__.py-- a/pylint/reporters/__init__.py++ b/pylint/reporters/__init__.py


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

from pylint.reporters.base_reporter import BaseReporter from pylint.reporters.collecting_reporter import CollectingReporter from pylint.reporters.json_reporter import JSONReporter<ins>from pylint.reporters.multi_reporter import MultiReporter</ins> from pylint.reporters.reports_handler_mix_in import ReportsHandlerMixIn


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

utils.register_plugins(linter, __path__[0])  __all__ = ["BaseReporter", "ReportsHandlerMixIn", "JSONReporter", "CollectingReporter"]__all__ = [    "BaseReporter",    "ReportsHandlerMixIn",    "JSONReporter",    "CollectingReporter",    "MultiReporter",]diff --git a/pylint/reporters/multi_reporter.py b/pylint/reporters/multi_reporter.pynew file mode 100644-- /dev/null++ b/pylint/reporters/multi_reporter.py


Question: Allow parseable output in parallel of human-readable output Currently, when selecting a format like JSON using the argument, it will replace the "normal" output. It would be nice to have it generate an output-file instead so the normal human-readable output is still there. This makes sens in a CI environment like travis or gitlab where you can see the stdout and stderr of each job but where you also want to parse the output. Allowing multiple output formats would solve this. Maybe with a new CLI argument? Or by adding a separator to the current value? For example: pylint -f # Would redirect the JSON data to and still write the normal report to stdout pylint 1.8.1, astroid 1.6.0 Python 3.5.2 (default, Nov 23 2017, 16:37:01) [GCC 5.4.0 ]

<ins># Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html# For details: https://github.com/PyCQA/pylint/blob/master/LICENSEimport osfrom typing import IO, Any, AnyStr, Callable, List, Mapping, Optional, Unionfrom pylint.interfaces import IReporterfrom pylint.reporters.base_reporter import BaseReporterfrom pylint.reporters.ureports.nodes import BaseLayoutAnyFile = IO[AnyStr]AnyPath = Union[str, bytes, os.PathLike]PyLinter = Anyclass MultiReporter:    """Reports messages and layouts in plain text"""    __implements__ = IReporter    name = "_internal_multi_reporter"    # Note: do not register this reporter with linter.register_reporter as it is    #       not intended to be used directly like a regular reporter, but is    #       instead used to implement the    #       `--output-format=json:somefile.json,colorized`    #       multiple output formats feature    extension = ""    def __init__(        self,        sub_reporters: List[BaseReporter],        close_output_files: Callable[[], None],        output: Optional[AnyFile] = None,    ):        self._sub_reporters = sub_reporters        self.close_output_files = close_output_files        self._path_strip_prefix = os.getcwd() + os.sep        self._linter: Optional[PyLinter] = None        self.set_output(output)    def __del__(self):        self.close_output_files()    @property    def path_strip_prefix(self) -> str:        return self._path_strip_prefix    @property    def linter(self) -> Optional[PyLinter]:        return self._linter    @linter.setter    def linter(self, value: PyLinter) -> None:        self._linter = value        for rep in self._sub_reporters:            rep.linter = value    def handle_message(self, msg: str) -> None:        """Handle a new message triggered on the current file."""        for rep in self._sub_reporters:            rep.handle_message(msg)    # pylint: disable=no-self-use    def set_output(self, output: Optional[AnyFile] = None) -> None:        """set output stream"""        # MultiReporter doesn't have it's own output. This method is only        # provided for API parity with BaseReporter and should not be called        # with non-None values for 'output'.        if output is not None:            raise NotImplementedError("MultiReporter does not support direct output.")    def writeln(self, string: str = "") -> None:        """write a line in the output buffer"""        for rep in self._sub_reporters:            rep.writeln(string)    def display_reports(self, layout: BaseLayout) -> None:        """display results encapsulated in the layout tree"""        for rep in self._sub_reporters:            rep.display_reports(layout)    def display_messages(self, layout: BaseLayout) -> None:        """hook for displaying the messages of the reporter"""        for rep in self._sub_reporters:            rep.display_messages(layout)    def on_set_current_module(self, module: str, filepath: Optional[AnyPath]) -> None:        """hook called when a module starts to be analysed"""        for rep in self._sub_reporters:            rep.on_set_current_module(module, filepath)    def on_close(        self,        stats: Mapping[Any, Any],        previous_stats: Mapping[Any, Any],    ) -> None:        """hook called when a module finished analyzing"""        for rep in self._sub_reporters:            rep.on_close(stats, previous_stats)</ins>


Question: Ignore clause not ignoring directories This is a different issue to . a directory and within that a directory . files and . Put syntax errors in both. , run . Pylint does not ignore , producing the message Pylint ignores the file . ignore-patterns does not skip non-top-level directories. <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --create a (where c.py will generate a pylint message, so that we get output) (along with the appropriate \init\.py files) Run pylint: pylint --ignore-patterns=b Run pylint: pylint --ignore-patterns=a c.py is skipped for ignore-patterns=a, but not for ignore-patterns=b c.py should be skipped for both pylint 2.1.1 astroid 2.1.0-dev Python 3.6.3 (v3.6.3:, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)]

import os import sys<ins>from typing import List, Pattern, Tuple</ins>  from astroid import modutils


Question: Ignore clause not ignoring directories This is a different issue to . a directory and within that a directory . files and . Put syntax errors in both. , run . Pylint does not ignore , producing the message Pylint ignores the file . ignore-patterns does not skip non-top-level directories. <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --create a (where c.py will generate a pylint message, so that we get output) (along with the appropriate \init\.py files) Run pylint: pylint --ignore-patterns=b Run pylint: pylint --ignore-patterns=a c.py is skipped for ignore-patterns=a, but not for ignore-patterns=b c.py should be skipped for both pylint 2.1.1 astroid 2.1.0-dev Python 3.6.3 (v3.6.3:, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)]

return os.getcwd()  def _basename_in_ignore_list_re(base_name, ignore_list_re):    """Determines if the basename is matched in a regex ignorelist    :param str base_name: The basename of the file    :param list ignore_list_re: A collection of regex patterns to match against.        Successful matches are ignored.    :returns: `True` if the basename is ignored, `False` otherwise.    :rtype: bool    """def _is_in_ignore_list_re(element: str, ignore_list_re: List[Pattern]) -> bool:    """determines if the element is matched in a regex ignore-list"""     for file_pattern in ignore_list_re:        if file_pattern.match(base_name):        if file_pattern.match(element):             return True     return False  def expand_modules(files_or_modules, ignore_list, ignore_list_re):    """Take a list of files/modules/packages and return the list of tuple    (file, module name) which have to be actually checked."""def expand_modules(    files_or_modules: List[str],    ignore_list: List[str],    ignore_list_re: List[Pattern],    ignore_list_paths_re: List[Pattern],) -> Tuple[List[dict], List[dict]]:    """take a list of files/modules/packages and return the list of tuple    (file, module name) which have to be actually checked    """     result = []     errors = []     path = sys.path.copy()     for something in files_or_modules:         basename = os.path.basename(something)        if basename in ignore_list or _basename_in_ignore_list_re(            basename, ignore_list_re        if (            basename in ignore_list            or _is_in_ignore_list_re(os.path.basename(something), ignore_list_re)            or _is_in_ignore_list_re(something, ignore_list_paths_re)         ):             continue         module_path = get_python_path(something)


Question: Ignore clause not ignoring directories This is a different issue to . a directory and within that a directory . files and . Put syntax errors in both. , run . Pylint does not ignore , producing the message Pylint ignores the file . ignore-patterns does not skip non-top-level directories. <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --create a (where c.py will generate a pylint message, so that we get output) (along with the appropriate \init\.py files) Run pylint: pylint --ignore-patterns=b Run pylint: pylint --ignore-patterns=a c.py is skipped for ignore-patterns=a, but not for ignore-patterns=b c.py should be skipped for both pylint 2.1.1 astroid 2.1.0-dev Python 3.6.3 (v3.6.3:, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)]

):                 if filepath == subfilepath:                     continue                if _basename_in_ignore_list_re(                if _is_in_ignore_list_re(                     os.path.basename(subfilepath), ignore_list_re                ):                ) or _is_in_ignore_list_re(subfilepath, ignore_list_paths_re):                     continue                 modpath = _modpath_from_file(                     subfilepath, is_namespace, path=additional_search_path                 )diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py-- a/pylint/lint/pylinter.py++ b/pylint/lint/pylinter.py


Question: Ignore clause not ignoring directories This is a different issue to . a directory and within that a directory . files and . Put syntax errors in both. , run . Pylint does not ignore , producing the message Pylint ignores the file . ignore-patterns does not skip non-top-level directories. <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --create a (where c.py will generate a pylint message, so that we get output) (along with the appropriate \init\.py files) Run pylint: pylint --ignore-patterns=b Run pylint: pylint --ignore-patterns=a c.py is skipped for ignore-patterns=a, but not for ignore-patterns=b c.py should be skipped for both pylint 2.1.1 astroid 2.1.0-dev Python 3.6.3 (v3.6.3:, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)]

" skipped. The regex matches against base names, not paths.",                 },             ),<ins>            (                "ignore-paths",                {                    "type": "regexp_csv",                    "metavar": "<pattern>[,<pattern>...]",                    "dest": "ignore_list_paths_re",                    "default": (),                    "help": "Add files or directories matching the regex patterns to the"                    " ignore-list. The regex matches against paths.",                },            ),</ins>             (                 "persistent",                 {


Question: Ignore clause not ignoring directories This is a different issue to . a directory and within that a directory . files and . Put syntax errors in both. , run . Pylint does not ignore , producing the message Pylint ignores the file . ignore-patterns does not skip non-top-level directories. <!-- Hi there! Thank you for discovering and submitting an issue. Before you submit this, make sure that the issue doesn't already exist or if it is not closed. Is your issue fixed on the preview release?: pip install pylint astroid --pre -U --create a (where c.py will generate a pylint message, so that we get output) (along with the appropriate \init\.py files) Run pylint: pylint --ignore-patterns=b Run pylint: pylint --ignore-patterns=a c.py is skipped for ignore-patterns=a, but not for ignore-patterns=b c.py should be skipped for both pylint 2.1.1 astroid 2.1.0-dev Python 3.6.3 (v3.6.3:, Oct 3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)]

def _expand_files(self, modules):         """get modules and errors from a list of modules and handle errors"""         result, errors = expand_modules(            modules, self.config.black_list, self.config.black_list_re            modules,            self.config.black_list,            self.config.black_list_re,            self.config.ignore_list_paths_re,         )         for error in errors:             message = modname = error["mod"]


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

if isinstance(node, astroid.Instance):                 node = node._proxied             if (                isinstance(node, astroid.ClassDef)                isinstance(node, (astroid.ClassDef, astroid.Name, astroid.Subscript))                 and hasattr(node, "name")                 and not self.has_node(node)             ):diff --git a/pylint/pyreverse/inspector.py b/pylint/pyreverse/inspector.py-- a/pylint/pyreverse/inspector.py++ b/pylint/pyreverse/inspector.py


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

# the name has been defined as 'global' in the frame and belongs             # there.             frame = node.root()        try:            if not hasattr(frame, "locals_type"):                # If the frame doesn't have a locals_type yet,                # it means it wasn't yet visited. Visit it now                # to add what's missing from it.                if isinstance(frame, astroid.ClassDef):                    self.visit_classdef(frame)                elif isinstance(frame, astroid.FunctionDef):                    self.visit_functiondef(frame)                else:                    self.visit_module(frame)            current = frame.locals_type[node.name]            values = set(node.infer())            frame.locals_type[node.name] = list(set(current) | values)        except astroid.InferenceError:            pass        if not hasattr(frame, "locals_type"):            # If the frame doesn't have a locals_type yet,            # it means it wasn't yet visited. Visit it now            # to add what's missing from it.            if isinstance(frame, astroid.ClassDef):                self.visit_classdef(frame)            elif isinstance(frame, astroid.FunctionDef):                self.visit_functiondef(frame)            else:                self.visit_module(frame)        current = frame.locals_type[node.name]        frame.locals_type[node.name] = list(set(current) | utils.infer_node(node))      @staticmethod     def handle_assignattr_type(node, parent):


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

handle instance_attrs_type         """        try:            values = set(node.infer())            current = set(parent.instance_attrs_type[node.attrname])            parent.instance_attrs_type[node.attrname] = list(current | values)        except astroid.InferenceError:            pass        current = set(parent.instance_attrs_type[node.attrname])        parent.instance_attrs_type[node.attrname] = list(            current | utils.infer_node(node)        )      def visit_import(self, node):         """visit an astroid.Import nodediff --git a/pylint/pyreverse/utils.py b/pylint/pyreverse/utils.py-- a/pylint/pyreverse/utils.py++ b/pylint/pyreverse/utils.py


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

import os import re import sys<ins>from typing import Optional, Unionimport astroid</ins>  RCFILE = ".pyreverserc"


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

if methods[1] is not None:             return methods[1](node)         return Nonedef get_annotation_label(ann: Union[astroid.Name, astroid.Subscript]) -> str:    label = ""    if isinstance(ann, astroid.Subscript):        label = ann.as_string()    elif isinstance(ann, astroid.Name):        label = ann.name    return labeldef get_annotation(    node: Union[astroid.AssignAttr, astroid.AssignName]) -> Optional[Union[astroid.Name, astroid.Subscript]]:    """return the annotation for `node`"""    ann = None    if isinstance(node.parent, astroid.AnnAssign):        ann = node.parent.annotation    elif isinstance(node, astroid.AssignAttr):        init_method = node.parent.parent        try:            annotations = dict(zip(init_method.locals, init_method.args.annotations))            ann = annotations.get(node.parent.value.name)        except AttributeError:            pass    else:        return ann    try:        default, *_ = node.infer()    except astroid.InferenceError:        default = ""    label = get_annotation_label(ann)    if ann:        label = (            rf"Optional[{label}]"            if getattr(default, "value", "value") is None            and not label.startswith("Optional")            else label        )    if label:        ann.name = label    return anndef infer_node(node: Union[astroid.AssignAttr, astroid.AssignName]) -> set:    """Return a set containing the node annotation if it exists    otherwise return a set of the inferred types using the NodeNG.infer method"""    ann = get_annotation(node)    if ann:        return {ann}    try:        return set(node.infer())    except astroid.InferenceError:        return set()diff --git a/pylint/pyreverse/writer.py b/pylint/pyreverse/writer.py-- a/pylint/pyreverse/writer.py++ b/pylint/pyreverse/writer.py


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

import os  from pylint.graph import DotBackendfrom pylint.pyreverse.utils import is_exceptionfrom pylint.pyreverse.utils import get_annotation_label, is_exception from pylint.pyreverse.vcgutils import VCGPrinter


Question: Use Python type hints for UML generation It seems that pyreverse does not read python type hints (as defined by ), and this does not help when you use as a default value : Output of pyreverse : ! I would like to see something like : in the output. pylint- 1.6.5, astroid 1.4.9 Python 3.6.0 (default, Dec 23 2016, 11:57:41) [MSC v.1900 64 bit (AMD64)]

if not self.config.only_classnames:             label = r"{}|{}\l|".format(label, r"\l".join(obj.attrs))             for func in obj.methods:                return_type = (                    f": {get_annotation_label(func.returns)}" if func.returns else ""                )                 if func.args.args:                    args = [arg.name for arg in func.args.args if arg.name != "self"]                    args = [arg for arg in func.args.args if arg.name != "self"]                 else:                     args = []                label = r"{}{}({})\l".format(label, func.name, ", ".join(args))                annotations = dict(zip(args, func.args.annotations[1:]))                for arg in args:                    annotation_label = ""                    ann = annotations.get(arg)                    if ann:                        annotation_label = get_annotation_label(ann)                    annotations[arg] = annotation_label                args = ", ".join(                    f"{arg.name}: {ann}" if ann else f"{arg.name}"                    for arg, ann in annotations.items()                )                label = fr"{label}{func.name}({args}){return_type}\l"             label = "{%s}" % label         if is_exception(obj.node):             return dict(fontcolor="red", label=label, shape="record")


Question: unused-import false positive for a module used in a type comment should not be emitted. Result of output: This is a follow up to .

self._type_annotation_names.append(type_annotation.name)             return         if isinstance(type_annotation, astroid.Attribute):            self._store_type_annotation_node(type_annotation.expr)            return         if not isinstance(type_annotation, astroid.Subscript):             return diff --git a/pylint/constants.py b/pylint/constants.py-- a/pylint/constants.py++ b/pylint/constants.py


Question: unused-import false positive for a module used in a type comment should not be emitted. Result of output: This is a follow up to .

# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html # For details: https://github.com/PyCQA/pylint/blob/master/LICENSE <ins>import platform</ins> import sys  import astroid


Question: unused-import false positive for a module used in a type comment should not be emitted. Result of output: This is a follow up to .

PY39_PLUS = sys.version_info[:2] >= (3, 9) PY310_PLUS = sys.version_info[:2] >= (3, 10) <ins>IS_PYPY = platform.python_implementation() == "PyPy"</ins>  PY_EXTS = (".py", ".pyc", ".pyo", ".pyw", ".so", ".dll")


Question: Make pylint XDG Base Directory Specification compliant I have this really annoying directory in my home folder. From what I can tell (I don't do C or C++), this directory is storing data. The problem with this is, quite simply, that data storage has a designated spot. The folder. This is a part of the . A system that designates the folders for specific things like cached files (), configuration files (), and data files (), among other things. The point is to keep user home directories clean and the user sane. This should be pretty easy to implement. Simply change the variables/constants for where these files are made and stored to the appropriate directory. Simple as that, even for a large codebase (if it was done right).

import pickle import sys <ins>import appdirs</ins> from pylint.config.configuration_mixin import ConfigurationMixIn from pylint.config.find_default_config_files import find_default_config_files from pylint.config.man_help_formatter import _ManHelpFormatter


Question: Make pylint XDG Base Directory Specification compliant I have this really annoying directory in my home folder. From what I can tell (I don't do C or C++), this directory is storing data. The problem with this is, quite simply, that data storage has a designated spot. The folder. This is a part of the . A system that designates the folders for specific things like cached files (), configuration files (), and data files (), among other things. The point is to keep user home directories clean and the user sane. This should be pretty easy to implement. Simply change the variables/constants for where these files are made and stored to the appropriate directory. Simple as that, even for a large codebase (if it was done right).

elif USER_HOME == "~":     PYLINT_HOME = ".pylint.d" else:    PYLINT_HOME = os.path.join(USER_HOME, ".pylint.d")    PYLINT_HOME = appdirs.user_cache_dir("pylint")    old_home = os.path.join(USER_HOME, ".pylint.d")    if os.path.exists(old_home):        print(            f"PYLINTHOME is now '{PYLINT_HOME}' but obsolescent '{old_home}' is found; "            "you can safely remove the latter",            file=sys.stderr,        )   def _get_pdata_path(base_name, recurs):


Question: Similarities checker with "ignore-signatures" option enabled ignores functions with docstring-only bodies follow-up. Given multiple files: : : Result of : error shouldn't be reported in this case. Note: if functions have bodies everything works correctly. You could add to the example functions above and no error would be reported. Result of output:

signature_lines = set(             chain(                 *(                    range(func.fromlineno, func.body[0].lineno)                    range(                        func.fromlineno,                        func.body[0].lineno if func.body else func.tolineno + 1,                    )                     for func in functions                    if func.body                 )             )         )


Question: Imports within TYPECHECKING can induce "cyclic-import" Suppose you have two modules: a.py and b.py. imports , but needs in order to do type annotations, then this is usually done by importing within a block. Unfortunately, this causes pylint to report . Possibly related to

self.add_message("import-error", args=repr(dotted_modname), node=importnode)         return None     def _add_imported_module(self, node, importedmodname):    def _add_imported_module(        self, node: Union[astroid.Import, astroid.ImportFrom], importedmodname: str    ) -> None:         """notify an imported module, used to analyze dependencies"""         module_file = node.root().file         context_name = node.root().name


Question: Imports within TYPECHECKING can induce "cyclic-import" Suppose you have two modules: a.py and b.py. imports , but needs in order to do type annotations, then this is usually done by importing within a block. Unfortunately, this causes pylint to report . Possibly related to

except ImportError:             pass <ins>        in_type_checking_block = (            isinstance(node.parent, astroid.If) and node.parent.is_typing_guard()        )</ins>         if context_name == importedmodname:             self.add_message("import-self", node=node)


Question: Imports within TYPECHECKING can induce "cyclic-import" Suppose you have two modules: a.py and b.py. imports , but needs in order to do type annotations, then this is usually done by importing within a block. Unfortunately, this causes pylint to report . Possibly related to

# update import graph             self.import_graph[context_name].add(importedmodname)            if not self.linter.is_message_enabled("cyclic-import", line=node.lineno):            if (                not self.linter.is_message_enabled("cyclic-import", line=node.lineno)                or in_type_checking_block            ):                 self._excluded_edges[context_name].add(importedmodname)      def _check_preferred_module(self, node, mod_path):


Question: Config File Does not Expand Environment Variables If a config file is provided that has an environment variable, such as "%AppData%", it fails. This can be fixed by changing from to

if config_file is None:             config_file = self.config_file         if config_file is not None:            config_file = os.path.expanduser(config_file)            config_file = os.path.expandvars(os.path.expanduser(config_file))             if not os.path.exists(config_file):                 raise OSError(f"The config file {config_file} doesn't exist!")


Question: Ignore class methods signatures with similarities "ignore-signatures" option enabled Initial already closed issue . One more related closed question with examples . Similarities "ignore-signatures" option currently only ignores functions' signatures. Class methods won't be ignored with the current implementation which would be very useful to avoid false-negative errors for classes. With similarities "ignore-signatures" option enabled, class methods' signatures are ignored the same way as functions'.

)  import astroid<ins>from astroid.node_classes import NodeNG</ins>  from pylint.checkers import BaseChecker, MapReduceMixin, table_lines_from_stats from pylint.interfaces import IRawChecker


Question: Ignore class methods signatures with similarities "ignore-signatures" option enabled Initial already closed issue . One more related closed question with examples . Similarities "ignore-signatures" option currently only ignores functions' signatures. Class methods won't be ignored with the current implementation which would be very useful to avoid false-negative errors for classes. With similarities "ignore-signatures" option enabled, class methods' signatures are ignored the same way as functions'.

}         current_line_is_import = False     if ignore_signatures:        functions = [            n            for n in tree.body            if isinstance(n, (astroid.FunctionDef, astroid.AsyncFunctionDef))        ]        def _get_functions(functions: List[NodeNG], tree: NodeNG) -> List[NodeNG]:            """Recursively get all functions including nested in the classes from the tree."""            for node in tree.body:                if isinstance(node, (astroid.FunctionDef, astroid.AsyncFunctionDef)):                    functions.append(node)                if isinstance(                    node,                    (astroid.ClassDef, astroid.FunctionDef, astroid.AsyncFunctionDef),                ):                    _get_functions(functions, node)            return functions        functions = _get_functions([], tree)         signature_lines = set(             chain(                 *(


Question: Setting to should stop pylint from checking duplicate code Setting to in the rcfile doesn't disable checking for duplicate code, it instead treats every line of code as duplicate and raises many errors. Setting to should disable the duplicate code check. It works that way in many other linters (like flake8). Setting a numerical value in flake8 to (e.g. ) disables that check. requests being able to disable , but it is still open

def run(self) -> None:         """start looking for similarities and display results on stdout"""<ins>        if self.min_lines == 0:            return</ins>         self._display_sims(self._compute_sims())      def _compute_sims(self) -> List[Tuple[int, Set[LinesChunkLimits_T]]]:


Question: args is considered as missing in documentation Hi, I met an issue with the following code: ` Return this warning: W9015: "args" missing in parameter documentation (missing-param-doc) No warning must be returned as there is a documentation concerning args pylint 2.5.3 astroid 2.4.2 Python 3.7.2 (default, Feb 25 2019, 14:07:05) [GCC 4.8.5 (Red Hat 4.8.5-36)]

\s+         )?         (\w+)                   # Parameter name        (\*{{0,2}}\w+)          # Parameter name with potential asterisks         \s*                     # whitespace         :                       # final colon         """


Question: args is considered as missing in documentation Hi, I met an issue with the following code: ` Return this warning: W9015: "args" missing in parameter documentation (missing-param-doc) No warning must be returned as there is a documentation concerning args pylint 2.5.3 astroid 2.4.2 Python 3.7.2 (default, Feb 25 2019, 14:07:05) [GCC 4.8.5 (Red Hat 4.8.5-36)]

re_param_line = re.compile(         fr"""        \s*  \*{{0,2}}(\w+)             # identifier potentially with asterisks        \s*  (\*{{0,2}}\w+)             # identifier potentially with asterisks         \s*  ( [(]             {re_multiple_type}             (?:,\s+optional)?


Question: args is considered as missing in documentation Hi, I met an issue with the following code: ` Return this warning: W9015: "args" missing in parameter documentation (missing-param-doc) No warning must be returned as there is a documentation concerning args pylint 2.5.3 astroid 2.4.2 Python 3.7.2 (default, Feb 25 2019, 14:07:05) [GCC 4.8.5 (Red Hat 4.8.5-36)]

re_param_line = re.compile(         fr"""        \s*  (\w+)                                                          # identifier        \s*  (\*{{0,2}}\w+)                                                 # identifier with potential asterisks         \s*  :         \s*  (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?)?     # optional type declaration         \s* (.*)                                                            # optional descriptiondiff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py-- a/pylint/extensions/docparams.py++ b/pylint/extensions/docparams.py


Question: args is considered as missing in documentation Hi, I met an issue with the following code: ` Return this warning: W9015: "args" missing in parameter documentation (missing-param-doc) No warning must be returned as there is a documentation concerning args pylint 2.5.3 astroid 2.4.2 Python 3.7.2 (default, Feb 25 2019, 14:07:05) [GCC 4.8.5 (Red Hat 4.8.5-36)]

}          if arguments_node.vararg is not None:            expected_argument_names.add(arguments_node.vararg)            not_needed_type_in_docstring.add(arguments_node.vararg)            expected_argument_names.add(f"*{arguments_node.vararg}")            not_needed_type_in_docstring.add(f"*{arguments_node.vararg}")         if arguments_node.kwarg is not None:            expected_argument_names.add(arguments_node.kwarg)            not_needed_type_in_docstring.add(arguments_node.kwarg)            expected_argument_names.add(f"**{arguments_node.kwarg}")            not_needed_type_in_docstring.add(f"**{arguments_node.kwarg}")         params_with_doc, params_with_type = doc.match_param_docs()         # Tolerate no parameter documentation at all.         if not params_with_doc and not params_with_type and accept_no_param_doc:diff --git a/pylint/reporters/text.py b/pylint/reporters/text.py-- a/pylint/reporters/text.py++ b/pylint/reporters/text.py


Question: args is considered as missing in documentation Hi, I met an issue with the following code: ` Return this warning: W9015: "args" missing in parameter documentation (missing-param-doc) No warning must be returned as there is a documentation concerning args pylint 2.5.3 astroid 2.4.2 Python 3.7.2 (default, Feb 25 2019, 14:07:05) [GCC 4.8.5 (Red Hat 4.8.5-36)]

:param style: the message's style elements, this will be deprecated     :param kwargs: used to accept `color` parameter while it is being deprecated    :param **kwargs: used to accept `color` parameter while it is being deprecated      :return: the ansi escaped string     """


Question: False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response

"""Utility methods for docstring checking."""  import refrom typing import Listfrom typing import List, Set, Tuple  import astroid from astroid import nodes


Question: False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response

re_param_line = re.compile(         fr"""        \s*  (\*{{0,2}}\w+)                                                 # identifier with potential asterisks        \s*  :        \s*  (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?)?     # optional type declaration        \s*  (\*{{0,2}}\w+)(\s?(:|\n))                                      # identifier with potential asterisks        \s*  (?:({GoogleDocstring.re_multiple_type})(?:,\s+optional)?\n)?   # optional type declaration         \s* (.*)                                                            # optional description     """,         re.X | re.S,


Question: False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response False positive missing-param-doc on numpy style when omitted Would not have expected either or checks to have failed. VS Code 1.61.2 Windows 10 Pro 21H1 No response

supports_yields = True <ins>    def match_param_docs(self) -> Tuple[Set[str], Set[str]]:        """Matches parameter documentation section to parameter documentation rules"""        params_with_doc = set()        params_with_type = set()        entries = self._parse_section(self.re_param_section)        print(entries)        entries.extend(self._parse_section(self.re_keyword_param_section))        for entry in entries:            match = self.re_param_line.match(entry)            if not match:                continue            # check if parameter has description only            re_only_desc = re.match(r"\s*  (\*{0,2}\w+)\s*:?\n", entry)            if re_only_desc:                param_name = match.group(1)                param_desc = match.group(2)                param_type = None            else:                param_name = match.group(1)                param_type = match.group(3)                param_desc = match.group(4)            if param_type:                params_with_type.add(param_name)            if param_desc:                params_with_doc.add(param_name)        return params_with_doc, params_with_type</ins>     @staticmethod     def min_section_indent(section_match):         return len(section_match.group(1))


Question: The duplicate-code (R0801) can't be disabled Originally reported by: Anonymous It's seems like it's not possible to disable the duplicate code check on portions of a file. Looking at the source, I can see why as it's not a trivial thing to do (if you want to maintain the same scope semantics as other #pylint:enable/disable comments. This would be nice to have though (or I guess I could just cleanup my duplicate code). Bitbucket:

else:             readlines = stream.readlines  # type: ignore[assignment] # hint parameter is incorrectly typed as non-optional         try:            active_lines: List[str] = []            if hasattr(self, "linter"):                # Remove those lines that should be ignored because of disables                for index, line in enumerate(readlines()):                    if self.linter._is_one_message_enabled("R0801", index + 1):  # type: ignore[attr-defined]                        active_lines.append(line)            else:                active_lines = readlines()             self.linesets.append(                 LineSet(                     streamid,                    readlines(),                    active_lines,                     self.ignore_comments,                     self.ignore_docstrings,                     self.ignore_imports,


Question: The negative score is not very beginner friendly For the past months I've been under the impression that the negative score is not very friendly for beginners. It somewhat demotivating to run over your project just to get a as a score, which would make look like a super drastic tool, that's super nitpicky about everything. I think we could do a better job here at welcoming everyone to using . Instead of having a score, we could check if other tools are doing something different and see what works best in general. The negative score is not very beginner friendly For the past months I've been under the impression that the negative score is not very friendly for beginners. It somewhat demotivating to run over your project just to get a as a score, which would make look like a super drastic tool, that's super nitpicky about everything. I think we could do a better job here at welcoming everyone to using . Instead of having a score, we could check if other tools are doing something different and see what works best in general.

"metavar": "<python_expression>",                     "group": "Reports",                     "level": 1,                    "default": "0 if fatal else 10.0 - ((float(5 * error + warning + refactor + "                    "convention) / statement) * 10)",                    "default": "max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + "                    "convention) / statement) * 10))",                     "help": "Python expression which should return a score less "                     "than or equal to 10. You have access to the variables 'fatal', "                     "'error', 'warning', 'refactor', 'convention', and 'info' which "