Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DM-39410: Removed Ellipsis workaround from lsst.utils #847

Merged
merged 3 commits into from
Jun 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/DM-39410.misc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Replaced the use of `lsst.utils.ellipsis` mypy workaround with the native type `type.EllipsisType` available since Python 3.10.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ classifiers = [
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Scientific/Engineering :: Astronomy",
]
keywords = ["lsst"]
Expand Down
1 change: 0 additions & 1 deletion python/lsst/daf/butler/core/serverModels.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ def expression(self) -> Any:
if isinstance(regexes, list):
expression.extend(regexes)
else:
# This avoids mypy needing to import Ellipsis type
if self._allow_ellipsis:
return ...
raise ValueError("Expression matches everything but that is not allowed.")
Expand Down
13 changes: 5 additions & 8 deletions python/lsst/daf/butler/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@
import functools
import logging
import re
from typing import TYPE_CHECKING, Any, Callable, List, Optional, Pattern, TypeVar, Union
from types import EllipsisType
from typing import Any, Callable, List, Optional, Pattern, TypeVar, Union

from lsst.utils.iteration import ensure_iterable

if TYPE_CHECKING:
from lsst.utils.ellipsis import Ellipsis, EllipsisType


_LOG = logging.getLogger(__name__)


Expand Down Expand Up @@ -97,11 +94,11 @@
A list of regex Patterns or simple strings. Returns ``...`` if
the provided expressions would match everything.
"""
if expressions is Ellipsis or expressions is None:
return Ellipsis
if expressions is ... or expressions is None:
return ...

Check warning on line 98 in python/lsst/daf/butler/core/utils.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/daf/butler/core/utils.py#L98

Added line #L98 was not covered by tests
expressions = list(ensure_iterable(expressions))
if not expressions or "*" in expressions:
return Ellipsis
return ...

# List of special glob characters supported by fnmatch.
# See: https://docs.python.org/3/library/fnmatch.html
Expand Down
3 changes: 1 addition & 2 deletions python/lsst/daf/butler/registries/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
import httpx
from lsst.daf.butler import __version__
from lsst.resources import ResourcePath, ResourcePathExpression
from lsst.utils.ellipsis import Ellipsis
from lsst.utils.introspection import get_full_type_name
from lsst.utils.iteration import ensure_iterable

Expand Down Expand Up @@ -666,7 +665,7 @@ def queryDimensionRecords( # type: ignore
def queryDatasetAssociations(
self,
datasetType: str | DatasetType,
collections: CollectionArgType | None = Ellipsis,
collections: CollectionArgType | None = ...,
*,
collectionTypes: Iterable[CollectionType] = CollectionType.all(),
flattenChains: bool = False,
Expand Down
3 changes: 1 addition & 2 deletions python/lsst/daf/butler/registries/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import sqlalchemy
from lsst.daf.relation import LeafRelation, Relation
from lsst.resources import ResourcePathExpression
from lsst.utils.ellipsis import Ellipsis
from lsst.utils.iteration import ensure_iterable

from ..core import (
Expand Down Expand Up @@ -1285,7 +1284,7 @@ def queryDimensionRecords(
def queryDatasetAssociations(
self,
datasetType: Union[str, DatasetType],
collections: CollectionArgType | None = Ellipsis,
collections: CollectionArgType | None = ...,
*,
collectionTypes: Iterable[CollectionType] = CollectionType.all(),
flattenChains: bool = False,
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/daf/butler/registry/_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import logging
import re
from abc import ABC, abstractmethod
from types import EllipsisType
from typing import (
TYPE_CHECKING,
Any,
Expand All @@ -45,7 +46,6 @@

from lsst.resources import ResourcePathExpression
from lsst.utils import doImportType
from lsst.utils.ellipsis import Ellipsis, EllipsisType

from ..core import (
Config,
Expand Down Expand Up @@ -1616,7 +1616,7 @@ def queryDimensionRecords(
def queryDatasetAssociations(
self,
datasetType: Union[str, DatasetType],
collections: CollectionArgType | None = Ellipsis,
collections: CollectionArgType | None = ...,
*,
collectionTypes: Iterable[CollectionType] = CollectionType.all(),
flattenChains: bool = False,
Expand Down
3 changes: 1 addition & 2 deletions python/lsst/daf/butler/registry/collections/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast

import sqlalchemy
from lsst.utils.ellipsis import Ellipsis

from ...core import DimensionUniverse, Timespan, TimespanDatabaseRepresentation, ddl
from .._collectionType import CollectionType
Expand Down Expand Up @@ -489,7 +488,7 @@ def resolve_nested(record: CollectionRecord, done: set[str]) -> Iterator[Collect

result: list[CollectionRecord] = []

if wildcard.patterns is Ellipsis:
if wildcard.patterns is ...:
for record in self._records.values():
result.extend(resolve_nested(record, done))
del resolve_nested
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from typing import TYPE_CHECKING, Any

import sqlalchemy
from lsst.utils.ellipsis import Ellipsis

from ....core import DatasetId, DatasetIdGenEnum, DatasetRef, DatasetType, DimensionUniverse, ddl
from ..._collection_summary import CollectionSummary
Expand Down Expand Up @@ -396,7 +395,7 @@ def resolve_wildcard(
elif missing is not None:
missing.append(name)
already_warned = False
if wildcard.patterns is Ellipsis:
if wildcard.patterns is ...:
if explicit_only:
raise TypeError(
"Universal wildcard '...' is not permitted for dataset types in this context."
Expand Down
32 changes: 16 additions & 16 deletions python/lsst/daf/butler/registry/wildcards.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
import dataclasses
import re
from collections.abc import Callable, Iterable, Iterator, Mapping, Sequence
from types import EllipsisType
from typing import Any

from deprecated.sphinx import deprecated
from lsst.utils.ellipsis import Ellipsis, EllipsisType
from lsst.utils.iteration import ensure_iterable
from pydantic import BaseModel

Expand Down Expand Up @@ -117,10 +117,10 @@
"""
assert expression is not None
# See if we were given ...; just return that if we were.
if expression is Ellipsis:
if expression is ...:
if not allowAny:
raise TypeError("This expression may not be unconstrained.")
return Ellipsis
return ...
if isinstance(expression, cls):
# This is already a CategorizedWildcard. Make sure it meets the
# reqs. implied by the kwargs we got.
Expand Down Expand Up @@ -185,8 +185,8 @@
# This returns a list but we know we only passed in
# single value.
converted = globToRegex(element)
if converted is Ellipsis:
return Ellipsis
if converted is ...:
return ...
element = converted[0]
# Let regex and ... go through to the next check
if isinstance(element, str):
Expand Down Expand Up @@ -235,11 +235,11 @@

for element in ensure_iterable(expression):
retval = process(element)
if retval is Ellipsis:
if retval is ...:
# One of the globs matched everything
if not allowAny:
raise TypeError("This expression may not be unconstrained.")
return Ellipsis
return ...
del process
return self

Expand Down Expand Up @@ -331,7 +331,7 @@
)
except TypeError as err:
raise CollectionExpressionError(str(err)) from None
assert wildcard is not Ellipsis
assert wildcard is not ...

Check warning on line 334 in python/lsst/daf/butler/registry/wildcards.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/daf/butler/registry/wildcards.py#L334

Added line #L334 was not covered by tests
assert not wildcard.patterns
assert not wildcard.items
deduplicated = []
Expand Down Expand Up @@ -387,15 +387,15 @@
"""An an ordered list of explicitly-named collections. (`tuple` [ `str` ]).
"""

patterns: tuple[re.Pattern, ...] | EllipsisType = Ellipsis
patterns: tuple[re.Pattern, ...] | EllipsisType = ...
"""Regular expression patterns to match against collection names, or the
special value ``...`` indicating all collections.

`...` must be accompanied by ``strings=()``.
"""

def __post_init__(self) -> None:
if self.patterns is Ellipsis and self.strings:
if self.patterns is ... and self.strings:
raise ValueError(
f"Collection wildcard matches any string, but still has explicit strings {self.strings}."
)
Expand Down Expand Up @@ -435,14 +435,14 @@
"""
if isinstance(expression, cls):
return expression
if expression is Ellipsis:
if expression is ...:
return cls()
wildcard = CategorizedWildcard.fromExpression(
expression,
allowAny=True,
allowPatterns=True,
)
if wildcard is Ellipsis:
if wildcard is ...:
return cls()
result = cls(
strings=tuple(wildcard.strings),
Expand Down Expand Up @@ -496,7 +496,7 @@
return not self.strings and not self.patterns

def __str__(self) -> str:
if self.patterns is Ellipsis:
if self.patterns is ...:
return "..."
else:
terms = list(self.strings)
Expand All @@ -518,7 +518,7 @@
instances.
"""

patterns: tuple[re.Pattern, ...] | EllipsisType = Ellipsis
patterns: tuple[re.Pattern, ...] | EllipsisType = ...
"""Regular expressions to be matched against dataset type names, or the
special value ``...`` indicating all dataset types.

Expand Down Expand Up @@ -564,7 +564,7 @@
)
except TypeError as err:
raise DatasetTypeExpressionError(f"Invalid dataset type expression: {expression!r}.") from err
if wildcard is Ellipsis:
if wildcard is ...:
return cls()
values: dict[str, DatasetType | None] = {}
for name in wildcard.strings:
Expand All @@ -579,7 +579,7 @@
return cls(values, patterns=tuple(wildcard.patterns))

def __str__(self) -> str:
if self.patterns is Ellipsis:
if self.patterns is ...:
return "..."
else:
terms = list(self.values.keys())
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/daf/butler/script/queryDataIds.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@

import logging
from collections.abc import Iterable
from types import EllipsisType
from typing import TYPE_CHECKING

import numpy as np
from astropy.table import Table as AstropyTable
from lsst.utils.ellipsis import Ellipsis, EllipsisType

from .._butler import Butler, DataCoordinate
from ..cli.utils import sortAstropyTable
Expand Down Expand Up @@ -131,7 +131,7 @@ def queryDataIds(

query_collections: Iterable[str] | EllipsisType | None = None
if datasets:
query_collections = collections if collections else Ellipsis
query_collections = collections if collections else ...
results = butler.registry.queryDataIds(
dimensions, datasets=datasets, where=where, collections=query_collections
)
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/daf/butler/script/queryDatasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
import dataclasses
from collections import defaultdict
from collections.abc import Iterable
from types import EllipsisType
from typing import TYPE_CHECKING

import numpy as np
from astropy.table import Table as AstropyTable
from lsst.utils.ellipsis import Ellipsis, EllipsisType

from .._butler import Butler
from ..cli.utils import sortAstropyTable
Expand Down Expand Up @@ -175,7 +175,7 @@ def _getDatasets(
self, glob: Iterable[str], collections: Iterable[str], where: str, find_first: bool
) -> None:
datasetTypes = glob if glob else ...
query_collections: Iterable[str] | EllipsisType = collections if collections else Ellipsis
query_collections: Iterable[str] | EllipsisType = collections if collections else ...

self.datasets = self.butler.registry.queryDatasets(
datasetType=datasetTypes, collections=query_collections, where=where, findFirst=find_first
Expand Down
4 changes: 2 additions & 2 deletions python/lsst/daf/butler/script/queryDimensionRecords.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
from __future__ import annotations

from collections.abc import Iterable
from types import EllipsisType
from typing import Any

from astropy.table import Table
from lsst.utils.ellipsis import Ellipsis, EllipsisType

from .._butler import Butler
from ..core import Timespan
Expand All @@ -50,7 +50,7 @@ def queryDimensionRecords(

query_collections: Iterable[str] | EllipsisType | None = None
if datasets:
query_collections = collections if collections else Ellipsis
query_collections = collections if collections else ...
query_results = butler.registry.queryDimensionRecords(
element, datasets=datasets, collections=query_collections, where=where, check=not no_check
)
Expand Down
5 changes: 2 additions & 3 deletions python/lsst/daf/butler/script/retrieveArtifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@
__all__ = ("retrieveArtifacts",)

import logging
from types import EllipsisType
from typing import TYPE_CHECKING

from lsst.utils.ellipsis import Ellipsis, EllipsisType

from .._butler import Butler

if TYPE_CHECKING:
Expand Down Expand Up @@ -79,7 +78,7 @@ def retrieveArtifacts(
The destination URIs of every transferred artifact.
"""
query_types = dataset_type if dataset_type else ...
query_collections: tuple[str, ...] | EllipsisType = collections if collections else Ellipsis
query_collections: tuple[str, ...] | EllipsisType = collections if collections else ...

butler = Butler(repo, writeable=False)

Expand Down
5 changes: 2 additions & 3 deletions python/lsst/daf/butler/script/transferDatasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
__all__ = ("transferDatasets",)

import logging

from lsst.utils.ellipsis import Ellipsis, EllipsisType
from types import EllipsisType

from .._butler import Butler
from ..registry.queries import DatasetQueryResults
Expand Down Expand Up @@ -73,7 +72,7 @@
dest_butler = Butler(dest, writeable=True)

dataset_type_expr = ... if not dataset_type else dataset_type
collections_expr: tuple[str, ...] | EllipsisType = Ellipsis if not collections else collections
collections_expr: tuple[str, ...] | EllipsisType = ... if not collections else collections

Check warning on line 75 in python/lsst/daf/butler/script/transferDatasets.py

View check run for this annotation

Codecov / codecov/patch

python/lsst/daf/butler/script/transferDatasets.py#L75

Added line #L75 was not covered by tests

source_refs = source_butler.registry.queryDatasets(
datasetType=dataset_type_expr, collections=collections_expr, where=where, findFirst=find_first
Expand Down