Skip to content

Commit 96a58ad

Browse files
committed
Update testing and hns key
1 parent cee1761 commit 96a58ad

File tree

6 files changed

+79
-72
lines changed

6 files changed

+79
-72
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ make test-live-cloud
8383

8484
#### Azure live backend tests
8585

86-
For Azure, you can test both against Azure Blob Storage backends and Azure Data Lake Storage Gen2 backends. To run these tests, you need to set connection strings for both of the backends by setting the following environment variables (in your `.env` file for local development). If `AZURE_STORAGE_GEN2_CONNECTION_STRING` is not set, only the blob storage backend will be tested.
86+
For Azure, you can test both against Azure Blob Storage backends and Azure Data Lake Storage Gen2 backends. To run these tests, you need to set connection strings for both of the backends by setting the following environment variables (in your `.env` file for local development). If `AZURE_STORAGE_GEN2_CONNECTION_STRING` is not set, only the blob storage backend will be tested. To set up a storage account with ADLS Gen2, go through the normal creation flow for a storage account in the Azure portal and select "Enable Hierarchical Namespace" in the "Advanced" tab of the settings when configuring the account.
8787

8888
```bash
8989
AZURE_STORAGE_CONNECTION_STRING=your_connection_string

cloudpathlib/azure/azblobclient.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,21 @@ def __init__(
139139
self.hns_cache: Dict[str, bool] = {}
140140

141141
def _check_hns(self, cloud_path: AzureBlobPath) -> bool:
142-
if cloud_path.container not in self.hns_cache:
142+
hns_key = self.service_client.account_name + "__" + cloud_path.container
143+
144+
if hns_key not in self.hns_cache:
143145
hns_enabled: bool = self.service_client.get_account_information().get(
144146
"is_hns_enabled", False
145147
) # type: ignore
146-
self.hns_cache[cloud_path.container] = hns_enabled
148+
self.hns_cache[hns_key] = hns_enabled
147149

148-
return self.hns_cache[cloud_path.container]
150+
return self.hns_cache[hns_key]
149151

150152
def _get_metadata(
151153
self, cloud_path: AzureBlobPath
152154
) -> Union["BlobProperties", "FileProperties", Dict[str, Any]]:
153155
if self._check_hns(cloud_path):
156+
154157
# works on both files and directories
155158
fsc = self.data_lake_client.get_file_system_client(cloud_path.container) # type: ignore
156159

tests/conftest.py

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -113,81 +113,88 @@ def create_test_dir_name(request) -> str:
113113
return test_dir
114114

115115

116-
def azure_rig_factory(conn_str_env_var):
117-
adls_gen2 = conn_str_env_var == "AZURE_STORAGE_GEN2_CONNECTION_STRING"
118-
119-
@fixture()
120-
def azure_rig(request, monkeypatch, assets_dir):
121-
drive = os.getenv("LIVE_AZURE_CONTAINER", DEFAULT_CONTAINER_NAME)
122-
test_dir = create_test_dir_name(request)
116+
def _azure_fixture(conn_str_env_var, adls_gen2, request, monkeypatch, assets_dir):
117+
drive = os.getenv("LIVE_AZURE_CONTAINER", DEFAULT_CONTAINER_NAME)
118+
test_dir = create_test_dir_name(request)
123119

124-
live_server = os.getenv("USE_LIVE_CLOUD") == "1"
120+
live_server = os.getenv("USE_LIVE_CLOUD") == "1"
125121

126-
if live_server:
127-
# Set up test assets
128-
blob_service_client = BlobServiceClient.from_connection_string(
129-
os.getenv(conn_str_env_var)
130-
)
131-
data_lake_service_client = DataLakeServiceClient.from_connection_string(
132-
os.getenv(conn_str_env_var)
122+
if live_server:
123+
# Set up test assets
124+
blob_service_client = BlobServiceClient.from_connection_string(
125+
os.getenv(conn_str_env_var)
126+
)
127+
data_lake_service_client = DataLakeServiceClient.from_connection_string(
128+
os.getenv(conn_str_env_var)
129+
)
130+
test_files = [
131+
f
132+
for f in assets_dir.glob("**/*")
133+
if f.is_file() and f.name not in UPLOAD_IGNORE_LIST
134+
]
135+
for test_file in test_files:
136+
blob_client = blob_service_client.get_blob_client(
137+
container=drive,
138+
blob=str(f"{test_dir}/{PurePosixPath(test_file.relative_to(assets_dir))}"),
133139
)
134-
test_files = [
135-
f
136-
for f in assets_dir.glob("**/*")
137-
if f.is_file() and f.name not in UPLOAD_IGNORE_LIST
138-
]
139-
for test_file in test_files:
140-
blob_client = blob_service_client.get_blob_client(
141-
container=drive,
142-
blob=str(f"{test_dir}/{PurePosixPath(test_file.relative_to(assets_dir))}"),
143-
)
144-
blob_client.upload_blob(test_file.read_bytes(), overwrite=True)
145-
else:
146-
monkeypatch.setenv("AZURE_STORAGE_CONNECTION_STRING", "")
147-
monkeypatch.setenv("AZURE_STORAGE_GEN2_CONNECTION_STRING", "")
148-
149-
# need shared client so both blob and adls APIs can point to same temp directory
150-
shared_client = mocked_client_class_factory(test_dir, adls_gen2=adls_gen2)()
140+
blob_client.upload_blob(test_file.read_bytes(), overwrite=True)
141+
else:
142+
monkeypatch.setenv("AZURE_STORAGE_CONNECTION_STRING", "")
143+
monkeypatch.setenv("AZURE_STORAGE_GEN2_CONNECTION_STRING", "")
151144

152-
monkeypatch.setattr(
153-
cloudpathlib.azure.azblobclient,
154-
"BlobServiceClient",
155-
shared_client,
156-
)
145+
# need shared client so both blob and adls APIs can point to same temp directory
146+
shared_client = mocked_client_class_factory(test_dir, adls_gen2=adls_gen2)()
157147

158-
monkeypatch.setattr(
159-
cloudpathlib.azure.azblobclient,
160-
"DataLakeServiceClient",
161-
mocked_adls_factory(test_dir, shared_client),
162-
)
148+
monkeypatch.setattr(
149+
cloudpathlib.azure.azblobclient,
150+
"BlobServiceClient",
151+
shared_client,
152+
)
163153

164-
rig = CloudProviderTestRig(
165-
path_class=AzureBlobPath,
166-
client_class=AzureBlobClient,
167-
drive=drive,
168-
test_dir=test_dir,
169-
live_server=live_server,
154+
monkeypatch.setattr(
155+
cloudpathlib.azure.azblobclient,
156+
"DataLakeServiceClient",
157+
mocked_adls_factory(test_dir, shared_client),
170158
)
171159

172-
rig.client_class().set_as_default_client() # set default client
160+
rig = CloudProviderTestRig(
161+
path_class=AzureBlobPath,
162+
client_class=AzureBlobClient,
163+
drive=drive,
164+
test_dir=test_dir,
165+
live_server=live_server,
166+
required_client_kwargs=dict(connection_string=os.getenv(conn_str_env_var)), # switch on/off adls gen2
167+
)
168+
169+
rig.client_class(connection_string=os.getenv(conn_str_env_var)).set_as_default_client() # set default client
170+
171+
# add flag for adls gen2 rig to skip some tests
172+
rig.is_adls_gen2 = adls_gen2
173173

174-
yield rig
174+
yield rig
175175

176-
rig.client_class._default_client = None # reset default client
176+
rig.client_class._default_client = None # reset default client
177177

178-
if live_server:
179-
if blob_service_client.get_account_information().get("is_hns_enabled", False):
180-
_hns_rmtree(data_lake_service_client, drive, test_dir)
178+
if live_server:
179+
if blob_service_client.get_account_information().get("is_hns_enabled", False):
180+
_hns_rmtree(data_lake_service_client, drive, test_dir)
181181

182-
else:
183-
# Clean up test dir
184-
container_client = blob_service_client.get_container_client(drive)
185-
to_delete = container_client.list_blobs(name_starts_with=test_dir)
186-
to_delete = sorted(to_delete, key=lambda b: len(b.name.split("/")), reverse=True)
182+
else:
183+
# Clean up test dir
184+
container_client = blob_service_client.get_container_client(drive)
185+
to_delete = container_client.list_blobs(name_starts_with=test_dir)
186+
to_delete = sorted(to_delete, key=lambda b: len(b.name.split("/")), reverse=True)
187187

188-
container_client.delete_blobs(*to_delete)
188+
container_client.delete_blobs(*to_delete)
189189

190-
return azure_rig
190+
191+
@fixture()
192+
def azure_rig(request, monkeypatch, assets_dir):
193+
yield from _azure_fixture("AZURE_STORAGE_CONNECTION_STRING", False, request, monkeypatch, assets_dir)
194+
195+
@fixture()
196+
def azure_gen2_rig(request, monkeypatch, assets_dir):
197+
yield from _azure_fixture("AZURE_STORAGE_GEN2_CONNECTION_STRING", True, request, monkeypatch, assets_dir)
191198

192199

193200
@fixture()
@@ -435,9 +442,6 @@ def local_s3_rig(request, monkeypatch, assets_dir):
435442
rig.client_class.reset_default_storage_dir() # reset local storage directory
436443

437444

438-
azure_rig = azure_rig_factory("AZURE_STORAGE_CONNECTION_STRING")
439-
azure_gen2_rig = azure_rig_factory("AZURE_STORAGE_GEN2_CONNECTION_STRING")
440-
441445
# create azure fixtures for both blob and gen2 storage
442446
azure_rigs = fixture_union(
443447
"azure_rigs",

tests/test_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010

1111
def test_default_client_instantiation(rig):
12-
if not getattr(rig, "is_custom_s3", False):
12+
if not getattr(rig, "is_custom_s3", False) and not (getattr(rig, "is_adls_gen2", False)):
1313
# Skip resetting the default client for custom S3 endpoint, but keep the other tests,
1414
# since they're still useful.
1515
rig.client_class._default_client = None
@@ -43,7 +43,7 @@ def test_default_client_instantiation(rig):
4343
def test_different_clients(rig):
4444
p = rig.create_cloud_path("dir_0/file0_0.txt")
4545

46-
new_client = rig.client_class()
46+
new_client = rig.client_class(**rig.required_client_kwargs)
4747
p2 = new_client.CloudPath(f"{rig.cloud_prefix}{rig.drive}/{rig.test_dir}/dir_0/file0_0.txt")
4848

4949
assert p.client is not p2.client

tests/test_cloudpath_instantiation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def test_instantiation_errors(rig):
7777
def test_idempotency(rig):
7878
rig.client_class._default_client = None
7979

80-
client = rig.client_class()
80+
client = rig.client_class(**rig.required_client_kwargs)
8181
p = client.CloudPath(f"{rig.cloud_prefix}{rig.drive}/{rig.test_dir}/dir_0/file0_0.txt")
8282

8383
p2 = CloudPath(p)

tests/test_cloudpath_manipulation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def test_joins(rig):
120120
def test_with_segments(rig):
121121
assert rig.create_cloud_path("a/b/c/d").with_segments(
122122
"x", "y", "z"
123-
) == rig.client_class().CloudPath(f"{rig.cloud_prefix}x/y/z")
123+
) == rig.client_class(**rig.required_client_kwargs).CloudPath(f"{rig.cloud_prefix}x/y/z")
124124

125125

126126
def test_is_junction(rig):

0 commit comments

Comments
 (0)