Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ jobs:
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"

- name: Install 'build' package
run: pip install build
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/run-precommit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4.3.0
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"

# mainly needed so mypy will have the dependencies it needs
- name: Install elementary
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-github-action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ jobs:
echo "$PROFILES_YML" > ~/.dbt/profiles.yml

- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"

- name: Install dbt
run: pip install --pre
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-warehouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ jobs:
# run: docker compose up -d clickhouse

- name: Setup Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.10"

- name: Install Spark requirements
if: inputs.warehouse-type == 'spark'
Expand Down
2 changes: 1 addition & 1 deletion elementary/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def get_quiet_logs(ctx):
return False


class ElementaryCLI(click.MultiCommand):
class ElementaryCLI(click.MultiCommand): # type: ignore[misc, valid-type]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

click types-click MultiCommand mypy typing issue 2025

💡 Result:

The most common cause is having types-click installed while using click>=8.0.

  • click ships its own type hints/stubs since v8.0, so types-click is no longer needed and can conflict with Click’s bundled annotations (often showing up around classes like click.MultiCommand). [1]
  • Fix: uninstall types-click (and then re-run mypy), keeping only click installed. If you must use types-click, you generally need to pin click<8. [1]

If the problem is an actual stub bug, the types-click stubs come from typeshed, and fixes should be filed/contributed there. [1][2]

Sources:
[1] https://pypi.org/project/types-click/
[2] https://github.com/python/typeshed


🌐 Web query:

click library Python type hints MultiCommand subclassing support

💡 Result:

Yes—Click supports subclassing click.MultiCommand (and click.Group) and it has type-hint support:

  • Subclassing support: A custom multi-command is implemented by overriding list_commands(ctx) and get_command(ctx, cmd_name). Click’s docs explicitly describe this extension point for Group / MultiCommand. [2]
  • Type hints: Click ships with type annotations / stubs since Click 8.0 (so you typically don’t need types-click on modern Click). [1]
  • Typed MultiCommand API: In the Click API docs, get_command is documented as returning Command | None and list_commands as List[str], which is what type checkers will expect your overrides to match. [3]

Sources:
[1] https://pypi.org/project/types-click/
[2] https://pocoo-click.readthedocs.io/en/latest/advanced/
[3] https://dokk.org/documentation/pallets-click/8.1.7/api/


🏁 Script executed:

# Find dependency files
fd -e "pyproject.toml" -e "setup.py" -e "requirements.txt" -e "setup.cfg" | head -20

Repository: elementary-data/elementary

Length of output: 52


🏁 Script executed:

# Check for mypy configuration
fd -e "mypy.ini" -e ".mypy.ini" | head -10
cat pyproject.toml 2>/dev/null | grep -A 20 "\[tool.mypy\]" || true

Repository: elementary-data/elementary

Length of output: 52


🏁 Script executed:

# Search for click and types-click in dependencies
grep -r "types-click\|click" pyproject.toml setup.py setup.cfg requirements.txt 2>/dev/null || true

Repository: elementary-data/elementary

Length of output: 402


🏁 Script executed:

# Check full pyproject.toml for types-click and mypy config
cat pyproject.toml | head -150

Repository: elementary-data/elementary

Length of output: 2653


🏁 Script executed:

# Check if types-click appears anywhere in dependencies
grep -i "types.click" pyproject.toml || echo "types-click not found in pyproject.toml"

Repository: elementary-data/elementary

Length of output: 109


🏁 Script executed:

# Check if there's a lock file indicating actual versions
ls -la | grep -E "\.lock|poetry\.lock|Pipfile"

Repository: elementary-data/elementary

Length of output: 52


🏁 Script executed:

# Check for mypy configuration in pyproject.toml
cat pyproject.toml | grep -A 30 "\[tool.mypy\]"

Repository: elementary-data/elementary

Length of output: 52


🏁 Script executed:

# Check if there's a mypy.ini or .mypy.ini file
find . -maxdepth 2 -name "mypy.ini" -o -name ".mypy.ini" -o -name "mypy.cfg" 2>/dev/null | head -5

Repository: elementary-data/elementary

Length of output: 80


🏁 Script executed:

# Verify the actual click version being used and Python version support
cat pyproject.toml | grep -E "python|click" | head -10

Repository: elementary-data/elementary

Length of output: 366


🏁 Script executed:

# Check mypy.ini configuration
cat ./mypy.ini

Repository: elementary-data/elementary

Length of output: 358


🏁 Script executed:

# Check the actual ElementaryCLI class to understand context
cat -n elementary/cli/cli.py | head -60

Repository: elementary-data/elementary

Length of output: 2271


Scoped type ignore is good practice, but reconsider the explanatory comment.

Using specific error codes (misc, valid-type) rather than a blanket ignore is correct. However, the suggested comment is inaccurate—Click 8.0+ has full type stub support for MultiCommand subclassing. The actual issue is likely method return type mismatches: list_commands() returns dict_keys but the type stub expects Sequence[str], and get_command() may have signature mismatches.

If the type ignore is still necessary, a more accurate comment would be: # type: ignore[misc, valid-type] # Method signatures differ from click.MultiCommand stubs. Alternatively, consider adjusting method signatures to match Click's type expectations (return list() from list_commands(), explicitly type get_command() return as Command | None).

🤖 Prompt for AI Agents
In `@elementary/cli/cli.py` at line 39, The type-ignore comment on the
ElementaryCLI class is misleading; update it to accurately state why the ignore
is used or eliminate it by aligning method signatures: either change the comment
to "# type: ignore[misc, valid-type]  # Method signatures differ from
click.MultiCommand stubs" or modify ElementaryCLI.list_commands to return a
Sequence[str] (e.g., return list(self._commands.keys())) and annotate
ElementaryCLI.get_command to return Command | None to match Click's stubs;
ensure both method signatures and return types conform to click.MultiCommand
expectations so the scoped type ignore is no longer necessary.

_CMD_MAP = {
"monitor": monitor,
"report": report,
Expand Down
12 changes: 11 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ readme = "README.md"
homepage = "https://www.elementary-data.com"
repository = "https://github.com/elementary-data/elementary"
documentation = "https://docs.elementary-data.com"
classifiers = [
"Natural Language :: English",
"Intended Audience :: Developers",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development :: Libraries",
]

packages = [{include = "elementary"}]

[tool.poetry.dependencies]
python = ">=3.9,<3.14"
python = ">=3.10,<3.14"
click = ">=7.0,<9.0"
dbt-core = ">=0.20,<2.0.0"
requests = ">=2.28.1,<3.0.0"
Expand Down
Loading