Skip to content

Commit

Permalink
Use ruff for linting.
Browse files Browse the repository at this point in the history
ruff and isort disagree about how to sort imports.  flake8-isort seems
to always fail if ruff reformats imports; ruff fails if isort reformats
imports.

ruff doesn't completely format spacing, so autopep8 is still needed for
formatting.
  • Loading branch information
manthey committed Aug 10, 2023
1 parent aa1dc05 commit dcda95e
Show file tree
Hide file tree
Showing 99 changed files with 1,205 additions and 1,005 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ jobs:
steps:
- checkout
- tox:
env: docs,flake8,lintclient
env: docs,lint,lintclient
- store_artifacts:
path: build/docs
- persist_to_workspace:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
- Add an endpoint to make it easier to replace thumbnails ([#1253](../../pull/1253))
- Presets from Large Image Configuration file ([#1248](../../pull/1248))

### Changes
- Minor code changes based on suggestions from ruff linting ([#1257](../../pull/1257))

### Bug Fixes
- Guard against ICC profiles that won't parse ([#1245](../../pull/1245))
- Fix filter button on item lists ([#1251](../../pull/1251))
Expand Down
6 changes: 3 additions & 3 deletions docs/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ By default, instead of storing test environments in a ``.tox`` directory, they a
nodejs and npm for Girder Tests or Development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``nodejs`` version 12.x and a corresponding version of ``npm`` are required to build and test Girder client code. See `nodejs <https://nodejs.org/en/download/>`_ for how to download and install it. Remember to get version 12 or earlier.
``nodejs`` version 14.x and a corresponding version of ``npm`` are required to build and test Girder client code. See `nodejs <https://nodejs.org/en/download/>`_ for how to download and install it. Remember to get version 12 or 14.

Mongo for Girder Tests or Development
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -33,13 +33,13 @@ Tests are run via tox environments:

.. code-block:: bash
tox -e test-py39,flake8,lintclient
tox -e test-py39,lint,lintclient
Or, without Girder:

.. code-block:: bash
tox -e core-py39,flake8
tox -e core-py39,lint
You can build the docs. They are created in the ``docs/build`` directory:

Expand Down
9 changes: 5 additions & 4 deletions examples/algorithm_progression.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def apply_algorithm(algorithm, input_filename, output_dir, params, param_space,
filepath = Path(output_dir, filename)

desc = dict(
**{'path': filename},
**{VARIABLE_LAYERS[i]: v for i, v in enumerate(iteration_id)}
path=filename,
**{VARIABLE_LAYERS[i]: v for i, v in enumerate(iteration_id)},
)

source = large_image.open(input_filename)
Expand Down Expand Up @@ -145,15 +145,16 @@ def sweep_algorithm(algorithm, input_filename, input_params, param_oder, output_
input_params = {}
input_params = {
key: np.linspace(
float(value[0]), float(value[1]), int(value[2]), endpoint=len(value) > 3
float(value[0]), float(value[1]), int(value[2]), endpoint=len(value) > 3,
)
for key, value in input_params.items()
if len(value) >= 3
}
param_order = list(input_params.keys())

if not Path(input_filename).exists():
raise ValueError(f'Cannot locate file {input_filename}.')
msg = f'Cannot locate file {input_filename}.'
raise ValueError(msg)

algorithm = algorithms.ALGORITHM_CODES[algorithm_code]
sig = inspect.signature(algorithm)
Expand Down
8 changes: 3 additions & 5 deletions examples/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,15 @@ def rgb_to_hsi(im):
"""
im = np.moveaxis(im, -1, 0)
if len(im) not in (3, 4):
raise ValueError(
'Expected 3-channel RGB or 4-channel RGBA image; '
'received a {}-channel image'.format(len(im))
)
msg = f'Expected 3-channel RGB or 4-channel RGBA image; received a {len(im)}-channel image'
raise ValueError(msg)
im = im[:3]
hues = (
np.arctan2(3**0.5 * (im[1] - im[2]), 2 * im[0] - im[1] - im[2]) / (2 * np.pi)
) % 1
intensities = im.mean(0)
saturations = np.where(
intensities, 1 - im.min(0) / np.maximum(intensities, 1e-10), 0
intensities, 1 - im.min(0) / np.maximum(intensities, 1e-10), 0,
)
return np.stack([hues, saturations, intensities], -1)

Expand Down
6 changes: 3 additions & 3 deletions examples/average_color.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import argparse

import numpy
import numpy as np

import large_image

Expand Down Expand Up @@ -36,13 +36,13 @@ def average_color(imagePath, magnification=None):
resample=True):
# The tile image data is in tile['tile'] and is a numpy
# multi-dimensional array
mean = numpy.mean(tile['tile'], axis=(0, 1))
mean = np.mean(tile['tile'], axis=(0, 1))
tileMeans.append(mean)
tileWeights.append(tile['width'] * tile['height'])
print('x: %d y: %d w: %d h: %d mag: %g color: %g %g %g' % (
tile['x'], tile['y'], tile['width'], tile['height'],
tile['magnification'], mean[0], mean[1], mean[2]))
mean = numpy.average(tileMeans, axis=0, weights=tileWeights)
mean = np.average(tileMeans, axis=0, weights=tileWeights)
print('Average color: %g %g %g' % (mean[0], mean[1], mean[2]))
return mean

Expand Down
6 changes: 3 additions & 3 deletions examples/sumsquare_color.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import argparse

import numpy
import numpy as np

import large_image

Expand Down Expand Up @@ -33,12 +33,12 @@ def sum_squares(imagePath, magnification=None, **kwargs):
tile['tile_overlap']['left']:
data.shape[1] - tile['tile_overlap']['right'],
:]
sumsq = numpy.sum(data**2, axis=(0, 1))
sumsq = np.sum(data**2, axis=(0, 1))
tileSumSquares.append(sumsq)
print('x: %d y: %d w: %d h: %d mag: %g sums: %d %d %d' % (
tile['x'], tile['y'], tile['width'], tile['height'],
tile['magnification'], sumsq[0], sumsq[1], sumsq[2]))
sumsq = numpy.sum(tileSumSquares, axis=0)
sumsq = np.sum(tileSumSquares, axis=0)
print('Sum of squares: %d %d %d' % (sumsq[0], sumsq[1], sumsq[2]))
return sumsq

Expand Down
9 changes: 5 additions & 4 deletions girder/girder_large_image/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ def _updateJob(event):
'job_id': job['_id'],
'item_id': item['_id'],
'success': status == JobStatus.SUCCESS,
'status': status
'status': status,
},
user={'_id': job.get('userId')},
expires=datetime.datetime.utcnow() + datetime.timedelta(seconds=30))
Expand Down Expand Up @@ -294,7 +294,8 @@ def metadataSearchHandler( # noqa
if any(typ not in models for typ in types):
raise RestException('The metadata search is only able to search in %r.' % models)
if not isinstance(query, str):
raise RestException('The search query must be a string.')
msg = 'The search query must be a string.'
raise RestException(msg)
# If we have the beginning of the field specifier, don't do a search
if re.match(r'^(k|ke|key|key:)$', query.strip()):
return {k: [] for k in types}
Expand All @@ -307,7 +308,7 @@ def metadataSearchHandler( # noqa
pipeline = [
{'$project': {'arrayofkeyvalue': {'$objectToArray': '$$ROOT.%s' % metakey}}},
{'$unwind': '$arrayofkeyvalue'},
{'$group': {'_id': None, 'allkeys': {'$addToSet': '$arrayofkeyvalue.k'}}}
{'$group': {'_id': None, 'allkeys': {'$addToSet': '$arrayofkeyvalue.k'}}},
]
for model in (searchModels or types):
modelInst = ModelImporter.model(*model if isinstance(model, tuple) else [model])
Expand Down Expand Up @@ -588,7 +589,7 @@ def validateNonnegativeInteger(doc):


@setting_utilities.validator({
constants.PluginSettings.LARGE_IMAGE_DEFAULT_VIEWER
constants.PluginSettings.LARGE_IMAGE_DEFAULT_VIEWER,
})
def validateDefaultViewer(doc):
doc['value'] = str(doc['value']).strip()
Expand Down
2 changes: 1 addition & 1 deletion girder/girder_large_image/loadmodelcache.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ def loadModel(resource, model, plugin='_core', id=None, allowCookie=False,
'tokenId': tokenStr,
'expiry': time.time() + LoadModelCacheExpiryDuration,
'result': entry,
'hits': 0
'hits': 0,
}
return entry
28 changes: 15 additions & 13 deletions girder/girder_large_image/models/image_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ def createImageItem(self, item, fileObj, user=None, token=None,
logger.info('createImageItem called on item %s (%s)', item['_id'], item['name'])
# Using setdefault ensures that 'largeImage' is in the item
if 'fileId' in item.setdefault('largeImage', {}):
raise TileGeneralError('Item already has largeImage set.')
msg = 'Item already has largeImage set.'
raise TileGeneralError(msg)
if fileObj['itemId'] != item['_id']:
raise TileGeneralError(
'The provided file must be in the provided item.')
msg = 'The provided file must be in the provided item.'
raise TileGeneralError(msg)
if (item['largeImage'].get('expected') is True and
'jobId' in item['largeImage']):
raise TileGeneralError(
'Item is scheduled to generate a largeImage.')
msg = 'Item is scheduled to generate a largeImage.'
raise TileGeneralError(msg)

item['largeImage'].pop('expected', None)
item['largeImage'].pop('sourceName', None)
Expand All @@ -90,8 +91,8 @@ def createImageItem(self, item, fileObj, user=None, token=None,
logger.info(
'createImageItem will not use item %s (%s) as a largeImage',
item['_id'], item['name'])
raise TileGeneralError(
'A job must be used to generate a largeImage.')
msg = 'A job must be used to generate a largeImage.'
raise TileGeneralError(msg)
logger.debug(
'createImageItem creating a job to generate a largeImage for item %s (%s)',
item['_id'], item['name'])
Expand Down Expand Up @@ -175,8 +176,8 @@ def _createLargeImageLocalJob(

def convertImage(self, item, fileObj, user=None, token=None, localJob=True, **kwargs):
if fileObj['itemId'] != item['_id']:
raise TileGeneralError(
'The provided file must be in the provided item.')
msg = 'The provided file must be in the provided item.'
raise TileGeneralError(msg)
if not localJob:
return self._createLargeImageJob(item, fileObj, user, token, toFolder=True, **kwargs)
return self._createLargeImageLocalJob(item, fileObj, user, toFolder=True, **kwargs)
Expand Down Expand Up @@ -220,10 +221,11 @@ def _tileFromHash(cls, item, x, y, z, mayRedirect=False, **kwargs):
@classmethod
def _loadTileSource(cls, item, **kwargs):
if 'largeImage' not in item:
raise TileSourceError('No large image file in this item.')
msg = 'No large image file in this item.'
raise TileSourceError(msg)
if item['largeImage'].get('expected'):
raise TileSourceError('The large image file for this item is '
'still pending creation.')
msg = 'The large image file for this item is still pending creation.'
raise TileSourceError(msg)

sourceName = item['largeImage']['sourceName']
try:
Expand Down Expand Up @@ -374,7 +376,7 @@ def _getAndCacheImageOrData(
if not hasattr(self, '_getAndCacheImageOrDataLock'):
self._getAndCacheImageOrDataLock = {
'keys': {},
'lock': threading.Lock()
'lock': threading.Lock(),
}
keylock = None
with self._getAndCacheImageOrDataLock['lock']:
Expand Down
10 changes: 5 additions & 5 deletions girder/girder_large_image/rest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,16 @@ def _itemFindRecursive(self, origItemFind, folderId, text, name, limit, offset,
'connectToField': 'parentId',
'depthField': '_depth',
'as': '_folder',
'startWith': '$_id'
'startWith': '$_id',
}},
{'$group': {'_id': '$_folder._id'}}
{'$group': {'_id': '$_folder._id'}},
]
children = [ObjectId(folderId)] + next(Folder().collection.aggregate(pipeline))['_id']
if len(children) > 1:
filters = (filters.copy() if filters else {})
if text:
filters['$text'] = {
'$search': text
'$search': text,
}
if name:
filters['name'] = name
Expand Down Expand Up @@ -121,7 +121,7 @@ def _itemFindRecursive(self, origItemFind, folderId, text, name, limit, offset,
'for admins).')
.modelParam('id', model=Folder, level=AccessType.READ)
.param('name', 'The name of the file.', paramType='path')
.errorResponse()
.errorResponse(),
)
@boundHandler()
def getYAMLConfigFile(self, folder, name):
Expand All @@ -142,7 +142,7 @@ def getYAMLConfigFile(self, folder, name):
.modelParam('id', model=Folder, level=AccessType.WRITE)
.param('name', 'The name of the file.', paramType='path')
.param('config', 'The contents of yaml config file to validate.',
paramType='body')
paramType='body'),
)
@boundHandler()
def putYAMLConfigFile(self, folder, name, config):
Expand Down
14 changes: 7 additions & 7 deletions girder/girder_large_image/rest/item_meta.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ class InternalMetadataItemResource(Item):
def __init__(self, apiRoot):
super().__init__()
apiRoot.item.route(
'GET', (':itemId', 'internal_metadata', ':key'), self.getMetadataKey
'GET', (':itemId', 'internal_metadata', ':key'), self.getMetadataKey,
)
apiRoot.item.route(
'PUT', (':itemId', 'internal_metadata', ':key'), self.updateMetadataKey
'PUT', (':itemId', 'internal_metadata', ':key'), self.updateMetadataKey,
)
apiRoot.item.route(
'DELETE', (':itemId', 'internal_metadata', ':key'), self.deleteMetadataKey
'DELETE', (':itemId', 'internal_metadata', ':key'), self.deleteMetadataKey,
)

@describeRoute(
Expand All @@ -44,7 +44,7 @@ def __init__(self, apiRoot):
default='meta',
)
.errorResponse('ID was invalid.')
.errorResponse('Read access was denied for the item.', 403)
.errorResponse('Read access was denied for the item.', 403),
)
@access.user(scope=TokenScope.DATA_READ)
@loadmodel(model='item', map={'itemId': 'item'}, level=AccessType.READ)
Expand All @@ -55,7 +55,7 @@ def getMetadataKey(self, item, key, params):

@describeRoute(
Description(
'Overwrite the value for a single internal metadata key on this item.'
'Overwrite the value for a single internal metadata key on this item.',
)
.param('itemId', 'The ID of the item.', paramType='path')
.param(
Expand All @@ -72,7 +72,7 @@ def getMetadataKey(self, item, key, params):
paramType='body',
)
.errorResponse('ID was invalid.')
.errorResponse('Write access was denied for the item.', 403)
.errorResponse('Write access was denied for the item.', 403),
)
@access.user(scope=TokenScope.DATA_WRITE)
@loadmodel(model='item', map={'itemId': 'item'}, level=AccessType.WRITE)
Expand All @@ -90,7 +90,7 @@ def updateMetadataKey(self, item, key, params):
default='meta',
)
.errorResponse('ID was invalid.')
.errorResponse('Write access was denied for the item.', 403)
.errorResponse('Write access was denied for the item.', 403),
)
@access.user(scope=TokenScope.DATA_WRITE)
@loadmodel(model='item', map={'itemId': 'item'}, level=AccessType.READ)
Expand Down
Loading

0 comments on commit dcda95e

Please sign in to comment.