From 815b261baa31df2c849a16a2f36d99d585eeb78a Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:25:54 -0700 Subject: [PATCH 01/10] add ruff action --- .github/workflows/format.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/format.yml diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 00000000..1e41c6bf --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,25 @@ +name: Lint and Format +on: + push: + branches: + - master + pull_request: + branches: master + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + # Allows other workflows to trigger this workflow + workflow_call: +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + with: + args: check --fix + - uses: chartboost/ruff-action@v1 + with: + args: format + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "style fixes by ruff" From 94b3eae1a40d3296ff8d83955f23f99d3adcb37e Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:27:35 -0700 Subject: [PATCH 02/10] apply ruff check --fix --- tests/test_annotation.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 753a7e39..7d58fae9 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -1,12 +1,8 @@ import pytest -from caveclient import CAVEclient from caveclient.endpoints import annotation_endpoints_v2, schema_endpoints_v2 -import pandas as pd import responses -from urllib.parse import urlencode from .conftest import TEST_DATASTACK, test_info, TEST_LOCAL_SERVER, TEST_GLOBAL_SERVER import numpy as np -from caveclient.base import BaseEncoder import json import jsonschema From ff5fd4435051462e10894dd62435fce37515885d Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:27:50 -0700 Subject: [PATCH 03/10] apply ruff format --- caveclient/chunkedgraph.py | 12 ++--- caveclient/emannotationschemas.py | 16 +++--- caveclient/materializationengine.py | 26 +++------- caveclient/tools/table_manager.py | 51 ++++++++++--------- tests/conftest.py | 4 +- tests/test_annotation.py | 2 +- tests/test_materialization.py | 79 +++++++++++++++++++++-------- 7 files changed, 113 insertions(+), 77 deletions(-) diff --git a/caveclient/chunkedgraph.py b/caveclient/chunkedgraph.py index 154015f7..b7cad8b8 100644 --- a/caveclient/chunkedgraph.py +++ b/caveclient/chunkedgraph.py @@ -785,11 +785,11 @@ def level2_chunk_graph(self, root_id, bounds=None) -> list: Root id of object bounds : np.array 3x2 bounding box (x,y,z) x (min,max) in chunked graph coordinates (use - `client.chunkedgraph.base_resolution` to view this default resolution for - your chunkedgraph client). Note that the result will include any level 2 - nodes which have chunk boundaries within some part of this bounding box, - meaning that the representative point for a given level 2 node could still - be slightly outside of these bounds. If None, returns all level 2 chunks + `client.chunkedgraph.base_resolution` to view this default resolution for + your chunkedgraph client). Note that the result will include any level 2 + nodes which have chunk boundaries within some part of this bounding box, + meaning that the representative point for a given level 2 node could still + be slightly outside of these bounds. If None, returns all level 2 chunks for the root ID. Returns @@ -807,7 +807,7 @@ def level2_chunk_graph(self, root_id, bounds=None) -> list: url = self._endpoints["lvl2_graph"].format_map(endpoint_mapping) response = self.session.get(url, params=query_d) - + r = handle_response(response) used_bounds = response.headers.get("Used-Bounds") diff --git a/caveclient/emannotationschemas.py b/caveclient/emannotationschemas.py index 3fa50ca6..58d2eb39 100644 --- a/caveclient/emannotationschemas.py +++ b/caveclient/emannotationschemas.py @@ -4,6 +4,7 @@ from .auth import AuthClient from requests import HTTPError import logging + logger = logging.getLogger(__name__) server_key = "emas_server_address" @@ -81,7 +82,7 @@ def get_schemas(self) -> list[str]: url = self._endpoints["schema"].format_map(endpoint_mapping) response = self.session.get(url) return handle_response(response) - + def schema_definition(self, schema_type: str) -> dict[str]: """Get the definition of a specified schema_type @@ -108,7 +109,7 @@ def schema_definition_multi(self, schema_types: list[str]) -> dict: ---------- schema_types : list List of schema names - + Returns ------- dict @@ -116,12 +117,14 @@ def schema_definition_multi(self, schema_types: list[str]) -> dict: """ endpoint_mapping = self.default_url_mapping url = self._endpoints["schema_definition_multi"].format_map(endpoint_mapping) - data={'schema_names': ','.join(schema_types)} + data = {"schema_names": ",".join(schema_types)} response = self.session.post(url, params=data) try: return handle_response(response) except HTTPError: - logger.warning('Client requested an schema service endpoint (see "schema_definition_multi") not yet available on your deployment. Please talk to your admin about updating your deployment') + logger.warning( + 'Client requested an schema service endpoint (see "schema_definition_multi") not yet available on your deployment. Please talk to your admin about updating your deployment' + ) return None def schema_definition_all(self) -> dict[str]: @@ -138,11 +141,12 @@ def schema_definition_all(self) -> dict[str]: try: return handle_response(response) except HTTPError: - logger.warning('Client requested an schema service endpoint (see "schema_definition_all") not yet available on your deployment. Please talk to your admin about updating your deployment') + logger.warning( + 'Client requested an schema service endpoint (see "schema_definition_all") not yet available on your deployment. Please talk to your admin about updating your deployment' + ) return None - client_mapping = { 1: SchemaClientLegacy, 2: SchemaClientLegacy, diff --git a/caveclient/materializationengine.py b/caveclient/materializationengine.py index 89d9dfd3..7f46dedf 100644 --- a/caveclient/materializationengine.py +++ b/caveclient/materializationengine.py @@ -258,7 +258,7 @@ def __init__( @property def datastack_name(self): return self._datastack_name - + @property def cg_client(self): if self._cg_client is None: @@ -296,7 +296,7 @@ def tables(self) -> TableManager: else: raise ValueError("No full CAVEclient specified") return self._tables - + @property def views(self) -> ViewManager: if self._views is None: @@ -1894,25 +1894,15 @@ def __init__(self, *args, **kwargs): self.get_tables_metadata, ) ) - metadata.append( - executor.submit( - self.fc.schema.schema_definition_all - ) - ) - metadata.append( - executor.submit( - self.get_views - ) - ) - metadata.append( - executor.submit( - self.get_view_schemas - ) - ) + metadata.append(executor.submit(self.fc.schema.schema_definition_all)) + metadata.append(executor.submit(self.get_views)) + metadata.append(executor.submit(self.get_view_schemas)) tables = None if self.fc is not None: if metadata[0].result() is not None and metadata[1].result() is not None: - tables = TableManager(self.fc, metadata[0].result(), metadata[1].result()) + tables = TableManager( + self.fc, metadata[0].result(), metadata[1].result() + ) self._tables = tables if self.fc is not None: views = ViewManager(self.fc, metadata[2].result(), metadata[3].result()) diff --git a/caveclient/tools/table_manager.py b/caveclient/tools/table_manager.py index da9f0b28..37ba0f00 100644 --- a/caveclient/tools/table_manager.py +++ b/caveclient/tools/table_manager.py @@ -117,20 +117,23 @@ def _schema_key(schema_name, client, **kwargs): key = keys.hashkey(schema_name, str(allow_types)) return key + def populate_schema_cache(client, schema_definitions=None): if schema_definitions is None: schema_definitions = client.schema.schema_definition_all() if schema_definitions is None: - schema_definitions = {sn:None for sn in client.schema.get_schemas()} + schema_definitions = {sn: None for sn in client.schema.get_schemas()} for schema_name, schema_definition in schema_definitions.items(): get_col_info(schema_name, client, schema_definition=schema_definition) + def populate_table_cache(client, metadata=None): if metadata is None: metadata = get_all_table_metadata(client) for tn, meta in metadata.items(): table_metadata(tn, client, meta=meta) + @cached(cache=_schema_cache, key=_schema_key) def get_col_info( schema_name, @@ -296,6 +299,7 @@ def get_table_info( _metadata_cache = TTLCache(maxsize=128, ttl=86_400) + def _metadata_key(tn, client, **kwargs): key = keys.hashkey(tn) return key @@ -567,26 +571,26 @@ def query( ): """Query views through the table interface - Parameters - ---------- - select_columns : list[str], optional - Specification of columns to return, by default None - offset : int, optional - Integer offset from the beginning of the table to return, by default None. - Used when tables are too large to return in one query. - limit : int, optional - Maximum number of rows to return, by default None - split_positions : bool, optional - If true, returns each point coordinate as a separate column, by default False - materialization_version : int, optional - Query a specified materialization version, by default None - metadata : bool, optional - If true includes query and table metadata in the .attrs property of the returned dataframe, by default True - desired_resolution : list[int], optional - Sets the 3d point resolution in nm, by default None. - If default, uses the values in the table directly. - get_counts : bool, optional - Only return number of rows in the query, by default False + Parameters + ---------- + select_columns : list[str], optional + Specification of columns to return, by default None + offset : int, optional + Integer offset from the beginning of the table to return, by default None. + Used when tables are too large to return in one query. + limit : int, optional + Maximum number of rows to return, by default None + split_positions : bool, optional + If true, returns each point coordinate as a separate column, by default False + materialization_version : int, optional + Query a specified materialization version, by default None + metadata : bool, optional + If true includes query and table metadata in the .attrs property of the returned dataframe, by default True + desired_resolution : list[int], optional + Sets the 3d point resolution in nm, by default None. + If default, uses the values in the table directly. + get_counts : bool, optional + Only return number of rows in the query, by default False """ logger.warning( "The `client.materialize.views` interface is experimental and might experience breaking changes before the feature is stabilized." @@ -676,7 +680,7 @@ def __repr__(self): @property def table_names(self): return self._tables - + def __len__(self): return len(self._tables) @@ -710,7 +714,6 @@ def __repr__(self): @property def table_names(self): return self._views - + def __len__(self): return len(self._views) - diff --git a/tests/conftest.py b/tests/conftest.py index 2df4991a..4544c3b5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -38,5 +38,7 @@ def myclient(): responses.add(responses.GET, url, json=test_info, status=200) - client = CAVEclient(TEST_DATASTACK, server_address=TEST_GLOBAL_SERVER, write_server_cache=False) + client = CAVEclient( + TEST_DATASTACK, server_address=TEST_GLOBAL_SERVER, write_server_cache=False + ) return client diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 7d58fae9..228acc5e 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -183,4 +183,4 @@ def test_staged_post(self, myclient, mocker): with pytest.raises(ValueError): myclient.annotation.upload_staged_annotations(schema_stage) schema_stage.table_name = self.default_mapping.get("table_name") - myclient.annotation.upload_staged_annotations(schema_stage) \ No newline at end of file + myclient.annotation.upload_staged_annotations(schema_stage) diff --git a/tests/test_materialization.py b/tests/test_materialization.py index f94e2ac2..014e0da8 100644 --- a/tests/test_materialization.py +++ b/tests/test_materialization.py @@ -318,40 +318,77 @@ class TestMatclient: def test_matclient_v3_tableinterface(self, myclient, mocker): myclient = copy.deepcopy(myclient) endpoint_mapping = self.default_mapping - endpoint_mapping['emas_server_address'] = TEST_GLOBAL_SERVER + endpoint_mapping["emas_server_address"] = TEST_GLOBAL_SERVER api_versions_url = chunkedgraph_endpoints_common["get_api_versions"].format_map( endpoint_mapping ) - responses.add(responses.GET, url=api_versions_url, json=[0,1], status=200) - responses.add(responses.GET, url=materialization_common['get_api_versions'].format_map(endpoint_mapping), json=[3], status=200) - - versionurl = materialization_endpoints_v3["versions"].format_map(endpoint_mapping) - responses.add(responses.GET, url=versionurl, json=[1], status=200, match=[query_param_matcher({'expired': False})],) - - all_tables_meta_url = materialization_endpoints_v3["all_tables_metadata"].format_map(endpoint_mapping) - responses.add(responses.GET, url=all_tables_meta_url, json=self.multitable_meta, status=200) + responses.add(responses.GET, url=api_versions_url, json=[0, 1], status=200) + responses.add( + responses.GET, + url=materialization_common["get_api_versions"].format_map(endpoint_mapping), + json=[3], + status=200, + ) + + versionurl = materialization_endpoints_v3["versions"].format_map( + endpoint_mapping + ) + responses.add( + responses.GET, + url=versionurl, + json=[1], + status=200, + match=[query_param_matcher({"expired": False})], + ) + + all_tables_meta_url = materialization_endpoints_v3[ + "all_tables_metadata" + ].format_map(endpoint_mapping) + responses.add( + responses.GET, + url=all_tables_meta_url, + json=self.multitable_meta, + status=200, + ) - all_schema_def_url = schema_endpoints_v2["schema_definition_all"].format_map(endpoint_mapping) - responses.add(responses.GET, url=all_schema_def_url, json=self.multischema_meta, status=200) + all_schema_def_url = schema_endpoints_v2["schema_definition_all"].format_map( + endpoint_mapping + ) + responses.add( + responses.GET, + url=all_schema_def_url, + json=self.multischema_meta, + status=200, + ) - get_views_url = materialization_endpoints_v3["get_views"].format_map(endpoint_mapping) - responses.add(responses.GET, url=get_views_url, json=self.views_list, status=200) + get_views_url = materialization_endpoints_v3["get_views"].format_map( + endpoint_mapping + ) + responses.add( + responses.GET, url=get_views_url, json=self.views_list, status=200 + ) - get_views_schema_url = materialization_endpoints_v3["view_schemas"].format_map(endpoint_mapping) + get_views_schema_url = materialization_endpoints_v3["view_schemas"].format_map( + endpoint_mapping + ) print(get_views_schema_url) - responses.add(responses.GET, url=get_views_schema_url, json=self.views_schema, status=200) + responses.add( + responses.GET, url=get_views_schema_url, json=self.views_schema, status=200 + ) assert len(myclient.materialize.tables) == 2 - qry = myclient.materialize.tables.allen_column_mtypes_v2(pt_root_id=[123, 456], target_id=271700) + qry = myclient.materialize.tables.allen_column_mtypes_v2( + pt_root_id=[123, 456], target_id=271700 + ) params = qry.filter_kwargs_live - assert 'allen_column_mtypes_v2' in params.get('filter_equal_dict') - assert 'nucleus_detection_v0' in params.get('filter_in_dict') - assert 'allen_column_mtypes_v2' == qry.joins_kwargs.get('joins')[0][0] + assert "allen_column_mtypes_v2" in params.get("filter_equal_dict") + assert "nucleus_detection_v0" in params.get("filter_in_dict") + assert "allen_column_mtypes_v2" == qry.joins_kwargs.get("joins")[0][0] - assert 'single_neurons' in myclient.materialize.views + assert "single_neurons" in myclient.materialize.views vqry = myclient.materialize.views.single_neurons(pt_root_id=[123, 456]) - assert 123 in vqry.filter_kwargs_mat.get('filter_in_dict').get('pt_root_id') + assert 123 in vqry.filter_kwargs_mat.get("filter_in_dict").get("pt_root_id") @responses.activate def test_matclient(self, myclient, mocker): From 8a29d82a044908d6b3dabec8a9b036eb78469a7d Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:36:29 -0700 Subject: [PATCH 04/10] run ruff with import sorting --- .github/workflows/format.yml | 4 ++-- caveclient/base.py | 10 ++++++---- caveclient/datastack_lookup.py | 5 +++-- caveclient/emannotationschemas.py | 9 ++++++--- caveclient/materializationengine.py | 4 ++-- caveclient/mytimer.py | 2 +- caveclient/tools/caching.py | 3 ++- caveclient/tools/stage.py | 4 ++-- caveclient/tools/table_manager.py | 9 +++++---- tests/conftest.py | 6 +++--- tests/test_annotation.py | 13 ++++++++----- tests/test_infoservice.py | 8 +++++--- tests/test_materialization.py | 27 +++++++++++++++------------ 13 files changed, 60 insertions(+), 44 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1e41c6bf..68af51d0 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -16,10 +16,10 @@ jobs: - uses: actions/checkout@v4 - uses: chartboost/ruff-action@v1 with: - args: check --fix + args: check . --fix --select I - uses: chartboost/ruff-action@v1 with: - args: format + args: format . - uses: stefanzweifel/git-auto-commit-action@v5 with: commit_message: "style fixes by ruff" diff --git a/caveclient/base.py b/caveclient/base.py index 7fa4e139..54d5d8cd 100644 --- a/caveclient/base.py +++ b/caveclient/base.py @@ -1,16 +1,18 @@ -import urllib -import requests import json import logging +import urllib + +import requests logger = logging.getLogger(__name__) +import datetime import webbrowser -from .session_config import patch_session import numpy as np -import datetime import pandas as pd +from .session_config import patch_session + class BaseEncoder(json.JSONEncoder): def default(self, obj): diff --git a/caveclient/datastack_lookup.py b/caveclient/datastack_lookup.py index e8f64520..11cd4623 100644 --- a/caveclient/datastack_lookup.py +++ b/caveclient/datastack_lookup.py @@ -1,7 +1,8 @@ -import os import json -from . import auth import logging +import os + +from . import auth logger = logging.getLogger(__name__) diff --git a/caveclient/emannotationschemas.py b/caveclient/emannotationschemas.py index 58d2eb39..cb9e8ae1 100644 --- a/caveclient/emannotationschemas.py +++ b/caveclient/emannotationschemas.py @@ -1,9 +1,12 @@ from __future__ import annotations + +import logging + +from requests import HTTPError + +from .auth import AuthClient from .base import ClientBase, _api_endpoints, handle_response from .endpoints import schema_api_versions, schema_endpoints_common -from .auth import AuthClient -from requests import HTTPError -import logging logger = logging.getLogger(__name__) diff --git a/caveclient/materializationengine.py b/caveclient/materializationengine.py index 7f46dedf..fc0269d9 100644 --- a/caveclient/materializationengine.py +++ b/caveclient/materializationengine.py @@ -3,17 +3,17 @@ import logging import re import warnings +from concurrent.futures import ThreadPoolExecutor from datetime import datetime, timezone from typing import Iterable, Optional, Union -from requests import HTTPError import numpy as np import pandas as pd import pyarrow as pa import pytz -from concurrent.futures import ThreadPoolExecutor from cachetools import TTLCache, cached from IPython.display import HTML +from requests import HTTPError from .auth import AuthClient from .base import ( diff --git a/caveclient/mytimer.py b/caveclient/mytimer.py index f6480a84..9d8b10fd 100644 --- a/caveclient/mytimer.py +++ b/caveclient/mytimer.py @@ -1,5 +1,5 @@ -from time import time import logging +from time import time logger = logging.getLogger(__name__) diff --git a/caveclient/tools/caching.py b/caveclient/tools/caching.py index 22467007..79da8670 100644 --- a/caveclient/tools/caching.py +++ b/caveclient/tools/caching.py @@ -1,6 +1,7 @@ -from caveclient import CAVEclient from cachetools import TTLCache, cached, keys +from caveclient import CAVEclient + info_cache_cache = TTLCache(maxsize=32, ttl=3600) diff --git a/caveclient/tools/stage.py b/caveclient/tools/stage.py index d4b5d9c1..ebd7b175 100644 --- a/caveclient/tools/stage.py +++ b/caveclient/tools/stage.py @@ -1,7 +1,7 @@ -import jsonschema import attrs -import pandas as pd +import jsonschema import numpy as np +import pandas as pd SPATIAL_POINT_CLASSES = ["SpatialPoint", "BoundSpatialPoint"] diff --git a/caveclient/tools/table_manager.py b/caveclient/tools/table_manager.py index 37ba0f00..b1bd15f1 100644 --- a/caveclient/tools/table_manager.py +++ b/caveclient/tools/table_manager.py @@ -1,8 +1,9 @@ -import attrs -import warnings -import re -from cachetools import cached, TTLCache, keys import logging +import re +import warnings + +import attrs +from cachetools import TTLCache, cached, keys logger = logging.getLogger(__name__) diff --git a/tests/conftest.py b/tests/conftest.py index 4544c3b5..7fbf89b7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,9 +1,9 @@ +import os + import pytest import responses -from caveclient import CAVEclient -import os -from caveclient import endpoints +from caveclient import CAVEclient, endpoints TEST_GLOBAL_SERVER = os.environ.get("TEST_SERVER", "https://test.cave.com") TEST_LOCAL_SERVER = os.environ.get("TEST_LOCAL_SERVER", "https://local.cave.com") diff --git a/tests/test_annotation.py b/tests/test_annotation.py index 228acc5e..0c7ed6cd 100644 --- a/tests/test_annotation.py +++ b/tests/test_annotation.py @@ -1,10 +1,13 @@ -import pytest -from caveclient.endpoints import annotation_endpoints_v2, schema_endpoints_v2 -import responses -from .conftest import TEST_DATASTACK, test_info, TEST_LOCAL_SERVER, TEST_GLOBAL_SERVER -import numpy as np import json + import jsonschema +import numpy as np +import pytest +import responses + +from caveclient.endpoints import annotation_endpoints_v2, schema_endpoints_v2 + +from .conftest import TEST_DATASTACK, TEST_GLOBAL_SERVER, TEST_LOCAL_SERVER, test_info test_jsonschema = { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/tests/test_infoservice.py b/tests/test_infoservice.py index 804242a0..69713dfc 100644 --- a/tests/test_infoservice.py +++ b/tests/test_infoservice.py @@ -1,7 +1,9 @@ -from caveclient.endpoints import infoservice_endpoints_v2 -import responses -from .conftest import test_info, TEST_DATASTACK, TEST_GLOBAL_SERVER import numpy as np +import responses + +from caveclient.endpoints import infoservice_endpoints_v2 + +from .conftest import TEST_DATASTACK, TEST_GLOBAL_SERVER, test_info def test_info_d(myclient): diff --git a/tests/test_materialization.py b/tests/test_materialization.py index 014e0da8..c3981c43 100644 --- a/tests/test_materialization.py +++ b/tests/test_materialization.py @@ -1,22 +1,25 @@ +import copy +import datetime +from io import BytesIO +from urllib.parse import urlencode + +import numpy as np +import pandas as pd +import pyarrow as pa import pytest +import responses +from responses.matchers import json_params_matcher, query_param_matcher + from caveclient import materializationengine from caveclient.endpoints import ( - materialization_endpoints_v2, chunkedgraph_endpoints_common, + materialization_common, + materialization_endpoints_v2, materialization_endpoints_v3, schema_endpoints_v2, - materialization_common, ) -import pandas as pd -import responses -from responses.matchers import json_params_matcher, query_param_matcher -import pyarrow as pa -from urllib.parse import urlencode -import copy -from .conftest import test_info, TEST_LOCAL_SERVER, TEST_DATASTACK, TEST_GLOBAL_SERVER -import datetime -import numpy as np -from io import BytesIO + +from .conftest import TEST_DATASTACK, TEST_GLOBAL_SERVER, TEST_LOCAL_SERVER, test_info def test_info_d(myclient): From 2496c5e37d7348a04a9d780e581b899cc28e377c Mon Sep 17 00:00:00 2001 From: bdpedigo Date: Thu, 21 Mar 2024 20:36:52 +0000 Subject: [PATCH 05/10] style fixes by ruff --- caveclient/chunkedgraph.py | 1 + 1 file changed, 1 insertion(+) diff --git a/caveclient/chunkedgraph.py b/caveclient/chunkedgraph.py index b7cad8b8..2642b7f8 100644 --- a/caveclient/chunkedgraph.py +++ b/caveclient/chunkedgraph.py @@ -1,4 +1,5 @@ """PyChunkedgraph service python interface""" + import datetime import json import logging From d52afb342acca474863025cf01ff8697b7d90a54 Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:37:37 -0700 Subject: [PATCH 06/10] fix e402 --- caveclient/base.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/caveclient/base.py b/caveclient/base.py index 54d5d8cd..021fddc9 100644 --- a/caveclient/base.py +++ b/caveclient/base.py @@ -1,18 +1,17 @@ +import datetime import json import logging import urllib - -import requests - -logger = logging.getLogger(__name__) -import datetime import webbrowser import numpy as np import pandas as pd +import requests from .session_config import patch_session +logger = logging.getLogger(__name__) + class BaseEncoder(json.JSONEncoder): def default(self, obj): From 6610cd2e11962f92b616ae5d1a2f07e423dd292f Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Thu, 21 Mar 2024 13:43:42 -0700 Subject: [PATCH 07/10] add sort import properly --- .github/workflows/format.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 68af51d0..3698be12 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -15,8 +15,8 @@ jobs: steps: - uses: actions/checkout@v4 - uses: chartboost/ruff-action@v1 - with: - args: check . --fix --select I + with: # the --extend-select flag adds import sorting + args: check . --fix --extend-select I - uses: chartboost/ruff-action@v1 with: args: format . From 31857f8905252d8aa82f731e2485c35c5ab2959f Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Fri, 22 Mar 2024 16:35:06 -0700 Subject: [PATCH 08/10] add some noqa and fix easy ones --- .github/workflows/format.yml | 7 ++----- caveclient/base.py | 2 +- caveclient/datastack_lookup.py | 2 +- caveclient/tools/table_manager.py | 19 +++++++++---------- tests/test_infoservice.py | 2 +- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 3698be12..bb927427 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -16,10 +16,7 @@ jobs: - uses: actions/checkout@v4 - uses: chartboost/ruff-action@v1 with: # the --extend-select flag adds import sorting - args: check . --fix --extend-select I + args: check . --extend-select I - uses: chartboost/ruff-action@v1 with: - args: format . - - uses: stefanzweifel/git-auto-commit-action@v5 - with: - commit_message: "style fixes by ruff" + args: format . --check diff --git a/caveclient/base.py b/caveclient/base.py index 021fddc9..c290ab98 100644 --- a/caveclient/base.py +++ b/caveclient/base.py @@ -150,7 +150,7 @@ def _api_endpoints( verify=verify, ) avail_vs_server = set(avail_vs_server) - except: + except: # noqa: E722 avail_vs_server = None avail_vs_client = set(endpoint_versions.keys()) diff --git a/caveclient/datastack_lookup.py b/caveclient/datastack_lookup.py index 11cd4623..6641b58c 100644 --- a/caveclient/datastack_lookup.py +++ b/caveclient/datastack_lookup.py @@ -17,7 +17,7 @@ def read_map(filename=None): with open(os.path.expanduser(filename), "r") as f: data = json.load(f) return data - except: + except: # noqa E722 return {} diff --git a/caveclient/tools/table_manager.py b/caveclient/tools/table_manager.py index b1bd15f1..a46ff5d6 100644 --- a/caveclient/tools/table_manager.py +++ b/caveclient/tools/table_manager.py @@ -79,10 +79,9 @@ def get_all_view_metadata(client): def is_list_like(x): if isinstance(x, str): return False - try: - len(x) + if hasattr(x, "__len__"): return True - except: + else: return False @@ -379,10 +378,10 @@ def __attrs_post_init__(self): tn: filter_empty( attrs.asdict( self, - filter=lambda a, v: is_list_like(v) == False + filter=lambda a, v: not is_list_like(v) and v is not None - and a.metadata.get("is_bbox", False) == False - and a.metadata.get("is_meta", False) == False + and a.metadata.get("is_bbox", False) == False # noqa E712 + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) @@ -392,10 +391,10 @@ def __attrs_post_init__(self): tn: filter_empty( attrs.asdict( self, - filter=lambda a, v: is_list_like(v) == True + filter=lambda a, v: is_list_like(v) and v is not None - and a.metadata.get("is_bbox", False) == False - and a.metadata.get("is_meta", False) == False + and a.metadata.get("is_bbox", False) == False # noqa E712 + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) @@ -407,7 +406,7 @@ def __attrs_post_init__(self): self, filter=lambda a, v: a.metadata.get("is_bbox", False) and v is not None - and a.metadata.get("is_meta", False) == False + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) diff --git a/tests/test_infoservice.py b/tests/test_infoservice.py index 69713dfc..4f1f8ca0 100644 --- a/tests/test_infoservice.py +++ b/tests/test_infoservice.py @@ -20,7 +20,7 @@ class TestInfoClient: @responses.activate def test_infoclient(self, myclient, mocker): - endpoint_mapping = self.default_mapping + endpoint_mapping = self.default_mapping # noqa F841 assert myclient.info.segmentation_source() == test_info["segmentation_source"] assert ( From 6045270ff0f9ea4b2e8b7e2ef5f09e4aebfa3bdf Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Fri, 22 Mar 2024 16:35:51 -0700 Subject: [PATCH 09/10] reformat --- caveclient/base.py | 2 +- caveclient/datastack_lookup.py | 2 +- caveclient/tools/table_manager.py | 10 +++++----- tests/test_infoservice.py | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/caveclient/base.py b/caveclient/base.py index c290ab98..acf886ef 100644 --- a/caveclient/base.py +++ b/caveclient/base.py @@ -150,7 +150,7 @@ def _api_endpoints( verify=verify, ) avail_vs_server = set(avail_vs_server) - except: # noqa: E722 + except: # noqa: E722 avail_vs_server = None avail_vs_client = set(endpoint_versions.keys()) diff --git a/caveclient/datastack_lookup.py b/caveclient/datastack_lookup.py index 6641b58c..7734dd16 100644 --- a/caveclient/datastack_lookup.py +++ b/caveclient/datastack_lookup.py @@ -17,7 +17,7 @@ def read_map(filename=None): with open(os.path.expanduser(filename), "r") as f: data = json.load(f) return data - except: # noqa E722 + except: # noqa E722 return {} diff --git a/caveclient/tools/table_manager.py b/caveclient/tools/table_manager.py index a46ff5d6..253ec950 100644 --- a/caveclient/tools/table_manager.py +++ b/caveclient/tools/table_manager.py @@ -380,8 +380,8 @@ def __attrs_post_init__(self): self, filter=lambda a, v: not is_list_like(v) and v is not None - and a.metadata.get("is_bbox", False) == False # noqa E712 - and a.metadata.get("is_meta", False) == False # noqa E712 + and a.metadata.get("is_bbox", False) == False # noqa E712 + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) @@ -393,8 +393,8 @@ def __attrs_post_init__(self): self, filter=lambda a, v: is_list_like(v) and v is not None - and a.metadata.get("is_bbox", False) == False # noqa E712 - and a.metadata.get("is_meta", False) == False # noqa E712 + and a.metadata.get("is_bbox", False) == False # noqa E712 + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) @@ -406,7 +406,7 @@ def __attrs_post_init__(self): self, filter=lambda a, v: a.metadata.get("is_bbox", False) and v is not None - and a.metadata.get("is_meta", False) == False # noqa E712 + and a.metadata.get("is_meta", False) == False # noqa E712 and a.metadata.get("table") == tn, ) ) diff --git a/tests/test_infoservice.py b/tests/test_infoservice.py index 4f1f8ca0..d0ff5bcf 100644 --- a/tests/test_infoservice.py +++ b/tests/test_infoservice.py @@ -20,7 +20,7 @@ class TestInfoClient: @responses.activate def test_infoclient(self, myclient, mocker): - endpoint_mapping = self.default_mapping # noqa F841 + endpoint_mapping = self.default_mapping # noqa F841 assert myclient.info.segmentation_source() == test_info["segmentation_source"] assert ( From 9978ee4d4a32688c59440cb42e79faf7b391c778 Mon Sep 17 00:00:00 2001 From: Ben Pedigo Date: Tue, 26 Mar 2024 11:32:56 -0700 Subject: [PATCH 10/10] add info to the contributing guidelines --- docs/contributing.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/docs/contributing.md b/docs/contributing.md index fb82c161..fad7bd13 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -31,8 +31,8 @@ and "help wanted" is open to whoever wants to implement it. ### Write Documentation -networkframe could always use more documentation, whether as part of the -official networkframe docs, in docstrings, or even on the web in blog posts, +`{{ names.package }}` could always use more documentation, whether as part of the +official `{{ names.package }}` docs, in docstrings, or even on the web in blog posts, articles, and such. ### Submit Feedback @@ -57,7 +57,12 @@ git clone git@github.com:your_name_here/{{ names.repo_title }}.git ``` - Ensure [pip](https://pip.pypa.io/en/stable/installation/) is installed. -- Create a virtual environment using pipenv: +- Create a virtual environment (here we use venv): + + ```console + python3 -m venv .venv + ``` + - Start your virtualenv: ```console @@ -71,6 +76,13 @@ git clone git@github.com:your_name_here/{{ names.repo_title }}.git ``` - Make your changes locally +- Install development requirements: + + ```console + pip install -r test_requirements.txt + pip install -e . + ``` + - When you're done making changes, check that your changes pass the tests by running [pytest](https://docs.pytest.org/en/): @@ -82,6 +94,19 @@ git clone git@github.com:your_name_here/{{ names.repo_title }}.git including on multiple operating systems and Python versions. Your pull request will have to pass on all of these before it can be merged. +- Ensure your contribution meets style guidelines. First, install [ruff](https://docs.astral.sh/ruff/): + + ```console + pip install ruff + ``` + +- Fix linting and formatting. From the root of the repository, run the following commands: + + ```console + ruff check . --extend-select I --fix + ruff format . + ``` + - Commit your changes and push your branch to GitHub: ```console @@ -108,5 +133,6 @@ use the [mkdocs-material](https://squidfunk.github.io/mkdocs-material/) theme, a variety of other extensions. !!! note + More information codifying our documentation style and principles coming soon. For now, just try to follow the style of the existing documentation.