Metadata-Version: 2.4
Name: recurvedata-lib
Version: 0.1.561
Summary: Common Library for ReOrc Data Platform
Author-email: Reorc Team <contact@recurvedata.com>
Requires-Dist: click<8.2
Requires-Dist: croniter
Requires-Dist: cytoolz
Requires-Dist: fsspec
Requires-Dist: httpx
Requires-Dist: jinja2
Requires-Dist: jsonschema
Requires-Dist: pendulum
Requires-Dist: pydantic
Requires-Dist: python-dateutil
Requires-Dist: sqlalchemy
Requires-Dist: sqlglot
Requires-Dist: typer
Provides-Extra: dbt
Requires-Dist: adlfs==2024.12.0; extra == 'dbt'
Requires-Dist: aenum==3.1.15; extra == 'dbt'
Requires-Dist: agate==1.9.1; extra == 'dbt'
Requires-Dist: aiobotocore==2.17.0; extra == 'dbt'
Requires-Dist: aiohappyeyeballs==2.4.4; extra == 'dbt'
Requires-Dist: aiohttp==3.10.5; extra == 'dbt'
Requires-Dist: aioitertools==0.12.0; extra == 'dbt'
Requires-Dist: aiooss2==0.2.10; extra == 'dbt'
Requires-Dist: aiosignal==1.3.2; extra == 'dbt'
Requires-Dist: aliyun-log-python-sdk==0.9.24; extra == 'dbt'
Requires-Dist: aliyun-python-sdk-core==2.16.0; extra == 'dbt'
Requires-Dist: aliyun-python-sdk-kms==2.16.5; extra == 'dbt'
Requires-Dist: annotated-types==0.7.0; extra == 'dbt'
Requires-Dist: anyio==4.8.0; extra == 'dbt'
Requires-Dist: asgiref==3.8.1; extra == 'dbt'
Requires-Dist: asn1crypto==1.5.1; extra == 'dbt'
Requires-Dist: astronomer-cosmos==1.6.0+recurve; extra == 'dbt'
Requires-Dist: asynch==0.2.5; extra == 'dbt'
Requires-Dist: attrs==24.3.0; extra == 'dbt'
Requires-Dist: azure-core==1.32.0; extra == 'dbt'
Requires-Dist: azure-datalake-store==0.0.53; extra == 'dbt'
Requires-Dist: azure-identity==1.19.0; extra == 'dbt'
Requires-Dist: azure-storage-blob==12.24.0; extra == 'dbt'
Requires-Dist: babel==2.16.0; extra == 'dbt'
Requires-Dist: backoff==2.2.1; extra == 'dbt'
Requires-Dist: bcrypt==4.2.1; extra == 'dbt'
Requires-Dist: beautifulsoup4==4.12.3; extra == 'dbt'
Requires-Dist: bitarray==3.0.0; extra == 'dbt'
Requires-Dist: boto3==1.35.93; extra == 'dbt'
Requires-Dist: botocore==1.35.93; extra == 'dbt'
Requires-Dist: cachetools==5.5.0; extra == 'dbt'
Requires-Dist: certifi==2024.12.14; extra == 'dbt'
Requires-Dist: cffi==1.17.1; extra == 'dbt'
Requires-Dist: chardet==5.2.0; extra == 'dbt'
Requires-Dist: charset-normalizer==3.4.1; extra == 'dbt'
Requires-Dist: ciso8601==2.3.2; extra == 'dbt'
Requires-Dist: click==8.1.8; extra == 'dbt'
Requires-Dist: clickhouse-cityhash==1.0.2.4; extra == 'dbt'
Requires-Dist: clickhouse-driver==0.2.9; extra == 'dbt'
Requires-Dist: clickhouse-sqlalchemy==0.3.2; extra == 'dbt'
Requires-Dist: colorama==0.4.6; extra == 'dbt'
Requires-Dist: confluent-kafka==2.12.2; extra == 'dbt'
Requires-Dist: cos-python-sdk-v5==1.9.33; extra == 'dbt'
Requires-Dist: crcmod==1.7; extra == 'dbt'
Requires-Dist: croniter==6.0.0; extra == 'dbt'
Requires-Dist: cryptography==44.0.0; extra == 'dbt'
Requires-Dist: cssselect==1.2.0; extra == 'dbt'
Requires-Dist: cssutils==2.11.1; extra == 'dbt'
Requires-Dist: cython==3.0.11; extra == 'dbt'
Requires-Dist: cytoolz==1.0.1; extra == 'dbt'
Requires-Dist: daff==1.3.46; extra == 'dbt'
Requires-Dist: dateparser==1.2.2; extra == 'dbt'
Requires-Dist: db-dtypes==1.3.1; extra == 'dbt'
Requires-Dist: dbt-adapters==1.9.0; extra == 'dbt'
Requires-Dist: dbt-bigquery==1.8.3; extra == 'dbt'
Requires-Dist: dbt-common==1.12.0; extra == 'dbt'
Requires-Dist: dbt-core==1.8.0; extra == 'dbt'
Requires-Dist: dbt-doris==0.3.4+recurve.11; extra == 'dbt'
Requires-Dist: dbt-duckdb==1.8.4; extra == 'dbt'
Requires-Dist: dbt-extractor==0.5.1; extra == 'dbt'
Requires-Dist: dbt-fabric==1.9.4; extra == 'dbt'
Requires-Dist: dbt-impala==1.8.0; extra == 'dbt'
Requires-Dist: dbt-mysql==1.8.0+recurve.1; extra == 'dbt'
Requires-Dist: dbt-postgres==1.8.2; extra == 'dbt'
Requires-Dist: dbt-redshift==1.8.1; extra == 'dbt'
Requires-Dist: dbt-semantic-interfaces==0.5.1; extra == 'dbt'
Requires-Dist: dbt-starrocks==1.7.0; extra == 'dbt'
Requires-Dist: deepdiff==7.0.1; extra == 'dbt'
Requires-Dist: deprecated==1.2.15; extra == 'dbt'
Requires-Dist: distlib==0.3.9; extra == 'dbt'
Requires-Dist: dnspython==2.7.0; extra == 'dbt'
Requires-Dist: duckdb==1.1.3; extra == 'dbt'
Requires-Dist: elastic-transport==8.17.0; extra == 'dbt'
Requires-Dist: elasticsearch==8.17.0; extra == 'dbt'
Requires-Dist: emails==0.6; extra == 'dbt'
Requires-Dist: et-xmlfile==2.0.0; extra == 'dbt'
Requires-Dist: fastapi==0.115.6; extra == 'dbt'
Requires-Dist: filelock==3.16.1; extra == 'dbt'
Requires-Dist: frozenlist==1.5.0; extra == 'dbt'
Requires-Dist: fsspec==2024.12.0; extra == 'dbt'
Requires-Dist: future==1.0.0; extra == 'dbt'
Requires-Dist: google-api-core==2.24.0; extra == 'dbt'
Requires-Dist: google-auth-oauthlib==1.2.1; extra == 'dbt'
Requires-Dist: google-auth==2.37.0; extra == 'dbt'
Requires-Dist: google-cloud-bigquery-storage==2.27.0; extra == 'dbt'
Requires-Dist: google-cloud-bigquery==3.27.0; extra == 'dbt'
Requires-Dist: google-cloud-core==2.4.1; extra == 'dbt'
Requires-Dist: google-cloud-dataproc==5.16.0; extra == 'dbt'
Requires-Dist: google-cloud-storage==2.19.0; extra == 'dbt'
Requires-Dist: google-crc32c==1.6.0; extra == 'dbt'
Requires-Dist: google-resumable-media==2.7.2; extra == 'dbt'
Requires-Dist: googleapis-common-protos==1.66.0; extra == 'dbt'
Requires-Dist: grpc-google-iam-v1==0.14.0; extra == 'dbt'
Requires-Dist: grpcio-status==1.62.3; extra == 'dbt'
Requires-Dist: grpcio==1.69.0; extra == 'dbt'
Requires-Dist: gspread==6.1.4; extra == 'dbt'
Requires-Dist: gunicorn==23.0.0; extra == 'dbt'
Requires-Dist: h11==0.14.0; extra == 'dbt'
Requires-Dist: httpcore==1.0.7; extra == 'dbt'
Requires-Dist: httpx==0.28.1; extra == 'dbt'
Requires-Dist: humanize==4.11.0; extra == 'dbt'
Requires-Dist: idna==3.10; extra == 'dbt'
Requires-Dist: importlib-metadata==6.11.0; extra == 'dbt'
Requires-Dist: impyla==0.18.0; extra == 'dbt'
Requires-Dist: isodate==0.6.1; extra == 'dbt'
Requires-Dist: jinja2==3.1.5; extra == 'dbt'
Requires-Dist: jmespath==0.10.0; extra == 'dbt'
Requires-Dist: jsonschema-specifications==2024.10.1; extra == 'dbt'
Requires-Dist: jsonschema==4.23.0; extra == 'dbt'
Requires-Dist: larksuite-oapi==1.0.34; extra == 'dbt'
Requires-Dist: leather==0.4.0; extra == 'dbt'
Requires-Dist: leb128==1.0.8; extra == 'dbt'
Requires-Dist: logbook==1.5.3; extra == 'dbt'
Requires-Dist: loguru==0.7.3; extra == 'dbt'
Requires-Dist: lxml==5.3.0; extra == 'dbt'
Requires-Dist: lz4==4.3.3; extra == 'dbt'
Requires-Dist: markdown-it-py==3.0.0; extra == 'dbt'
Requires-Dist: markupsafe==3.0.2; extra == 'dbt'
Requires-Dist: mashumaro==3.15; extra == 'dbt'
Requires-Dist: mdurl==0.1.2; extra == 'dbt'
Requires-Dist: minimal-snowplow-tracker==0.0.2; extra == 'dbt'
Requires-Dist: more-itertools==10.5.0; extra == 'dbt'
Requires-Dist: msal-extensions==1.2.0; extra == 'dbt'
Requires-Dist: msal==1.31.1; extra == 'dbt'
Requires-Dist: msgpack==1.1.0; extra == 'dbt'
Requires-Dist: multidict==6.1.0; extra == 'dbt'
Requires-Dist: mysql-connector-python==9.1.0; extra == 'dbt'
Requires-Dist: networkx==3.4.2; extra == 'dbt'
Requires-Dist: numpy==2.2.1; extra == 'dbt'
Requires-Dist: oauthlib==3.2.2; extra == 'dbt'
Requires-Dist: openpyxl==3.1.5; extra == 'dbt'
Requires-Dist: opentelemetry-api==1.29.0; extra == 'dbt'
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.15.0; extra == 'dbt'
Requires-Dist: opentelemetry-proto==1.15.0; extra == 'dbt'
Requires-Dist: opentelemetry-sdk==1.29.0; extra == 'dbt'
Requires-Dist: opentelemetry-semantic-conventions==0.50b0; extra == 'dbt'
Requires-Dist: ordered-set==4.1.0; extra == 'dbt'
Requires-Dist: orjson==3.10.14; extra == 'dbt'
Requires-Dist: oss2==2.18.1; extra == 'dbt'
Requires-Dist: ossfs==2023.12.0; extra == 'dbt'
Requires-Dist: packaging==24.2; extra == 'dbt'
Requires-Dist: pandas==2.2.3; extra == 'dbt'
Requires-Dist: paramiko==3.5.0; extra == 'dbt'
Requires-Dist: parsedatetime==2.6; extra == 'dbt'
Requires-Dist: pathspec==0.12.1; extra == 'dbt'
Requires-Dist: pendulum==3.0.0; extra == 'dbt'
Requires-Dist: platformdirs==4.3.6; extra == 'dbt'
Requires-Dist: portalocker==2.10.1; extra == 'dbt'
Requires-Dist: premailer==3.10.0; extra == 'dbt'
Requires-Dist: propcache==0.2.1; extra == 'dbt'
Requires-Dist: proto-plus==1.25.0; extra == 'dbt'
Requires-Dist: protobuf==4.25.5; extra == 'dbt'
Requires-Dist: psycopg2-binary==2.9.10; extra == 'dbt'
Requires-Dist: pure-sasl==0.6.2; extra == 'dbt'
Requires-Dist: pyarrow==18.1.0; extra == 'dbt'
Requires-Dist: pyasn1-modules==0.4.1; extra == 'dbt'
Requires-Dist: pyasn1==0.6.1; extra == 'dbt'
Requires-Dist: pycparser==2.22; extra == 'dbt'
Requires-Dist: pycryptodome==3.21.0; extra == 'dbt'
Requires-Dist: pydantic-core==2.27.2; extra == 'dbt'
Requires-Dist: pydantic==2.10.5; extra == 'dbt'
Requires-Dist: pygments==2.19.1; extra == 'dbt'
Requires-Dist: pyhive==0.7.0; extra == 'dbt'
Requires-Dist: pyjwt==2.10.1; extra == 'dbt'
Requires-Dist: pymongo==4.10.1; extra == 'dbt'
Requires-Dist: pymysql==1.1.1; extra == 'dbt'
Requires-Dist: pynacl==1.5.0; extra == 'dbt'
Requires-Dist: pyocclient==0.6; extra == 'dbt'
Requires-Dist: pyodbc==5.1.0; extra == 'dbt'
Requires-Dist: python-dateutil==2.9.0.post0; extra == 'dbt'
Requires-Dist: python-decouple==3.8; extra == 'dbt'
Requires-Dist: python-slugify==8.0.4; extra == 'dbt'
Requires-Dist: pytimeparse==1.1.8; extra == 'dbt'
Requires-Dist: pytz==2024.2; extra == 'dbt'
Requires-Dist: pywebhdfs==0.4.1; extra == 'dbt'
Requires-Dist: pyyaml==6.0.2; extra == 'dbt'
Requires-Dist: redis==5.2.1; extra == 'dbt'
Requires-Dist: redshift-connector==2.0.917; extra == 'dbt'
Requires-Dist: referencing==0.35.1; extra == 'dbt'
Requires-Dist: regex==2024.11.6; extra == 'dbt'
Requires-Dist: requests-oauthlib==2.0.0; extra == 'dbt'
Requires-Dist: requests==2.32.3; extra == 'dbt'
Requires-Dist: rich==13.9.4; extra == 'dbt'
Requires-Dist: rpds-py==0.22.3; extra == 'dbt'
Requires-Dist: rsa==4.9; extra == 'dbt'
Requires-Dist: s3fs==2024.12.0; extra == 'dbt'
Requires-Dist: s3transfer==0.10.4; extra == 'dbt'
Requires-Dist: scramp==1.4.5; extra == 'dbt'
Requires-Dist: setuptools==75.8.0; extra == 'dbt'
Requires-Dist: shellingham==1.5.4; extra == 'dbt'
Requires-Dist: six==1.17.0; extra == 'dbt'
Requires-Dist: sniffio==1.3.1; extra == 'dbt'
Requires-Dist: soupsieve==2.6; extra == 'dbt'
Requires-Dist: sqlalchemy-bigquery==1.12.0; extra == 'dbt'
Requires-Dist: sqlalchemy-doris==0.2.2; extra == 'dbt'
Requires-Dist: sqlalchemy-redshift==0.8.15+recurve; extra == 'dbt'
Requires-Dist: sqlalchemy-utils==0.41.2; extra == 'dbt'
Requires-Dist: sqlalchemy==2.0.37; extra == 'dbt'
Requires-Dist: sqlglot==26.1.3; extra == 'dbt'
Requires-Dist: sqlparse==0.5.3; extra == 'dbt'
Requires-Dist: sshtunnel==0.4.0; extra == 'dbt'
Requires-Dist: starlette==0.41.3; extra == 'dbt'
Requires-Dist: tenacity==8.5.0; extra == 'dbt'
Requires-Dist: text-unidecode==1.3; extra == 'dbt'
Requires-Dist: thrift-sasl==0.4.3; extra == 'dbt'
Requires-Dist: thrift==0.16.0; extra == 'dbt'
Requires-Dist: time-machine==2.16.0; extra == 'dbt'
Requires-Dist: toolz==1.0.0; extra == 'dbt'
Requires-Dist: typer==0.15.1; extra == 'dbt'
Requires-Dist: typing-extensions==4.12.2; extra == 'dbt'
Requires-Dist: tzdata==2024.2; extra == 'dbt'
Requires-Dist: tzlocal==5.2; extra == 'dbt'
Requires-Dist: ujson==5.10.0; extra == 'dbt'
Requires-Dist: urllib3==1.26.20; extra == 'dbt'
Requires-Dist: uvicorn==0.34.0; extra == 'dbt'
Requires-Dist: virtualenv==20.28.1; extra == 'dbt'
Requires-Dist: wrapt==1.17.1; extra == 'dbt'
Requires-Dist: xmltodict==0.14.2; extra == 'dbt'
Requires-Dist: yarl==1.18.3; extra == 'dbt'
Requires-Dist: zipp==3.21.0; extra == 'dbt'
Requires-Dist: zstd==1.5.6.1; extra == 'dbt'
Provides-Extra: slim
Requires-Dist: annotated-types==0.7.0; extra == 'slim'
Requires-Dist: anyio==4.9.0; extra == 'slim'
Requires-Dist: attrs==25.3.0; extra == 'slim'
Requires-Dist: certifi==2025.1.31; extra == 'slim'
Requires-Dist: charset-normalizer==3.4.1; extra == 'slim'
Requires-Dist: click==8.1.8; extra == 'slim'
Requires-Dist: croniter==6.0.0; extra == 'slim'
Requires-Dist: cytoolz==1.0.1; extra == 'slim'
Requires-Dist: deprecated==1.2.18; extra == 'slim'
Requires-Dist: fsspec==2025.3.2; extra == 'slim'
Requires-Dist: googleapis-common-protos==1.70.0; extra == 'slim'
Requires-Dist: h11==0.14.0; extra == 'slim'
Requires-Dist: httpcore==1.0.8; extra == 'slim'
Requires-Dist: httpx==0.28.1; extra == 'slim'
Requires-Dist: humanize==4.12.2; extra == 'slim'
Requires-Dist: idna==3.10; extra == 'slim'
Requires-Dist: importlib-metadata==8.6.1; extra == 'slim'
Requires-Dist: jinja2==3.1.6; extra == 'slim'
Requires-Dist: jsonschema-specifications==2025.4.1; extra == 'slim'
Requires-Dist: jsonschema==4.23.0; extra == 'slim'
Requires-Dist: loguru==0.7.3; extra == 'slim'
Requires-Dist: markdown-it-py==3.0.0; extra == 'slim'
Requires-Dist: markupsafe==3.0.2; extra == 'slim'
Requires-Dist: mdurl==0.1.2; extra == 'slim'
Requires-Dist: opentelemetry-api==1.32.1; extra == 'slim'
Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.32.1; extra == 'slim'
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.32.1; extra == 'slim'
Requires-Dist: opentelemetry-proto==1.32.1; extra == 'slim'
Requires-Dist: opentelemetry-sdk==1.32.1; extra == 'slim'
Requires-Dist: opentelemetry-semantic-conventions==0.53b1; extra == 'slim'
Requires-Dist: pendulum==3.1.0; extra == 'slim'
Requires-Dist: protobuf==5.29.4; extra == 'slim'
Requires-Dist: pydantic-core==2.33.1; extra == 'slim'
Requires-Dist: pydantic==2.11.3; extra == 'slim'
Requires-Dist: pygments==2.19.1; extra == 'slim'
Requires-Dist: python-dateutil==2.9.0.post0; extra == 'slim'
Requires-Dist: pytz==2025.2; extra == 'slim'
Requires-Dist: referencing==0.36.2; extra == 'slim'
Requires-Dist: requests==2.32.3; extra == 'slim'
Requires-Dist: rich==14.0.0; extra == 'slim'
Requires-Dist: rpds-py==0.24.0; extra == 'slim'
Requires-Dist: shellingham==1.5.4; extra == 'slim'
Requires-Dist: six==1.17.0; extra == 'slim'
Requires-Dist: sniffio==1.3.1; extra == 'slim'
Requires-Dist: sqlalchemy==2.0.40; extra == 'slim'
Requires-Dist: sqlglot==26.16.0; extra == 'slim'
Requires-Dist: sqlparse==0.5.3; extra == 'slim'
Requires-Dist: toolz==1.0.0; extra == 'slim'
Requires-Dist: typer==0.15.2; extra == 'slim'
Requires-Dist: typing-extensions==4.13.2; extra == 'slim'
Requires-Dist: typing-inspection==0.4.0; extra == 'slim'
Requires-Dist: tzdata==2025.2; extra == 'slim'
Requires-Dist: urllib3==2.4.0; extra == 'slim'
Requires-Dist: wrapt==1.17.2; extra == 'slim'
Requires-Dist: zipp==3.21.0; extra == 'slim'
Provides-Extra: worker
Requires-Dist: adlfs==2024.12.0; extra == 'worker'
Requires-Dist: aiobotocore==2.17.0; extra == 'worker'
Requires-Dist: aiohappyeyeballs==2.4.4; extra == 'worker'
Requires-Dist: aiohttp==3.10.5; extra == 'worker'
Requires-Dist: aioitertools==0.12.0; extra == 'worker'
Requires-Dist: aiooss2==0.2.10; extra == 'worker'
Requires-Dist: aiosignal==1.3.2; extra == 'worker'
Requires-Dist: aliyun-log-python-sdk==0.9.24; extra == 'worker'
Requires-Dist: aliyun-python-sdk-core==2.16.0; extra == 'worker'
Requires-Dist: aliyun-python-sdk-kms==2.16.5; extra == 'worker'
Requires-Dist: annotated-types==0.7.0; extra == 'worker'
Requires-Dist: anyio==4.8.0; extra == 'worker'
Requires-Dist: asgiref==3.8.1; extra == 'worker'
Requires-Dist: asn1crypto==1.5.1; extra == 'worker'
Requires-Dist: asynch==0.2.5; extra == 'worker'
Requires-Dist: attrs==24.3.0; extra == 'worker'
Requires-Dist: azure-core==1.32.0; extra == 'worker'
Requires-Dist: azure-datalake-store==0.0.53; extra == 'worker'
Requires-Dist: azure-identity==1.19.0; extra == 'worker'
Requires-Dist: azure-storage-blob==12.24.0; extra == 'worker'
Requires-Dist: backoff==2.2.1; extra == 'worker'
Requires-Dist: bcrypt==4.2.1; extra == 'worker'
Requires-Dist: beautifulsoup4==4.12.3; extra == 'worker'
Requires-Dist: bitarray==3.0.0; extra == 'worker'
Requires-Dist: boto3==1.35.93; extra == 'worker'
Requires-Dist: botocore==1.35.93; extra == 'worker'
Requires-Dist: cachetools==5.5.0; extra == 'worker'
Requires-Dist: certifi==2024.12.14; extra == 'worker'
Requires-Dist: cffi==1.17.1; extra == 'worker'
Requires-Dist: chardet==5.2.0; extra == 'worker'
Requires-Dist: charset-normalizer==3.4.1; extra == 'worker'
Requires-Dist: ciso8601==2.3.2; extra == 'worker'
Requires-Dist: click==8.1.8; extra == 'worker'
Requires-Dist: clickhouse-cityhash==1.0.2.4; extra == 'worker'
Requires-Dist: clickhouse-driver==0.2.9; extra == 'worker'
Requires-Dist: clickhouse-sqlalchemy==0.3.2; extra == 'worker'
Requires-Dist: confluent-kafka==2.12.1; extra == 'worker'
Requires-Dist: cos-python-sdk-v5==1.9.10; extra == 'worker'
Requires-Dist: crcmod==1.7; extra == 'worker'
Requires-Dist: croniter==6.0.0; extra == 'worker'
Requires-Dist: cryptography==44.0.0; extra == 'worker'
Requires-Dist: cssselect==1.2.0; extra == 'worker'
Requires-Dist: cssutils==2.11.1; extra == 'worker'
Requires-Dist: cython==3.0.11; extra == 'worker'
Requires-Dist: cytoolz==1.0.1; extra == 'worker'
Requires-Dist: dateparser==1.2.2; extra == 'worker'
Requires-Dist: deprecated==1.2.15; extra == 'worker'
Requires-Dist: dicttoxml==1.7.16; extra == 'worker'
Requires-Dist: dnspython==2.7.0; extra == 'worker'
Requires-Dist: elastic-transport==8.17.0; extra == 'worker'
Requires-Dist: elasticsearch==8.17.0; extra == 'worker'
Requires-Dist: emails==0.6; extra == 'worker'
Requires-Dist: et-xmlfile==2.0.0; extra == 'worker'
Requires-Dist: fastapi==0.115.6; extra == 'worker'
Requires-Dist: frozenlist==1.5.0; extra == 'worker'
Requires-Dist: fsspec==2024.12.0; extra == 'worker'
Requires-Dist: future==1.0.0; extra == 'worker'
Requires-Dist: google-api-core==2.24.0; extra == 'worker'
Requires-Dist: google-auth-oauthlib==1.2.1; extra == 'worker'
Requires-Dist: google-auth==2.37.0; extra == 'worker'
Requires-Dist: google-cloud-bigquery-storage==2.27.0; extra == 'worker'
Requires-Dist: google-cloud-bigquery==3.27.0; extra == 'worker'
Requires-Dist: google-cloud-core==2.4.1; extra == 'worker'
Requires-Dist: google-cloud-storage==2.19.0; extra == 'worker'
Requires-Dist: google-crc32c==1.6.0; extra == 'worker'
Requires-Dist: google-resumable-media==2.7.2; extra == 'worker'
Requires-Dist: googleapis-common-protos==1.66.0; extra == 'worker'
Requires-Dist: grpcio-status==1.62.3; extra == 'worker'
Requires-Dist: grpcio==1.69.0; extra == 'worker'
Requires-Dist: gspread==6.1.4; extra == 'worker'
Requires-Dist: gunicorn==23.0.0; extra == 'worker'
Requires-Dist: h11==0.14.0; extra == 'worker'
Requires-Dist: httpcore==1.0.7; extra == 'worker'
Requires-Dist: httpx==0.28.1; extra == 'worker'
Requires-Dist: humanize==4.11.0; extra == 'worker'
Requires-Dist: idna==3.10; extra == 'worker'
Requires-Dist: importlib-metadata==8.5.0; extra == 'worker'
Requires-Dist: impyla==0.19.0; extra == 'worker'
Requires-Dist: isodate==0.7.2; extra == 'worker'
Requires-Dist: jinja2==3.1.5; extra == 'worker'
Requires-Dist: jmespath==0.10.0; extra == 'worker'
Requires-Dist: jsonschema-specifications==2024.10.1; extra == 'worker'
Requires-Dist: jsonschema==4.23.0; extra == 'worker'
Requires-Dist: larksuite-oapi==1.0.34; extra == 'worker'
Requires-Dist: leb128==1.0.8; extra == 'worker'
Requires-Dist: loguru==0.7.3; extra == 'worker'
Requires-Dist: lxml==5.3.0; extra == 'worker'
Requires-Dist: lz4==4.3.3; extra == 'worker'
Requires-Dist: markdown-it-py==3.0.0; extra == 'worker'
Requires-Dist: markupsafe==3.0.2; extra == 'worker'
Requires-Dist: mdurl==0.1.2; extra == 'worker'
Requires-Dist: more-itertools==10.5.0; extra == 'worker'
Requires-Dist: msal-extensions==1.2.0; extra == 'worker'
Requires-Dist: msal==1.31.1; extra == 'worker'
Requires-Dist: multidict==6.1.0; extra == 'worker'
Requires-Dist: mysql-connector-python==9.1.0; extra == 'worker'
Requires-Dist: numpy==2.2.1; extra == 'worker'
Requires-Dist: oauthlib==3.2.2; extra == 'worker'
Requires-Dist: openpyxl==3.1.5; extra == 'worker'
Requires-Dist: opentelemetry-api==1.29.0; extra == 'worker'
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.15.0; extra == 'worker'
Requires-Dist: opentelemetry-proto==1.15.0; extra == 'worker'
Requires-Dist: opentelemetry-sdk==1.29.0; extra == 'worker'
Requires-Dist: opentelemetry-semantic-conventions==0.50b0; extra == 'worker'
Requires-Dist: orjson==3.10.14; extra == 'worker'
Requires-Dist: oss2==2.18.1; extra == 'worker'
Requires-Dist: ossfs==2023.12.0; extra == 'worker'
Requires-Dist: packaging==24.2; extra == 'worker'
Requires-Dist: pandas==2.2.3; extra == 'worker'
Requires-Dist: paramiko==2.7.1; extra == 'worker'
Requires-Dist: pendulum==3.0.0; extra == 'worker'
Requires-Dist: portalocker==2.10.1; extra == 'worker'
Requires-Dist: premailer==3.10.0; extra == 'worker'
Requires-Dist: propcache==0.2.1; extra == 'worker'
Requires-Dist: proto-plus==1.25.0; extra == 'worker'
Requires-Dist: protobuf==4.25.5; extra == 'worker'
Requires-Dist: psycopg2-binary==2.9.10; extra == 'worker'
Requires-Dist: pure-sasl==0.6.2; extra == 'worker'
Requires-Dist: pyarrow==18.1.0; extra == 'worker'
Requires-Dist: pyasn1-modules==0.4.1; extra == 'worker'
Requires-Dist: pyasn1==0.6.1; extra == 'worker'
Requires-Dist: pycparser==2.22; extra == 'worker'
Requires-Dist: pycryptodome==3.21.0; extra == 'worker'
Requires-Dist: pydantic-core==2.27.2; extra == 'worker'
Requires-Dist: pydantic==2.10.5; extra == 'worker'
Requires-Dist: pygments==2.19.1; extra == 'worker'
Requires-Dist: pyhive==0.7.0; extra == 'worker'
Requires-Dist: pyjwt==2.10.1; extra == 'worker'
Requires-Dist: pymongo==4.10.1; extra == 'worker'
Requires-Dist: pymysql==1.1.1; extra == 'worker'
Requires-Dist: pynacl==1.5.0; extra == 'worker'
Requires-Dist: pyocclient==0.6; extra == 'worker'
Requires-Dist: pyodbc==5.2.0; extra == 'worker'
Requires-Dist: python-dateutil==2.9.0.post0; extra == 'worker'
Requires-Dist: python-slugify==8.0.4; extra == 'worker'
Requires-Dist: pytz==2024.2; extra == 'worker'
Requires-Dist: pywebhdfs==0.4.1; extra == 'worker'
Requires-Dist: pyyaml==6.0.2; extra == 'worker'
Requires-Dist: redis==5.2.1; extra == 'worker'
Requires-Dist: redshift-connector==2.1.5; extra == 'worker'
Requires-Dist: referencing==0.35.1; extra == 'worker'
Requires-Dist: regex==2024.11.6; extra == 'worker'
Requires-Dist: requests-oauthlib==2.0.0; extra == 'worker'
Requires-Dist: requests==2.32.3; extra == 'worker'
Requires-Dist: rich==13.9.4; extra == 'worker'
Requires-Dist: rpds-py==0.22.3; extra == 'worker'
Requires-Dist: rsa==4.9; extra == 'worker'
Requires-Dist: s3fs==2024.12.0; extra == 'worker'
Requires-Dist: s3transfer==0.10.4; extra == 'worker'
Requires-Dist: scramp==1.4.5; extra == 'worker'
Requires-Dist: setuptools==75.8.0; extra == 'worker'
Requires-Dist: shellingham==1.5.4; extra == 'worker'
Requires-Dist: six==1.17.0; extra == 'worker'
Requires-Dist: sniffio==1.3.1; extra == 'worker'
Requires-Dist: soupsieve==2.6; extra == 'worker'
Requires-Dist: sqlalchemy-bigquery==1.12.0; extra == 'worker'
Requires-Dist: sqlalchemy-doris==0.2.2; extra == 'worker'
Requires-Dist: sqlalchemy-redshift==0.8.15+recurve; extra == 'worker'
Requires-Dist: sqlalchemy-utils==0.41.2; extra == 'worker'
Requires-Dist: sqlalchemy==2.0.37; extra == 'worker'
Requires-Dist: sqlglot==26.1.3; extra == 'worker'
Requires-Dist: sqlparse==0.5.3; extra == 'worker'
Requires-Dist: sshtunnel==0.3.2; extra == 'worker'
Requires-Dist: starlette==0.41.3; extra == 'worker'
Requires-Dist: tenacity==8.5.0; extra == 'worker'
Requires-Dist: text-unidecode==1.3; extra == 'worker'
Requires-Dist: thrift-sasl==0.4.3; extra == 'worker'
Requires-Dist: thrift==0.16.0; extra == 'worker'
Requires-Dist: time-machine==2.16.0; extra == 'worker'
Requires-Dist: toolz==1.0.0; extra == 'worker'
Requires-Dist: typer==0.15.1; extra == 'worker'
Requires-Dist: typing-extensions==4.12.2; extra == 'worker'
Requires-Dist: tzdata==2024.2; extra == 'worker'
Requires-Dist: tzlocal==5.2; extra == 'worker'
Requires-Dist: ujson==5.10.0; extra == 'worker'
Requires-Dist: urllib3==2.3.0; extra == 'worker'
Requires-Dist: uvicorn==0.34.0; extra == 'worker'
Requires-Dist: wrapt==1.17.1; extra == 'worker'
Requires-Dist: yarl==1.18.3; extra == 'worker'
Requires-Dist: zipp==3.21.0; extra == 'worker'
Requires-Dist: zstd==1.5.6.1; extra == 'worker'
Description-Content-Type: text/markdown

# Recurve Libraries

For the unified maintenance of public components of the Recurve platform,
these codes may be used in both Server and Executor (Worker) environments.

Only Python 3.11+ are supported.

## Components

This code repository consists of the following core components:

### Core
The foundation of the Recurve platform that provides:

- Base classes and interfaces for platform components
- Jinja2 templating engine integration
- Core configuration management
- Common platform abstractions

### Utils
A comprehensive utility library offering:

- Time handling and date manipulation
- Concurrent processing tools
- File system operations and path handling
- String manipulation and text processing
- Logging and error handling utilities
- Data validation helpers

### Connectors
A robust data connectivity layer supporting:
- Database connections (MySQL, PostgreSQL, Redshift, BigQuery, etc.)
- Cloud storage (S3, GCS, Azure Blob Storage)
- Messaging services and APIs
- Custom connector development framework

Note: Run `make update-connector-schema` after updating connector config schemas to regenerate config_schema.py

### Schedulers
Airflow integration components including:

- Custom Airflow operators and sensors
- DAG generation utilities
- Workflow scheduling interfaces
- Task dependency management

### Operators
Task-specific operators for:

- Data extraction and loading
- Data transformation and processing
- Running Python code
- Running SQL code
- Building and running DBT jobs


### Client
A flexible client interface providing:

- Platform API abstractions
- Authentication handling
- Resource management
- Extensible base classes for custom clients
- Connection pooling and retry logic

### Executors

Core job execution engine that:

- Manages job submissions and execution flows
- Orchestrates task execution on infrastructure
- Handles job lifecycle and state management
- Provides infrastructure abstraction layer

## Development Workflow

### Requirements management

We use `uv` to manage Python package dependencies. The workflow is:

1. Update source requirements in `.in` files:
   - [`requirements.in`](./requirements.in) - All dependencies
   - [`requirements/worker.in`](requirements/worker.in) - Worker-specific dependencies
   - [`requirements/dbt.in`](requirements/dbt.in) - DBT-specific dependencies
   - [`requirements-dev.in`](requirements-dev.in) - Development dependencies

2. Compile locked requirements:
   ```bash
   make compile-requirements  # Compiles all requirements files
   ```
   Or compile individual files:
   ```bash
   make compile-worker  # Just worker requirements
   make compile-dbt    # Just DBT requirements
   ```

3. After compiling requirements, update optional dependencies in pyproject.toml:
   ```bash
   make update-optional-deps
   ```

This ensures consistent dependencies across development and production environments.

### Release Process

1. Update version number in [`recurvedata/__version__.py`](recurvedata/__version__.py)
2. Build and publish package:
   ```bash
   make publish
   ```
   This will clean build artifacts, build new package, and publish to Recurve PyPI.

### Available Commands

The following make commands are available:

Build and Publishing:
- `make clean` - Remove build artifacts (dist directory)
- `make build` - Clean and build the package
- `make publish` - Build and publish package to Recurve PyPI

Requirements Management:
- `make upgrade-uv` - Upgrade the uv package installer
- `make compile-worker` - Compile worker-specific requirements
- `make compile-dbt` - Compile DBT-specific requirements
- `make compile-requirements` - Compile all requirements files and sync environment
- `make install-requirements` - Install requirements files

Maintenance Scripts:
- `make update-optional-deps` - Update optional dependencies in pyproject.toml
- `make update-connector-schema` - Update connector configuration schemas

## GitLab CI/CD Pipeline

### Overview
This repository uses GitLab CI for build and release. The primary stages (in order) are:
- python_internal: build and publish internal PyPI package (develop)
- python_public: build and publish public PyPI package (main, manual)
- copy_dockerfiles: prepare Docker build context and version metadata
- docker_internal: build and push internal Docker images (develop / release/*)
- docker_official: build and push public Docker images (main, manual)
- scan: SAST/Sonar (disabled by default)

Configuration files:
- `.gitlab-ci.yml` (stages, rules, job orchestration)
- `.gitlab/ci/templates.yml` (shared templates and login configuration)
- `.gitlab/ci/variables.yml` (shared variables)
- `dockerfiles/build_push_images.sh` (image build and push script)

### Branch rules and triggers
- develop branch
  - Runs: `check_version` → `package_python_internal` → `copy_dockerfiles` → `build_docker_internal`
  - Environment: `ENVIRONMENT=test`
  - Targets: internal private registry + Aliyun `internal` namespace

- release/* branches
  - Runs: `copy_dockerfiles` → `build_docker_internal`
  - Environment: `ENVIRONMENT=staging`
  - Targets: internal private registry + Aliyun `internal` namespace

- main branch
  - Runs (manual): `package_python_public`, `build_docker_public`, `tag`
  - Environment: `ENVIRONMENT=production`
  - Targets: Docker Hub public registry + Aliyun `public` namespace

Note: the `tag` job creates an annotated tag after the public image build, including deployment metadata.

### Image build and naming
Build script: `dockerfiles/build_push_images.sh`
- Image names:
  - Production: `recurve-<service>` (current service = worker)
  - Non-production: `recurve-<service>-<environment>` (e.g., `recurve-worker-test`, `recurve-worker-staging`)
- Tags:
  - version: `${VERSION_PACKAGE}` (from `recurvedata/__version__.py`)
  - `latest`

### Push targets
- Internal private registry (login handled by job type)
  - Registry: `$DOCKER_REPOSITORY_URL` (internal jobs)
  - Example path: `docker.tool.reorc.cloud/<image_name>:<tags>`

- Public Docker Hub (public jobs)
  - Namespace: `recurvedata/<image_name>:<tags>`

- Aliyun Container Registry (pushed in addition for all Docker build jobs)
  - Registry: `reorc-registry-cn-registry-vpc.cn-shenzhen.cr.aliyuncs.com`
  - Namespace mapping:
    - Non-production (test/staging): `internal`
    - Production: `public`
  - Full path: `<registry>/<namespace>/<image_name>:<tags>`

### Login and authentication
Templates in `.gitlab/ci/templates.yml`:
- `.docker_internal_configuration`: login to internal private registry and also login to Aliyun
- `.docker_public_configuration`: login to Docker Hub and also login to Aliyun

Both templates execute `docker logout || true` once in `before_script`, then log in to the respective registry and Aliyun so a single job can push to multiple registries.

### Required CI variables (examples)
Configure the following as Masked/Protected variables in GitLab CI/CD settings:

```text
# Nexus / PyPI
NEXUS_USERNAME, NEXUS_PASSWORD, NEXUS_REPOSITORY_URL, NEXUS_PACKAGE_URL
PYPI_USERNAME, PYPI_PASSWORD, PYPI_REPOSITORY_URL (optional)

# Private registry (internal jobs)
DOCKER_REPOSITORY_URL, DOCKER_USERNAME, DOCKER_PASSWORD

# Docker Hub (public jobs)
DOCKER_OFFICIAL_REPOSITORY_URL, DOCKER_OFFICIAL_USERNAME, DOCKER_OFFICIAL_PASSWORD

# Aliyun registry (additional push in all Docker jobs)
ALIYUN_REGISTRY_URL=reorc-registry-cn-registry-vpc.cn-shenzhen.cr.aliyuncs.com
ALIYUN_USERNAME, ALIYUN_PASSWORD

# Namespaces declared in repo variables (adjust if needed)
ALIYUN_NAMESPACE_INTERNAL=internal
ALIYUN_NAMESPACE_PUBLIC=public
```

### Manual triggers and verification
- On the main branch, `package_python_public` and `build_docker_public` are manual; click “Play” in the GitLab Pipeline UI.
- Verify images:
  - Internal: `docker.tool.reorc.cloud/<image_name>:<tag>`
  - Docker Hub: `recurvedata/<image_name>:<tag>`
  - Aliyun: `reorc-registry-cn-registry-vpc.cn-shenzhen.cr.aliyuncs.com/<namespace>/<image_name>:<tag>`
