diff --git a/api/python/quilt3/data_transfer.py b/api/python/quilt3/data_transfer.py index 219c584de57..7ae97ef5bf4 100644 --- a/api/python/quilt3/data_transfer.py +++ b/api/python/quilt3/data_transfer.py @@ -136,7 +136,7 @@ def find_correct_client(self, api_type, bucket, param_dict): S3Api.LIST_OBJECTS_V2: check_list_objects_v2_works_for_client, S3Api.LIST_OBJECT_VERSIONS: check_list_object_versions_works_for_client } - assert api_type in check_fn_mapper.keys(), f"Only certain APIs are supported with unsigned_client. The " \ + assert api_type in check_fn_mapper, f"Only certain APIs are supported with unsigned_client. The " \ f"API '{api_type}' is not current supported. You may want to use S3ClientProvider.standard_client " \ f"instead " check_fn = check_fn_mapper[api_type] diff --git a/api/python/tests/integration/test_packages.py b/api/python/tests/integration/test_packages.py index 12701ca71dd..1a3e34664ad 100644 --- a/api/python/tests/integration/test_packages.py +++ b/api/python/tests/integration/test_packages.py @@ -1390,7 +1390,7 @@ def test_filter(self): pkg['b'].set_meta({'foo': 'bar'}) p_copy = pkg.filter(lambda lk, entry: lk == 'a/', include_directories=True) - assert list(p_copy) == [] + assert not list(p_copy) p_copy = pkg.filter(lambda lk, entry: lk in ('a/', 'a/df'), include_directories=True) assert list(p_copy) == ['a'] and list(p_copy['a']) == ['df'] @@ -1872,7 +1872,8 @@ def test_push_dest_fn_non_string(self): with self.subTest(value=val): with pytest.raises(TypeError) as excinfo: pkg.push('foo/bar', registry='s3://test-bucket', - dest=(lambda v: lambda *args, **kwargs: v)(val), force=True) + # pylint: disable=cell-var-from-loop + dest=lambda *args, **kwargs: val, force=True) assert 'str is expected' in str(excinfo.value) @patch('quilt3.workflows.validate', mock.MagicMock(return_value=None)) @@ -1882,7 +1883,8 @@ def test_push_dest_fn_non_supported_uri(self): with self.subTest(value=val): with pytest.raises(quilt3.util.URLParseError): pkg.push('foo/bar', registry='s3://test-bucket', - dest=(lambda v: lambda *args, **kwargs: v)(val), force=True) + # pylint: disable=cell-var-from-loop + dest=lambda *args, **kwargs: val, force=True) @patch('quilt3.workflows.validate', mock.MagicMock(return_value=None)) def test_push_dest_fn_s3_uri_with_version_id(self): diff --git a/catalog/CHANGELOG.md b/catalog/CHANGELOG.md index 4966d7d8362..159c9776ffb 100644 --- a/catalog/CHANGELOG.md +++ b/catalog/CHANGELOG.md @@ -17,6 +17,8 @@ where verb is one of ## Changes +- [Fixed] Keep default Intercom launcher closed when closing Package Dialog ([#4244](https://github.com/quiltdata/quilt/pull/4244)) +- [Fixed] Handle invalid bucket name in `ui.sourceBuckets` in bucket config ([#4242](https://github.com/quiltdata/quilt/pull/4242)) - [Added] Preview Markdown while editing ([#4153](https://github.com/quiltdata/quilt/pull/4153)) - [Changed] Athena: hide data catalogs user doesn't have access to ([#4239](https://github.com/quiltdata/quilt/pull/4239)) - [Added] Enable MixPanel tracking in Embed mode ([#4237](https://github.com/quiltdata/quilt/pull/4237)) diff --git a/catalog/app/components/Intercom/Intercom.js b/catalog/app/components/Intercom/Intercom.js index 1803246ebf7..a0b87e965b1 100644 --- a/catalog/app/components/Intercom/Intercom.js +++ b/catalog/app/components/Intercom/Intercom.js @@ -103,6 +103,7 @@ export function useIntercom() { export { IntercomProvider as Provider, useIntercom as use } +// Hides or shows __default__ Intercom launcher when the `condition` changes export function usePauseVisibilityWhen(condition) { const intercom = useIntercom() const [isVisible, setVisible] = React.useState(true) @@ -117,7 +118,8 @@ export function usePauseVisibilityWhen(condition) { [intercom, isVisible, setVisible], ) React.useEffect(() => { + if (intercom.isCustom) return if (condition) showIntercom(false) return () => showIntercom(true) - }, [condition, showIntercom]) + }, [condition, intercom.isCustom, showIntercom]) } diff --git a/catalog/app/containers/Bucket/PackageDialog/S3FilePicker.tsx b/catalog/app/containers/Bucket/PackageDialog/S3FilePicker.tsx index e238620572f..27a617292cd 100644 --- a/catalog/app/containers/Bucket/PackageDialog/S3FilePicker.tsx +++ b/catalog/app/containers/Bucket/PackageDialog/S3FilePicker.tsx @@ -1,3 +1,4 @@ +import type { AWSError } from 'aws-sdk' import invariant from 'invariant' import cx from 'classnames' import * as R from 'ramda' @@ -210,7 +211,19 @@ export function Dialog({ bucket, buckets, selectBucket, open, onClose }: DialogP [selectBucket], ) - const data = useData(bucketListing, { bucket, path, prefix, prev, drain: true }) + const data = useData( + bucketListing, + { + bucket, + path, + prefix, + prev, + drain: true, + }, + { + noAutoFetch: !open, + }, + ) const loadMore = React.useCallback(() => { AsyncResult.case( @@ -275,7 +288,16 @@ export function Dialog({ bucket, buckets, selectBucket, open, onClose }: DialogP {data.case({ // TODO: customized error display? - Err: displayError(), + Err: displayError([ + [ + (e: unknown) => (e as AWSError)?.code === 'InvalidBucketName', + (e: AWSError) => ( + + {e.message} + + ), + ], + ]), Init: () => null, _: (x: $TSFixMe) => { const res: requests.BucketListingResult | null = AsyncResult.getPrevResult(x) diff --git a/lambdas/indexer/test/test_index.py b/lambdas/indexer/test/test_index.py index 05cc0c85a1f..216b78d4303 100644 --- a/lambdas/indexer/test/test_index.py +++ b/lambdas/indexer/test/test_index.py @@ -1504,8 +1504,7 @@ def test_get_contents_large(self, get_memory_mock): @pytest.mark.extended @patch('document_queue.ELASTIC_LIMIT_BYTES', 64_000) def test_get_contents_extended(self): - directory = (BASE_DIR / 'extended') - files = directory.glob('**/*-c000') + files = (BASE_DIR / 'extended').glob('**/*-c000') for f in files: parquet = f.read_bytes() size = len(parquet) @@ -1657,8 +1656,7 @@ def test_parquet_contents(self): # see PRE conditions in conftest.py @pytest.mark.extended def test_parquet_extended(self): - directory = (BASE_DIR / 'extended') - files = directory.glob('**/*.parquet') + files = (BASE_DIR / 'extended').glob('**/*.parquet') for f in files: print(f"Testing {f}") parquet = f.read_bytes() diff --git a/lambdas/shared/tests/test_decorator.py b/lambdas/shared/tests/test_decorator.py index bd68e06960b..93b14b6a387 100644 --- a/lambdas/shared/tests/test_decorator.py +++ b/lambdas/shared/tests/test_decorator.py @@ -184,6 +184,7 @@ def handler(request): code, body, headers = handler(Request(self._make_get({'foo': 'bar'}, None), None)) assert code == 200 assert body == 'blah' + # pylint: disable=use-implicit-booleaness-not-comparison assert headers == {} code, _, headers = handler(Request(self._make_get(None, None), None)) diff --git a/pylintrc b/pylintrc index 4f862167463..5cec2078ac4 100644 --- a/pylintrc +++ b/pylintrc @@ -1,9 +1,12 @@ [MASTER] -ignore-paths=.*/api/python/quilt3/admin/_graphql_client/.* +ignore-paths=api/python/quilt3/admin/_graphql_client/.*,.*/venv/.*,catalog/.* +recursive=yes [MESSAGES CONTROL] disable=attribute-defined-outside-init, broad-except, + broad-exception-raised, + consider-using-f-string, consider-using-sys-exit, cyclic-import, duplicate-code, @@ -28,7 +31,6 @@ disable=attribute-defined-outside-init, no-member, no-name-in-module, no-self-argument, - no-self-use, not-callable, no-value-for-parameter, pointless-statement, @@ -47,7 +49,9 @@ disable=attribute-defined-outside-init, too-many-public-methods, too-many-statements, unnecessary-pass, + unspecified-encoding, unused-argument, unused-variable, + use-dict-literal, wrong-import-order, wrong-import-position,