diff --git a/pyright/alt-1/requirements-pinned.txt b/pyright/alt-1/requirements-pinned.txt index 753959ae7d4c4..f24d75669a908 100644 --- a/pyright/alt-1/requirements-pinned.txt +++ b/pyright/alt-1/requirements-pinned.txt @@ -1,11 +1,11 @@ agate==1.9.1 -aiobotocore==2.17.0 +aiobotocore==2.18.0 aiofile==3.9.0 aiohappyeyeballs==2.4.4 aiohttp==3.11.11 aioitertools==0.12.0 aiosignal==1.3.2 -alembic==1.14.0 +alembic==1.14.1 annotated-types==0.7.0 antlr4-python3-runtime==4.13.2 anyio==4.8.0 @@ -24,10 +24,10 @@ backoff==2.2.1 backports-tarfile==1.2.0 beautifulsoup4==4.12.3 bleach==6.2.0 -boto3==1.35.93 -boto3-stubs-lite==1.35.70 -botocore==1.35.93 -botocore-stubs==1.35.97 +boto3==1.36.1 +boto3-stubs-lite==1.36.2 +botocore==1.36.1 +botocore-stubs==1.36.2 buildkite-test-collector==0.1.9 cachetools==5.5.0 caio==0.9.21 @@ -72,12 +72,12 @@ dbt-duckdb==1.9.1 dbt-extractor==0.5.1 dbt-semantic-interfaces==0.7.4 dbt-snowflake==1.9.0 -debugpy==1.8.11 +debugpy==1.8.12 decopatch==1.4.10 decorator==5.1.1 deepdiff==7.0.1 defusedxml==0.7.1 -deltalake==0.23.2 +deltalake==0.24.0 dill==0.3.9 distlib==0.3.9 docker==7.1.0 @@ -88,13 +88,13 @@ executing==2.1.0 fastjsonschema==2.21.1 filelock==3.16.1 flaky==3.8.1 -fonttools==4.55.3 +fonttools==4.55.4 fqdn==1.5.1 frozenlist==1.5.0 fsspec==2024.3.0 gcsfs==0.8.0 google-api-core==2.24.0 -google-api-python-client==2.158.0 +google-api-python-client==2.159.0 google-auth==2.37.0 google-auth-httplib2==0.2.0 google-auth-oauthlib==1.2.1 @@ -118,7 +118,7 @@ httplib2==0.22.0 httptools==0.6.4 httpx==0.28.1 humanfriendly==10.0 -hypothesis==6.123.16 +hypothesis==6.124.1 idna==3.10 importlib-metadata==6.11.0 iniconfig==2.0.0 @@ -160,18 +160,18 @@ matplotlib-inline==0.1.7 mccabe==0.7.0 mdurl==0.1.2 mistune==3.1.0 -more-itertools==10.5.0 +more-itertools==10.6.0 morefs==0.2.2 msgpack==1.1.0 multidict==6.1.0 mypy==1.14.1 -mypy-boto3-ecs==1.35.93 -mypy-boto3-emr==1.35.93 -mypy-boto3-emr-containers==1.35.93 -mypy-boto3-emr-serverless==1.35.93 -mypy-boto3-glue==1.35.93 -mypy-boto3-logs==1.35.93 -mypy-boto3-s3==1.35.93 +mypy-boto3-ecs==1.36.1 +mypy-boto3-emr==1.36.0 +mypy-boto3-emr-containers==1.36.0 +mypy-boto3-emr-serverless==1.36.0 +mypy-boto3-glue==1.36.0 +mypy-boto3-logs==1.36.0 +mypy-boto3-s3==1.36.0 mypy-extensions==1.0.0 mypy-protobuf==3.6.0 nbclient==0.10.2 @@ -181,12 +181,12 @@ nest-asyncio==1.6.0 networkx==3.4.2 nodeenv==1.9.1 notebook-shim==0.2.4 -numpy==2.2.1 +numpy==2.2.2 oauth2client==4.1.3 oauthlib==3.2.2 objgraph==3.6.2 ordered-set==4.1.0 -orjson==3.10.14 +orjson==3.10.15 overrides==7.7.0 packaging==24.2 pandas==2.2.3 @@ -201,10 +201,10 @@ pillow==11.1.0 pip==24.3.1 platformdirs==4.3.6 pluggy==1.5.0 -polars==1.19.0 +polars==1.20.0 -e examples/project_fully_featured prometheus-client==0.21.1 -prompt-toolkit==3.0.48 +prompt-toolkit==3.0.50 propcache==0.2.1 proto-plus==1.25.0 protobuf==5.29.3 @@ -224,7 +224,7 @@ pyjwt==2.10.1 pylint==3.3.3 pyopenssl==24.3.0 pyparsing==3.2.1 -pyproject-api==1.8.0 +pyproject-api==1.9.0 pyright==1.1.379 pyspark==3.5.4 pytest==8.3.4 @@ -242,7 +242,7 @@ pytz==2024.2 pyyaml==6.0.2 pyzmq==26.2.0 rapidfuzz==3.11.0 -referencing==0.35.1 +referencing==0.36.1 requests==2.32.3 requests-oauthlib==2.0.0 requests-toolbelt==1.0.0 @@ -253,7 +253,7 @@ rich==13.9.4 rpds-py==0.22.3 rsa==4.9 s3fs==2024.3.0 -s3transfer==0.10.4 +s3transfer==0.11.1 scikit-learn==1.6.1 scipy==1.15.1 seaborn==0.13.2 @@ -269,12 +269,12 @@ snowplow-tracker==1.0.4 sortedcontainers==2.4.0 soupsieve==2.6 sqlalchemy==1.4.54 -sqlglot==26.1.3 -sqlglotrs==0.3.4 +sqlglot==26.2.1 +sqlglotrs==0.3.5 sqlparse==0.5.3 stack-data==0.6.3 starlette==0.45.2 -structlog==24.4.0 +structlog==25.1.0 syrupy==4.8.1 tabulate==0.9.0 terminado==0.18.1 @@ -304,7 +304,7 @@ types-python-dateutil==2.9.0.20241206 types-pytz==2024.2.0.20241221 types-pyyaml==6.0.12.20241230 types-requests==2.32.0.20241016 -types-s3transfer==0.10.4 +types-s3transfer==0.11.1 types-setuptools==75.8.0.20250110 types-simplejson==3.19.0.20241221 types-six==1.17.0.20241205 @@ -321,15 +321,15 @@ uritemplate==4.1.1 urllib3==2.3.0 uvicorn==0.34.0 uvloop==0.21.0 -virtualenv==20.28.1 +virtualenv==20.29.1 watchdog==5.0.3 watchfiles==1.0.4 wcwidth==0.2.13 webcolors==24.11.1 webencodings==0.5.1 websocket-client==1.8.0 -websockets==14.1 +websockets==14.2 wheel==0.45.1 -wrapt==1.17.1 +wrapt==1.17.2 yarl==1.18.3 zipp==3.21.0 diff --git a/pyright/master/requirements-pinned.txt b/pyright/master/requirements-pinned.txt index 1a69e90ecf825..97f66c1c5b946 100644 --- a/pyright/master/requirements-pinned.txt +++ b/pyright/master/requirements-pinned.txt @@ -1,13 +1,13 @@ -acryl-datahub==0.15.0.1 +acryl-datahub==0.15.0.3 agate==1.9.1 aiofile==3.9.0 aiohappyeyeballs==2.4.4 aiohttp==3.10.11 aiohttp-retry==2.8.3 -aioresponses==0.7.7 +aioresponses==0.7.8 aiosignal==1.3.2 alabaster==1.0.0 -alembic==1.14.0 +alembic==1.14.1 altair==4.2.2 amqp==5.3.1 annotated-types==0.7.0 @@ -27,16 +27,12 @@ apeye-core==1.1.5 apispec==6.8.1 appnope==0.1.4 argcomplete==3.5.3 -argon2-cffi==23.1.0 -argon2-cffi-bindings==21.2.0 -arrow==1.3.0 asgiref==3.8.1 asn1crypto==1.5.1 -e examples/assets_dynamic_partitions -e examples/assets_pandas_pyspark asttokens==3.0.0 -async-lru==2.0.4 -atproto==0.0.56 +atproto==0.0.57 attrs==24.3.0 autodocsumm==0.2.14 autoflake==2.3.1 @@ -58,10 +54,10 @@ billiard==4.2.1 bleach==6.2.0 blinker==1.9.0 bokeh==3.6.2 -boto3==1.35.97 -boto3-stubs-lite==1.35.70 -botocore==1.35.97 -botocore-stubs==1.35.97 +boto3==1.36.2 +boto3-stubs-lite==1.36.2 +botocore==1.36.2 +botocore-stubs==1.36.2 buildkite-test-collector==0.1.9 cachecontrol==0.14.2 cached-property==2.0.1 @@ -73,7 +69,7 @@ cattrs==23.1.2 celery==5.4.0 certifi==2024.12.14 cffi==1.17.1 -cfn-lint==1.22.4 +cfn-lint==1.22.5 chardet==5.2.0 charset-normalizer==3.4.1 click==8.1.8 @@ -83,7 +79,7 @@ click-plugins==1.1.1 click-repl==0.3.0 click-spinner==0.1.10 clickclick==20.10.2 -cloudpickle==3.1.0 +cloudpickle==3.1.1 colorama==0.4.6 coloredlogs==14.0 colorlog==4.8.0 @@ -113,7 +109,6 @@ daff==1.3.46 -e python_modules/libraries/dagster-celery-k8s -e python_modules/libraries/dagster-census -e python_modules/libraries/dagster-components -dagster-modal==0.0.2 -e python_modules/libraries/dagster-dask -e python_modules/libraries/dagster-databricks -e python_modules/libraries/dagster-datadog @@ -144,6 +139,7 @@ dagster-modal==0.0.2 -e python_modules/libraries/dagster-looker -e python_modules/libraries/dagster-managed-elements -e python_modules/libraries/dagster-mlflow +dagster-modal==0.0.2 -e python_modules/libraries/dagster-msteams -e python_modules/libraries/dagster-mysql -e python_modules/libraries/dagster-openai @@ -175,12 +171,10 @@ dagster-modal==0.0.2 -e python_modules/libraries/dagster-wandb -e python_modules/dagster-webserver -e python_modules/libraries/dagstermill -dask==2024.12.1 -dask-expr==1.1.21 +dask==2025.1.0 dask-jobqueue==0.9.0 dask-kubernetes==2022.9.0 dask-yarn==0.9 -databricks-cli==0.18.0 databricks-sdk==0.17.0 dataclasses-json==0.6.7 datadog==0.50.2 @@ -193,7 +187,7 @@ dbt-duckdb==1.9.1 -e examples/starlift-demo dbt-extractor==0.5.1 dbt-semantic-interfaces==0.7.4 -debugpy==1.8.11 +debugpy==1.8.12 decopatch==1.4.10 decorator==5.1.1 deepdiff==7.0.1 @@ -204,7 +198,7 @@ deprecated==1.2.15 dict2css==0.3.0.post1 dill==0.3.9 distlib==0.3.9 -distributed==2024.12.1 +distributed==2025.1.0 distro==1.9.0 -e examples/experimental/dagster-dlift/kitchen-sink dlt==1.5.0 @@ -239,14 +233,13 @@ flask-babel==2.0.0 flask-caching==2.3.0 flask-cors==5.0.0 flask-jwt-extended==4.7.1 -flask-limiter==3.10.0 +flask-limiter==3.10.1 flask-login==0.6.3 flask-session==0.5.0 flask-sqlalchemy==2.5.1 flask-wtf==1.2.2 flatbuffers==24.12.23 -fonttools==4.55.3 -fqdn==1.5.1 +fonttools==4.55.4 frozenlist==1.5.0 fsspec==2024.3.0 future==1.0.0 @@ -254,7 +247,7 @@ gitdb==4.0.12 gitpython==3.1.44 giturlparse==0.12.0 google-api-core==2.24.0 -google-api-python-client==2.158.0 +google-api-python-client==2.159.0 google-auth==2.37.0 google-auth-httplib2==0.2.0 google-auth-oauthlib==1.2.1 @@ -270,16 +263,16 @@ graphene==3.4.3 graphql-core==3.2.5 graphql-relay==3.2.0 graphviz==0.20.3 -great-expectations==0.18.22 +great-expectations==1.3.2 grpcio==1.69.0 grpcio-health-checking==1.69.0 grpcio-status==1.69.0 grpcio-tools==1.69.0 grpclib==0.4.7 -gunicorn==23.0.0 +gunicorn==21.2.0 h11==0.14.0 h2==4.1.0 -hexbytes==1.2.1 +hexbytes==1.3.0 hpack==4.0.0 html5lib==1.1 httpcore==1.0.7 @@ -290,7 +283,7 @@ httpx-sse==0.4.0 humanfriendly==10.0 humanize==4.11.0 hyperframe==6.0.1 -hypothesis==6.123.16 +hypothesis==6.124.1 idna==3.10 ijson==3.3.0 imagesize==1.4.1 @@ -301,10 +294,8 @@ iniconfig==2.0.0 ipykernel==6.29.5 ipython==8.31.0 ipython-genutils==0.2.0 -ipywidgets==8.1.5 iso8601==2.1.0 isodate==0.6.1 -isoduration==20.11.0 itsdangerous==2.2.0 jaraco-classes==3.4.0 jaraco-context==6.0.1 @@ -314,7 +305,6 @@ jinja2==3.1.5 jiter==0.8.2 jmespath==1.0.1 joblib==1.4.2 -json5==0.10.0 jsondiff==2.2.1 jsonpatch==1.33 jsonpath-ng==1.7.0 @@ -325,14 +315,7 @@ jsonschema-path==0.3.3 jsonschema-specifications==2024.10.1 jupyter-client==7.4.9 jupyter-core==5.7.2 -jupyter-events==0.11.0 -jupyter-lsp==2.2.5 -jupyter-server==2.15.0 -jupyter-server-terminals==0.5.3 -jupyterlab==4.3.4 jupyterlab-pygments==0.3.0 -jupyterlab-server==2.27.3 -jupyterlab-widgets==3.0.13 keyring==25.6.0 -e python_modules/libraries/dagster-airlift/kitchen-sink kiwisolver==1.4.8 @@ -342,14 +325,14 @@ kubernetes==31.0.0 kubernetes-asyncio==32.0.0 langchain==0.3.7 langchain-community==0.3.5 -langchain-core==0.3.29 +langchain-core==0.3.31 langchain-openai==0.2.5 langchain-text-splitters==0.3.5 langsmith==0.1.147 lazy-object-proxy==1.10.0 leather==0.4.0 libipld==3.0.0 -limits==4.0.0 +limits==4.0.1 linkify-it-py==2.0.3 lkml==1.3.6 locket==1.0.0 @@ -367,14 +350,15 @@ marshmallow-sqlalchemy==0.26.1 mashumaro==3.14 matplotlib==3.10.0 matplotlib-inline==0.1.3 -mbstrdecoder==1.1.3 +mbstrdecoder==1.1.4 mdit-py-plugins==0.4.2 mdurl==0.1.2 mistune==3.1.0 mixpanel==4.10.1 -mlflow==1.27.0 -modal==0.72.10 -more-itertools==10.5.0 +mlflow==2.12.1 +modal==0.72.36 +monotonic==1.6 +more-itertools==10.6.0 morefs==0.2.2 moto==4.2.14 mpmath==1.3.0 @@ -382,16 +366,16 @@ msal==1.31.1 msal-extensions==1.2.0 msgpack==1.1.0 multidict==6.1.0 -mypy-boto3-ecs==1.35.93 -mypy-boto3-emr==1.35.93 -mypy-boto3-emr-containers==1.35.93 -mypy-boto3-emr-serverless==1.35.93 -mypy-boto3-glue==1.35.93 -mypy-boto3-logs==1.35.93 -mypy-boto3-s3==1.35.93 +mypy-boto3-ecs==1.36.1 +mypy-boto3-emr==1.36.0 +mypy-boto3-emr-containers==1.36.0 +mypy-boto3-emr-serverless==1.36.0 +mypy-boto3-glue==1.36.0 +mypy-boto3-logs==1.36.0 +mypy-boto3-s3==1.36.0 mypy-extensions==1.0.0 mypy-protobuf==3.6.0 -mysql-connector-python==9.1.0 +mysql-connector-python==9.2.0 natsort==8.4.0 nbclient==0.10.2 nbconvert==7.16.5 @@ -400,8 +384,6 @@ nest-asyncio==1.6.0 networkx==3.4.2 nh3==0.2.20 nodeenv==1.9.1 -notebook==7.3.2 -notebook-shim==0.2.4 numpy==1.26.4 oauth2client==4.1.3 oauthlib==3.2.2 @@ -409,7 +391,7 @@ objgraph==3.6.2 onnx==1.17.0 onnxconverter-common==1.13.0 onnxruntime==1.20.1 -openai==1.59.7 +openai==1.59.9 openapi-schema-validator==0.6.3 openapi-spec-validator==0.7.1 opentelemetry-api==1.29.0 @@ -421,11 +403,10 @@ opentelemetry-proto==1.29.0 opentelemetry-sdk==1.29.0 opentelemetry-semantic-conventions==0.50b0 ordered-set==4.1.0 -orjson==3.10.14 +orjson==3.10.15 outcome==1.3.0.post0 -overrides==7.7.0 packaging==24.2 -pandas==2.2.3 +pandas==2.1.4 pandas-gbq==0.26.1 pandas-stubs==2.2.3.241126 pandera==0.22.1 @@ -449,16 +430,16 @@ platformdirs==4.3.6 plotly==5.24.1 pluggy==1.5.0 ply==3.11 -polars==1.19.0 +polars==1.20.0 portalocker==2.10.1 +posthog==3.8.4 premailer==3.10.0 prison==0.2.1 progressbar2==4.5.0 -e examples/project_atproto_dashboard -e examples/project_dagster_modal_pipes prometheus-client==0.21.1 -prometheus-flask-exporter==0.23.1 -prompt-toolkit==3.0.48 +prompt-toolkit==3.0.50 propcache==0.2.1 proto-plus==1.25.0 protobuf==5.29.3 @@ -468,7 +449,7 @@ ptyprocess==0.7.0 pure-eval==0.2.3 py-partiql-parser==0.5.0 py4j==0.10.9.7 -pyarrow==18.1.0 +pyarrow==15.0.2 pyarrow-hotfix==0.6 pyasn1==0.6.1 pyasn1-modules==0.4.1 @@ -485,7 +466,7 @@ pynacl==1.5.0 pyopenssl==24.3.0 pyparsing==3.2.1 pypd==1.1.0 -pyproject-api==1.8.0 +pyproject-api==1.9.0 pyright==1.1.379 pysocks==1.7.1 pyspark==3.5.4 @@ -526,24 +507,22 @@ requirements-parser==0.11.0 responses==0.23.1 rfc3339-validator==0.1.4 rfc3986==2.0.0 -rfc3986-validator==0.1.1 rich==13.9.4 rich-argparse==1.6.0 rpds-py==0.22.3 rsa==4.9 -ruamel-yaml==0.17.40 +ruamel-yaml==0.18.10 ruamel-yaml-clib==0.2.12 -ruff==0.9.1 -s3transfer==0.10.4 +ruff==0.9.2 +s3transfer==0.11.1 scikit-learn==1.6.1 scipy==1.15.1 scrapbook==0.5.0 sdf-cli==0.3.23 seaborn==0.13.2 -selenium==4.27.1 +selenium==4.28.0 semver==3.0.2 -send2trash==1.8.3 -sentry-sdk==2.19.2 +sentry-sdk==2.20.0 setproctitle==1.3.4 setuptools==70.3.0 sgmllib3k==1.0.0 @@ -554,18 +533,18 @@ six==1.17.0 skein==0.8.2 skl2onnx==1.18.0 slack-sdk==3.34.0 -sling==1.3.4 -sling-mac-arm64==1.3.4 +sling==1.3.5 +sling-mac-arm64==1.3.5 smmap==5.0.2 sniffio==1.3.1 snowballstemmer==2.2.0 snowflake-connector-python==3.12.4 -snowflake-sqlalchemy==1.7.2 +snowflake-sqlalchemy==1.7.3 snowplow-tracker==1.0.4 sortedcontainers==2.4.0 soupsieve==2.6 sphinx==8.1.3 -sphinx-autodoc-typehints==3.0.0 +sphinx-autodoc-typehints==3.0.1 sphinx-jinja2-compat==0.3.0 sphinx-prompt==1.9.0 sphinx-tabs==3.4.5 @@ -579,31 +558,30 @@ sphinxcontrib-serializinghtml==2.0.0 sqlalchemy==1.4.54 sqlalchemy-jsonfield==1.0.2 sqlalchemy-utils==0.41.2 -sqlglot==26.1.3 -sqlglotrs==0.3.4 +sqlglot==26.2.1 +sqlglotrs==0.3.5 sqlparse==0.5.3 sshpubkeys==3.3.1 sshtunnel==0.4.0 stack-data==0.6.3 starlette==0.41.3 -structlog==24.4.0 +structlog==25.1.0 sympy==1.13.1 synchronicity==0.9.8 syrupy==4.8.1 -tableauserverclient==0.35 +tableauserverclient==0.36 tabledata==1.3.4 tabulate==0.9.0 tblib==3.0.0 tenacity==9.0.0 termcolor==2.5.0 -terminado==0.18.1 text-unidecode==1.3 threadpoolctl==3.5.0 tiktoken==0.8.0 tinycss2==1.4.0 toml==0.10.2 tomli==2.2.1 -tomli-w==1.1.0 +tomli-w==1.2.0 tomlkit==0.13.2 toolz==1.0.0 toposort==1.10 @@ -622,6 +600,7 @@ twine==6.0.1 typeguard==4.4.1 typepy==1.3.4 typer==0.15.1 +typer-di==0.1.2 types-awscrt==0.23.6 types-backports==0.1.3 types-certifi==2021.10.8.3 @@ -636,7 +615,7 @@ types-python-dateutil==2.9.0.20241206 types-pytz==2024.2.0.20241221 types-pyyaml==6.0.12.20241230 types-requests==2.32.0.20241016 -types-s3transfer==0.10.4 +types-s3transfer==0.11.1 types-setuptools==75.8.0.20250110 types-simplejson==3.19.0.20241221 types-six==1.17.0.20241205 @@ -651,36 +630,33 @@ tzlocal==5.2 uc-micro-py==1.0.3 unicodecsv==0.14.1 universal-pathlib==0.2.6 -uri-template==1.3.0 uritemplate==4.1.1 urllib3==2.3.0 -e examples/use_case_repository uvicorn==0.34.0 uvloop==0.21.0 vine==5.1.0 -virtualenv==20.28.1 -wandb==0.19.2 +virtualenv==20.29.1 +wandb==0.19.4 watchdog==5.0.3 watchfiles==1.0.4 wcwidth==0.2.13 -webcolors==24.11.1 webencodings==0.5.1 websocket-client==1.8.0 websockets==13.1 werkzeug==2.2.3 wheel==0.45.1 -widgetsnbextension==4.0.13 -e examples/with_great_expectations -e examples/with_openai -e examples/with_pyspark -e examples/with_wandb wordcloud==1.9.4 -wrapt==1.17.1 +wrapt==1.17.2 wsproto==1.2.0 wtforms==3.0.1 xgboost==2.1.3 xmltodict==0.12.0 -xyzservices==2024.9.0 +xyzservices==2025.1.0 yagmail==0.15.293 yarl==1.18.3 zict==3.0.0 diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/__init__.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/__init__.py index d6ce83e69f707..d3778feab65c8 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/__init__.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/__init__.py @@ -1,62 +1,56 @@ from pathlib import Path +from typing import Annotated import click +import typer +from typer_di import Depends, TyperDI from dagster_dg.cli.code_location import code_location_group from dagster_dg.cli.component import component_group from dagster_dg.cli.component_type import component_type_group from dagster_dg.cli.deployment import deployment_group -from dagster_dg.cli.global_options import dg_global_options +from dagster_dg.cli.global_options import typer_dg_global_options from dagster_dg.component import RemoteComponentRegistry from dagster_dg.config import normalize_cli_config from dagster_dg.context import DgContext -from dagster_dg.utils import DgClickGroup, exit_with_error +from dagster_dg.utils import exit_with_error from dagster_dg.version import __version__ DG_CLI_MAX_OUTPUT_WIDTH = 120 def create_dg_cli(): - @click.group( - name="dg", - commands={ - "code-location": code_location_group, - "deployment": deployment_group, - "component": component_group, - "component-type": component_type_group, - }, - context_settings={ - "max_content_width": DG_CLI_MAX_OUTPUT_WIDTH, - "help_option_names": ["-h", "--help"], - }, - invoke_without_command=True, - cls=DgClickGroup, - ) - @dg_global_options - @click.option( - "--clear-cache", - is_flag=True, - help="Clear the cache.", - default=False, - ) - @click.option( - "--rebuild-component-registry", - is_flag=True, - help=( - "Recompute and cache the set of available component types for the current environment." - " Note that this also happens automatically whenever the cache is detected to be stale." - ), - default=False, - ) - @click.version_option(__version__, "--version", "-v") - @click.pass_context - def group( - context: click.Context, - clear_cache: bool, - rebuild_component_registry: bool, - **global_options: object, + app = TyperDI(name="dg") + # app = typer.Typer(name="dg") + + app.add_typer(code_location_group, name="code-location") + app.add_typer(deployment_group, name="deployment") + # app.add_typer(component_group, name="component") + app.add_typer(component_type_group, name="component-type") + + # context_settings={ + # "max_content_width": DG_CLI_MAX_OUTPUT_WIDTH, + # "help_option_names": ["-h", "--help"], + # }, + # invoke_without_command=True, + + @app.callback() + def callback( + context: typer.Context, + clear_cache: Annotated[bool, typer.Option(help="Clear the cache.")] = False, + rebuild_component_registry: Annotated[ + bool, + typer.Option( + help="Recompute and cache the set of available component types for the current environment. Note that this also happens automatically whenever the cache is detected to be stale.", + ), + ] = False, + version: Annotated[bool, typer.Option(help="Show the version and exit.")] = False, + global_options: dict[str, object] = Depends(typer_dg_global_options), ): """CLI for working with Dagster components.""" + if version: + click.echo(f"dg version: {__version__}") + context.exit(0) if clear_cache and rebuild_component_registry: exit_with_error("Cannot specify both --clear-cache and --rebuild-component-registry.") elif clear_cache: @@ -75,7 +69,15 @@ def group( click.echo(context.get_help()) context.exit(0) - return group + typer_click_object = typer.main.get_group(app) + typer_click_object.context_settings = { + "max_content_width": DG_CLI_MAX_OUTPUT_WIDTH, + "help_option_names": ["-h", "--help"], + } + typer_click_object.invoke_without_command = True + typer_click_object.add_command(component_group) + + return typer_click_object def _rebuild_component_registry(dg_context: DgContext): diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/code_location.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/code_location.py index 2764a675ed54a..3f903b365ef2d 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/code_location.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/code_location.py @@ -1,19 +1,20 @@ import os from pathlib import Path -from typing import Optional +from typing import Annotated import click +import typer +from typer_di import Depends, TyperDI -from dagster_dg.cli.global_options import dg_global_options +from dagster_dg.cli.global_options import typer_dg_global_options from dagster_dg.config import normalize_cli_config from dagster_dg.context import DgContext from dagster_dg.scaffold import scaffold_code_location -from dagster_dg.utils import DgClickCommand, DgClickGroup, exit_with_error +from dagster_dg.utils import exit_with_error - -@click.group(name="code-location", cls=DgClickGroup) -def code_location_group(): - """Commands for operating code location directories.""" +code_location_group = TyperDI( + name="code-location", help="Commands for operating on code location directories." +) # ######################## @@ -21,34 +22,27 @@ def code_location_group(): # ######################## -@code_location_group.command(name="scaffold", cls=DgClickCommand) -@click.argument("name", type=str) -@click.option( - "--use-editable-dagster", - type=str, - flag_value="TRUE", - is_flag=False, - default=None, - help=( - "Install Dagster package dependencies from a local Dagster clone. Accepts a path to local Dagster clone root or" - " may be set as a flag (no value is passed). If set as a flag," - " the location of the local Dagster clone will be read from the `DAGSTER_GIT_REPO_DIR` environment variable." - ), -) -@click.option( - "--skip-venv", - is_flag=True, - default=False, - help="Do not create a virtual environment for the code location.", -) -@dg_global_options -@click.pass_context +@code_location_group.command(name="scaffold") def code_location_scaffold_command( context: click.Context, name: str, - use_editable_dagster: Optional[str], - skip_venv: bool, - **global_options: object, + use_editable_dagster: Annotated[ + bool, + typer.Option( + help=( + "Install Dagster package dependencies from a local Dagster clone. Accepts a path to local Dagster clone root or" + " may be set as a flag (no value is passed). If set as a flag," + " the location of the local Dagster clone will be read from the `DAGSTER_GIT_REPO_DIR` environment variable." + ), + ), + ] = False, + skip_venv: Annotated[ + bool, + typer.Option( + help="Do not create a virtual environment for the code location.", + ), + ] = False, + global_options: dict[str, object] = Depends(typer_dg_global_options), ) -> None: """Scaffold a Dagster code location file structure and a uv-managed virtual environment scoped to the code location. @@ -83,14 +77,12 @@ def code_location_scaffold_command( else: code_location_path = Path.cwd() / name - if use_editable_dagster == "TRUE": + if use_editable_dagster: if not os.environ.get("DAGSTER_GIT_REPO_DIR"): exit_with_error( "The `--use-editable-dagster` flag requires the `DAGSTER_GIT_REPO_DIR` environment variable to be set." ) editable_dagster_root = os.environ["DAGSTER_GIT_REPO_DIR"] - elif use_editable_dagster: # a string value was passed - editable_dagster_root = use_editable_dagster else: editable_dagster_root = None @@ -104,10 +96,11 @@ def code_location_scaffold_command( # ######################## -@code_location_group.command(name="list", cls=DgClickCommand) -@dg_global_options -@click.pass_context -def code_location_list_command(context: click.Context, **global_options: object) -> None: +@code_location_group.command(name="list") +def code_location_list_command( + context: typer.Context, + global_options: dict[str, object] = Depends(typer_dg_global_options), +) -> None: """List code locations in the current deployment.""" cli_config = normalize_cli_config(global_options, context) dg_context = DgContext.from_config_file_discovery_and_cli_config(Path.cwd(), cli_config) diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/component.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/component.py index 1ceae6078127d..181bec6be3eb8 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/component.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/component.py @@ -233,7 +233,10 @@ def scaffold_component_command( @component_group.command(name="list", cls=DgClickCommand) @dg_global_options @click.pass_context -def component_list_command(context: click.Context, **global_options: object) -> None: +def component_list_command( + context: click.Context, + **global_options: object, +) -> None: """List Dagster component instances defined in the current code location.""" cli_config = normalize_cli_config(global_options, context) dg_context = DgContext.from_config_file_discovery_and_cli_config(Path.cwd(), cli_config) @@ -254,9 +257,7 @@ def component_list_command(context: click.Context, **global_options: object) -> @dg_global_options @click.pass_context def component_check_command( - context: click.Context, - paths: Sequence[str], - **global_options: object, + context: click.Context, paths: Sequence[str], **global_options: object ) -> None: """Check component files against their schemas, showing validation errors.""" cli_config = normalize_cli_config(global_options, context) diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/component_type.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/component_type.py index 3475be7565441..2e5086b159243 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/component_type.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/component_type.py @@ -1,35 +1,34 @@ import json from collections.abc import Mapping from pathlib import Path -from typing import Any +from typing import Annotated, Any import click +import typer +from typer_di import Depends, TyperDI -from dagster_dg.cli.global_options import dg_global_options +from dagster_dg.cli.global_options import typer_dg_global_options from dagster_dg.component import RemoteComponentRegistry from dagster_dg.config import normalize_cli_config from dagster_dg.context import DgContext from dagster_dg.docs import markdown_for_component_type, render_markdown_in_browser from dagster_dg.scaffold import scaffold_component_type -from dagster_dg.utils import DgClickCommand, DgClickGroup, exit_with_error - - -@click.group(name="component-type", cls=DgClickGroup) -def component_type_group(): - """Commands for operating on components types.""" +from dagster_dg.utils import exit_with_error +component_type_group = TyperDI( + name="component-type", help="Commands for operating on components types." +) # ######################## # ##### SCAFFOLD # ######################## -@component_type_group.command(name="scaffold", cls=DgClickCommand) -@click.argument("name", type=str) -@dg_global_options -@click.pass_context +@component_type_group.command(name="scaffold") def component_type_scaffold_command( - context: click.Context, name: str, **global_options: object + context: typer.Context, + name: str, + global_options: dict[str, object] = Depends(typer_dg_global_options), ) -> None: """Scaffold of a custom Dagster component type. @@ -53,14 +52,11 @@ def component_type_scaffold_command( # ######################## -@component_type_group.command(name="docs", cls=DgClickCommand) -@click.argument("component_type", type=str) -@dg_global_options -@click.pass_context +@component_type_group.command(name="docs") def component_type_docs_command( - context: click.Context, + context: typer.Context, component_type: str, - **global_options: object, + global_options: dict[str, object] = Depends(typer_dg_global_options), ) -> None: """Get detailed information on a registered Dagster component type.""" cli_config = normalize_cli_config(global_options, context) @@ -77,20 +73,14 @@ def component_type_docs_command( # ######################## -@component_type_group.command(name="info", cls=DgClickCommand) -@click.argument("component_type", type=str) -@click.option("--description", is_flag=True, default=False) -@click.option("--scaffold-params-schema", is_flag=True, default=False) -@click.option("--component-params-schema", is_flag=True, default=False) -@dg_global_options -@click.pass_context +@component_type_group.command(name="info") def component_type_info_command( - context: click.Context, + context: typer.Context, component_type: str, - description: bool, - scaffold_params_schema: bool, - component_params_schema: bool, - **global_options: object, + description: Annotated[bool, typer.Option(is_flag=True)] = False, + scaffold_params_schema: Annotated[bool, typer.Option(is_flag=True)] = False, + component_params_schema: Annotated[bool, typer.Option(is_flag=True)] = False, + global_options: dict[str, object] = Depends(typer_dg_global_options), ) -> None: """Get detailed information on a registered Dagster component type.""" cli_config = normalize_cli_config(global_options, context) @@ -144,10 +134,10 @@ def _serialize_json_schema(schema: Mapping[str, Any]) -> str: # ######################## -@component_type_group.command(name="list", cls=DgClickCommand) -@dg_global_options -@click.pass_context -def component_type_list(context: click.Context, **global_options: object) -> None: +@component_type_group.command(name="list") +def component_type_list( + context: typer.Context, global_options: dict[str, object] = Depends(typer_dg_global_options) +) -> None: """List registered Dagster components in the current code location environment.""" cli_config = normalize_cli_config(global_options, context) dg_context = DgContext.from_config_file_discovery_and_cli_config(Path.cwd(), cli_config) diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/deployment.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/deployment.py index c622a9c548b94..9edc5478ecd5b 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/deployment.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/deployment.py @@ -2,30 +2,30 @@ from pathlib import Path import click +import typer +from typer_di import Depends, TyperDI -from dagster_dg.cli.global_options import dg_global_options +from dagster_dg.cli.global_options import typer_dg_global_options from dagster_dg.config import normalize_cli_config from dagster_dg.context import DgContext from dagster_dg.scaffold import scaffold_deployment -from dagster_dg.utils import DgClickCommand, DgClickGroup, exit_with_error - - -@click.group(name="deployment", cls=DgClickGroup) -def deployment_group(): - """Commands for operating on deployment directories.""" +from dagster_dg.utils import exit_with_error +deployment_group = TyperDI( + name="deployment", help="Commands for operating on deployment directories." +) # ######################## # ##### SCAFFOLD # ######################## -@deployment_group.command(name="scaffold", cls=DgClickCommand) -@dg_global_options +@deployment_group.command(name="scaffold") @click.argument("path", type=Path) -@click.pass_context def deployment_scaffold_command( - context: click.Context, path: Path, **global_options: object + context: typer.Context, + path: Path, + global_options: dict[str, object] = Depends(typer_dg_global_options), ) -> None: """Scaffold a Dagster deployment file structure. diff --git a/python_modules/libraries/dagster-dg/dagster_dg/cli/global_options.py b/python_modules/libraries/dagster-dg/dagster_dg/cli/global_options.py index 0f0bdc1d0ba5b..48c075b148a83 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/cli/global_options.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/cli/global_options.py @@ -1,8 +1,9 @@ from collections.abc import Sequence from pathlib import Path -from typing import Any, Callable, Optional, TypeVar, Union +from typing import Annotated, Any, Callable, Optional, TypeVar, Union import click +import typer from dagster_dg.config import DgConfig @@ -46,6 +47,47 @@ } +def typer_dg_global_options( + cache_dir: Annotated[ + Path, + typer.Option( + help="Specify a directory to use for the cache.", + ), + ] = DgConfig.cache_dir, + disable_cache: Annotated[ + bool, + typer.Option( + help="Disable the cache.", + ), + ] = DgConfig.disable_cache, + verbose: Annotated[ + bool, + typer.Option( + help="Enable verbose output for debugging.", + ), + ] = DgConfig.verbose, + builtin_component_lib: Annotated[ + str, + typer.Option( + help="Specify a builitin component library to use.", + ), + ] = DgConfig.builtin_component_lib, + use_dg_managed_environment: Annotated[ + bool, + typer.Option( + help="Enable management of the virtual environment with uv.", + ), + ] = DgConfig.use_dg_managed_environment, +) -> dict[str, object]: + return { + "cache_dir": cache_dir, + "disable_cache": disable_cache, + "verbose": verbose, + "builtin_component_lib": builtin_component_lib, + "use_dg_managed_environment": use_dg_managed_environment, + } + + def dg_global_options( fn: Optional[T_Command] = None, *, names: Optional[Sequence[str]] = None ) -> Union[T_Command, Callable[[T_Command], T_Command]]: diff --git a/python_modules/libraries/dagster-dg/dagster_dg/utils.py b/python_modules/libraries/dagster-dg/dagster_dg/utils.py index e3786504cbd28..0056c0b40133b 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg/utils.py +++ b/python_modules/libraries/dagster-dg/dagster_dg/utils.py @@ -39,7 +39,10 @@ def ensure_loadable_path(path: Path) -> Iterator[None]: def is_package_installed(package_name: str) -> bool: - return bool(importlib.util.find_spec(package_name)) + try: + return bool(importlib.util.find_spec(package_name)) + except ModuleNotFoundError: + return False def get_path_for_package(package_name: str) -> str: diff --git a/python_modules/libraries/dagster-dg/dagster_dg_tests/cli_tests/test_code_location_commands.py b/python_modules/libraries/dagster-dg/dagster_dg_tests/cli_tests/test_code_location_commands.py index 6702e4990742d..af5af8701a676 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg_tests/cli_tests/test_code_location_commands.py +++ b/python_modules/libraries/dagster-dg/dagster_dg_tests/cli_tests/test_code_location_commands.py @@ -28,13 +28,18 @@ # and returns the local version of the package. -def test_code_location_scaffold_inside_deployment_success(monkeypatch) -> None: +def test_code_location_scaffold_inside_deployment_success() -> None: # Remove when we are able to test without editable install dagster_git_repo_dir = discover_git_root(Path(__file__)) - monkeypatch.setenv("DAGSTER_GIT_REPO_DIR", str(dagster_git_repo_dir)) - with ProxyRunner.test() as runner, isolated_example_deployment_foo(runner): + with ( + pytest.MonkeyPatch.context() as mp, + ProxyRunner.test() as runner, + isolated_example_deployment_foo(runner), + ): + mp.setenv("DAGSTER_GIT_REPO_DIR", str(dagster_git_repo_dir)) result = runner.invoke("code-location", "scaffold", "foo-bar", "--use-editable-dagster") + # result = runner.invoke("code-location", "scaffold", "foo-bar") assert_runner_result(result) assert Path("code_locations/foo-bar").exists() assert Path("code_locations/foo-bar/foo_bar").exists() @@ -81,14 +86,10 @@ def test_code_location_scaffold_outside_deployment_success(monkeypatch) -> None: assert Path("foo-bar/uv.lock").exists() -@pytest.mark.parametrize("mode", ["env_var", "arg"]) -def test_code_location_scaffold_editable_dagster_success(mode: str, monkeypatch) -> None: +def test_code_location_scaffold_editable_dagster_success(monkeypatch) -> None: dagster_git_repo_dir = discover_git_root(Path(__file__)) - if mode == "env_var": - monkeypatch.setenv("DAGSTER_GIT_REPO_DIR", str(dagster_git_repo_dir)) - editable_args = ["--use-editable-dagster", "--"] - else: - editable_args = ["--use-editable-dagster", str(dagster_git_repo_dir)] + monkeypatch.setenv("DAGSTER_GIT_REPO_DIR", str(dagster_git_repo_dir)) + editable_args = ["--use-editable-dagster", "--"] with ProxyRunner.test() as runner, isolated_example_deployment_foo(runner): result = runner.invoke("code-location", "scaffold", *editable_args, "foo-bar") assert_runner_result(result) diff --git a/python_modules/libraries/dagster-dg/dagster_dg_tests/utils.py b/python_modules/libraries/dagster-dg/dagster_dg_tests/utils.py index cd3806c32f30c..5c8f6fc96a5a5 100644 --- a/python_modules/libraries/dagster-dg/dagster_dg_tests/utils.py +++ b/python_modules/libraries/dagster-dg/dagster_dg_tests/utils.py @@ -16,6 +16,7 @@ cli as dg_cli, ) from dagster_dg.utils import discover_git_root, pushd +from pytest import MonkeyPatch from typing_extensions import Self @@ -36,30 +37,30 @@ def isolated_example_code_location_foo_bar( ) -> Iterator[None]: runner = ProxyRunner(runner) if isinstance(runner, CliRunner) else runner dagster_git_repo_dir = str(discover_git_root(Path(__file__))) - if in_deployment: - with isolated_example_deployment_foo(runner): - runner.invoke( - "code-location", - "scaffold", - "--use-editable-dagster", - dagster_git_repo_dir, - *(["--no-use-dg-managed-environment"] if skip_venv else []), - "foo-bar", - ) - with clear_module_from_cache("foo_bar"), pushd("code_locations/foo-bar"): - yield - else: - with runner.isolated_filesystem(): - runner.invoke( - "code-location", - "scaffold", - "--use-editable-dagster", - dagster_git_repo_dir, - *(["--no-use-dg-managed-environment"] if skip_venv else []), - "foo-bar", - ) - with clear_module_from_cache("foo_bar"), pushd("foo-bar"): - yield + with MonkeyPatch.context() as mp: + mp.setenv("DAGSTER_GIT_REPO_DIR", dagster_git_repo_dir) + if in_deployment: + with isolated_example_deployment_foo(runner): + runner.invoke( + "code-location", + "scaffold", + "--use-editable-dagster", + *(["--no-use-dg-managed-environment"] if skip_venv else []), + "foo-bar", + ) + with clear_module_from_cache("foo_bar"), pushd("code_locations/foo-bar"): + yield + else: + with runner.isolated_filesystem(): + runner.invoke( + "code-location", + "scaffold", + "--use-editable-dagster", + *(["--no-use-dg-managed-environment"] if skip_venv else []), + "foo-bar", + ) + with clear_module_from_cache("foo_bar"), pushd("foo-bar"): + yield @contextmanager diff --git a/python_modules/libraries/dagster-dg/setup.py b/python_modules/libraries/dagster-dg/setup.py index aa2a825251696..c50744977f34c 100644 --- a/python_modules/libraries/dagster-dg/setup.py +++ b/python_modules/libraries/dagster-dg/setup.py @@ -34,6 +34,8 @@ def get_version() -> str: install_requires=[ "Jinja2", "tomli", + "typer", + "typer_di", "click>=8", "typing_extensions>=4.4.0,<5", "markdown",