Skip to content

Commit c7287ed

Browse files
authored
Merge pull request #679 from atlanhq/APP-5243
APP-5243: Migrate to `httpx` (goodbye `requests` πŸ‘‹ ) - Completely removed support for requests and replaced it with httpx (which supports both sync and async clients) - Implemented AsyncAtlanClient for all async operations (extends AtlanClient for reusability) - Refactored all existing clients, caches, and several creators (connection, badge, etc.) to support async variants, and added new models (mainly search result models that require async iteration). Following aio directory convention for all async components. - Used a "sandwich approach" for refactoring: extracted common functionality (request preparation and response processing) into a separate common sub-package. This enables reuse across both sync and async operations - only the middle layer (API calling with respective clients) differs.
2 parents fcefbdc + ff0f932 commit c7287ed

File tree

213 files changed

+36691
-2895
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

213 files changed

+36691
-2895
lines changed

β€Ž.conda-envs/meta.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ requirements:
1616
- setuptools
1717
- python
1818
run:
19-
- python >=3.9,<3.13
19+
- python >=3.9,<4
2020
- jinja2 ~=3.1.6
2121
- lazy_loader ~=0.4
2222
- pydantic ~=2.11.7

β€Ž.github/workflows/pyatlan-pr.yaml

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
name: Pyatlan Pull Request Build
22

3+
# This workflow runs both sync and async integration tests intelligently:
4+
# - Sync integration tests: Always run on every PR
5+
# - Async integration tests: Only run when:
6+
# 1. Changes detected in pyatlan/*/aio/ or tests/*/aio/ paths
7+
# 2. PR has the "run-async-tests" label (manual trigger)
8+
# This prevents adding 12+ minutes to every PR while ensuring async tests run when needed.
9+
310
on:
411
pull_request:
512
workflow_dispatch:
@@ -39,11 +46,45 @@ jobs:
3946
vulnerability-service: osv
4047
inputs: .
4148

49+
check-aio-changes:
50+
runs-on: ubuntu-latest
51+
outputs:
52+
run-async-tests: ${{ steps.check-conditions.outputs.run-async-tests }}
53+
steps:
54+
- name: Checkout code
55+
uses: actions/checkout@v4
56+
with:
57+
fetch-depth: 0
58+
59+
- name: Check for AIO changes or manual trigger
60+
id: check-conditions
61+
run: |
62+
# Check if PR has the run-async-tests label
63+
if echo '${{ toJson(github.event.pull_request.labels.*.name) }}' | grep -q "run-async-tests"; then
64+
echo "run-async-tests=true" >> $GITHUB_OUTPUT
65+
echo "🏷️ Manual trigger: Found 'run-async-tests' label"
66+
exit 0
67+
fi
68+
69+
# Check for changes in AIO-related paths
70+
if git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD | grep -E "(pyatlan/.*aio/|tests/.*aio/)"; then
71+
echo "run-async-tests=true" >> $GITHUB_OUTPUT
72+
echo "πŸ” Change detection: Found AIO-related changes:"
73+
aio_files=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD | grep -E "(pyatlan/.*aio/|tests/.*aio/)")
74+
echo "$aio_files" | head -20
75+
total_count=$(echo "$aio_files" | wc -l)
76+
echo "πŸ“Š Total AIO files changed: $total_count"
77+
else
78+
echo "run-async-tests=false" >> $GITHUB_OUTPUT
79+
echo "⏭️ No AIO changes detected and no manual trigger label found"
80+
fi
81+
4282
qa-checks-and-unit-tests:
4383
needs: [vulnerability-scan]
4484
runs-on: ubuntu-latest
4585
outputs:
4686
files: ${{ steps.distribute-integration-test-files.outputs.files }}
87+
aio-files: ${{ steps.distribute-aio-test-files.outputs.aio-files }}
4788
strategy:
4889
matrix:
4990
# Specify version as a string
@@ -73,7 +114,7 @@ jobs:
73114
ATLAN_API_KEY: ${{ secrets.ATLAN_API_KEY }}
74115
ATLAN_BASE_URL: ${{ secrets.ATLAN_BASE_URL }}
75116
# Run with `pytest-sugar` for enhancing the overall test report output
76-
run: uv run pytest tests/unit --force-sugar
117+
run: uv run pytest tests/unit --force-sugar -vv
77118

78119
- name: Prepare integration tests distribution
79120
id: distribute-integration-test-files
@@ -83,6 +124,22 @@ jobs:
83124
json_files=$(echo "${files[@]}" | jq -R -c 'split(" ")[:-1]')
84125
echo "files=$json_files" >> $GITHUB_OUTPUT
85126
127+
- name: Prepare async integration tests distribution
128+
id: distribute-aio-test-files
129+
run: |
130+
# Check if AIO test directory exists and has test files
131+
if [ -d "tests/integration/aio" ]; then
132+
aio_files=$(find tests/integration/aio -name "test_*.py" -o -name "*_test.py" | tr '\n' ' ')
133+
if [ -n "$aio_files" ]; then
134+
json_aio_files=$(echo "${aio_files[@]}" | jq -R -c 'split(" ")[:-1]')
135+
echo "aio-files=$json_aio_files" >> $GITHUB_OUTPUT
136+
else
137+
echo "aio-files=[]" >> $GITHUB_OUTPUT
138+
fi
139+
else
140+
echo "aio-files=[]" >> $GITHUB_OUTPUT
141+
fi
142+
86143
integration-tests:
87144
needs: [vulnerability-scan, qa-checks-and-unit-tests]
88145
runs-on: ubuntu-latest
@@ -120,4 +177,46 @@ jobs:
120177
timeout_minutes: 10 # Maximum time per test job; otherwise, the job will fail
121178
# Run the integration test file using `pytest-timer` plugin
122179
# to display only the durations of the 10 slowest tests with `pytest-sugar`
123-
command: uv run pytest ${{ matrix.test_file }} -p name_of_plugin --timer-top-n 10 --force-sugar
180+
command: uv run pytest ${{ matrix.test_file }} -p name_of_plugin --timer-top-n 10 --force-sugar -vv
181+
182+
183+
async-integration-tests:
184+
needs: [vulnerability-scan, qa-checks-and-unit-tests, check-aio-changes]
185+
runs-on: ubuntu-latest
186+
# Only run if AIO changes detected or manual trigger
187+
if: needs.check-aio-changes.outputs.run-async-tests == 'true'
188+
strategy:
189+
fail-fast: false
190+
matrix:
191+
test_file: ${{fromJson(needs.qa-checks-and-unit-tests.outputs.aio-files)}}
192+
concurrency:
193+
group: async-${{ matrix.test_file }}
194+
195+
steps:
196+
- name: Checkout code
197+
uses: actions/checkout@v4
198+
199+
- name: Set up Python 3.9
200+
uses: actions/setup-python@v5
201+
with:
202+
# Specify version as a string
203+
# https://github.com/actions/setup-python/issues/160"
204+
python-version: "3.9"
205+
206+
- name: Install uv
207+
uses: astral-sh/setup-uv@v6
208+
209+
- name: Install dependencies
210+
run: uv sync --group dev
211+
212+
- name: Run async integration tests
213+
env: # Test tenant environment variables
214+
ATLAN_API_KEY: ${{ secrets.ATLAN_API_KEY }}
215+
ATLAN_BASE_URL: ${{ secrets.ATLAN_BASE_URL }}
216+
uses: nick-fields/retry@v3
217+
with:
218+
max_attempts: 3
219+
timeout_minutes: 15 # Async tests may take longer, increased timeout
220+
# Run the async integration test file using `pytest-timer` plugin
221+
# to display only the durations of the 10 slowest tests with `pytest-sugar`
222+
command: uv run pytest ${{ matrix.test_file }} -p name_of_plugin --timer-top-n 10 --force-sugar -vv

β€Ž.github/workflows/pyatlan-test-cron.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ jobs:
3737
# to display only the durations of the 25 slowest tests with `pytest-sugar`
3838
run: |
3939
uv run pytest tests/unit
40-
uv run pytest tests/integration -p name_of_plugin --timer-top-n 25
40+
uv run pytest tests/integration -p name_of_plugin --timer-top-n 25 -vv

β€Ždocs/asset/appworkflowrun.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _appworkflowrun:
2+
3+
AppWorkflowRun
4+
==============
5+
6+
.. module:: pyatlan.model.assets
7+
:no-index:
8+
9+
.. autoclass:: AppWorkflowRun
10+
:members:

β€Ždocs/asset/databricksnotebook.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _databricksnotebook:
2+
3+
DatabricksNotebook
4+
==================
5+
6+
.. module:: pyatlan.model.assets
7+
:no-index:
8+
9+
.. autoclass:: DatabricksNotebook
10+
:members:

β€Ždocs/asset/microstrategycolumn.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _microstrategycolumn:
2+
3+
MicroStrategyColumn
4+
===================
5+
6+
.. module:: pyatlan.model.assets
7+
:no-index:
8+
9+
.. autoclass:: MicroStrategyColumn
10+
:members:

β€Ždocs/asset/notebook.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _notebook:
2+
3+
Notebook
4+
========
5+
6+
.. module:: pyatlan.model.assets
7+
:no-index:
8+
9+
.. autoclass:: Notebook
10+
:members:

β€Ždocs/asset/qlikcolumn.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. _qlikcolumn:
2+
3+
QlikColumn
4+
==========
5+
6+
.. module:: pyatlan.model.assets
7+
:no-index:
8+
9+
.. autoclass:: QlikColumn
10+
:members:

β€Ždocs/assets.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ You can interact with all of the following different kinds of assets:
4747
asset/anomalo
4848
asset/anomalocheck
4949
asset/app
50+
asset/appworkflowrun
5051
asset/application
5152
asset/applicationfield
5253
asset/asset
@@ -124,6 +125,7 @@ You can interact with all of the following different kinds of assets:
124125
asset/databricks
125126
asset/databricksaimodelcontext
126127
asset/databricksaimodelversion
128+
asset/databricksnotebook
127129
asset/databricksunitycatalogtag
128130
asset/dataverse
129131
asset/dataverseattribute
@@ -204,6 +206,7 @@ You can interact with all of the following different kinds of assets:
204206
asset/metric
205207
asset/microstrategy
206208
asset/microstrategyattribute
209+
asset/microstrategycolumn
207210
asset/microstrategycube
208211
asset/microstrategydocument
209212
asset/microstrategydossier
@@ -232,6 +235,7 @@ You can interact with all of the following different kinds of assets:
232235
asset/multidimensionaldataset
233236
asset/namespace
234237
asset/nosql
238+
asset/notebook
235239
asset/objectstore
236240
asset/persona
237241
asset/powerbi
@@ -260,6 +264,7 @@ You can interact with all of the following different kinds of assets:
260264
asset/qlik
261265
asset/qlikapp
262266
asset/qlikchart
267+
asset/qlikcolumn
263268
asset/qlikdataset
264269
asset/qliksheet
265270
asset/qlikspace
@@ -366,5 +371,3 @@ You can interact with all of the following different kinds of assets:
366371
asset/view
367372
asset/workflow
368373
asset/workflowrun
369-
asset/alpha_dqrule
370-
asset/alpha_dqruletemplate

β€Žpyatlan/cache/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# SPDX-License-Identifier: Apache-2.0
2-
# Copyright 2022 Atlan Pte. Ltd.
2+
# Copyright 2025 Atlan Pte. Ltd.
33
# Based on original code from https://github.com/apache/atlas (under Apache-2.0 license)

0 commit comments

Comments
Β (0)