diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 688c980d31..09ea00a3c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -17,19 +17,19 @@ repos: - id: mixed-line-ending - repo: https://github.com/asottile/pyupgrade - rev: v3.14.0 + rev: v3.17.0 hooks: - id: pyupgrade args: - --py310-plus - repo: https://github.com/MarcoGorelli/absolufy-imports - rev: v0.3.0 + rev: v0.3.1 hooks: - id: absolufy-imports - repo: https://github.com/myint/autoflake - rev: v2.2.1 + rev: v2.3.1 hooks: - id: autoflake args: @@ -38,19 +38,19 @@ repos: - --ignore-init-module-imports - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.8.0 hooks: - id: black name: Run black - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort name: Run isort - repo: https://github.com/sirosen/check-jsonschema - rev: 0.27.0 + rev: 0.29.2 hooks: - id: check-github-workflows - id: check-github-actions @@ -63,7 +63,7 @@ repos: files: pyproject\.toml - repo: https://github.com/jackdewinter/pymarkdown - rev: v0.9.13.4 + rev: v0.9.23 hooks: - id: pymarkdown args: diff --git a/alembic/versions/20240216_9d2dccb0d6ff_ability_to_suppress_works_per_library.py b/alembic/versions/20240216_9d2dccb0d6ff_ability_to_suppress_works_per_library.py index 2b906d8022..a906e05c4c 100644 --- a/alembic/versions/20240216_9d2dccb0d6ff_ability_to_suppress_works_per_library.py +++ b/alembic/versions/20240216_9d2dccb0d6ff_ability_to_suppress_works_per_library.py @@ -9,6 +9,7 @@ See: https://alembic.sqlalchemy.org/en/latest/cookbook.html#building-an-up-to-date-database-from-scratch """ + import sqlalchemy as sa from alembic import op diff --git a/alembic/versions/20240318_3e43ed59f256_playtime_tables_have_no_dependencies.py b/alembic/versions/20240318_3e43ed59f256_playtime_tables_have_no_dependencies.py index 39c758b9ba..06de04213b 100644 --- a/alembic/versions/20240318_3e43ed59f256_playtime_tables_have_no_dependencies.py +++ b/alembic/versions/20240318_3e43ed59f256_playtime_tables_have_no_dependencies.py @@ -5,6 +5,7 @@ Create Date: 2024-03-18 01:34:28.381129+00:00 """ + from functools import cache import sqlalchemy as sa diff --git a/alembic/versions/20240319_b2353c25a95e_add_deferredtasks_table.py b/alembic/versions/20240319_b2353c25a95e_add_deferredtasks_table.py index 9fa7daadac..19b3bfcd8e 100644 --- a/alembic/versions/20240319_b2353c25a95e_add_deferredtasks_table.py +++ b/alembic/versions/20240319_b2353c25a95e_add_deferredtasks_table.py @@ -5,6 +5,7 @@ Create Date: 2024-03-19 21:48:45.911507+00:00 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/alembic/versions/20240417_f532186a3d48_remove_deferredtasks_table.py b/alembic/versions/20240417_f532186a3d48_remove_deferredtasks_table.py index fbf12bee76..b63d106c61 100644 --- a/alembic/versions/20240417_f532186a3d48_remove_deferredtasks_table.py +++ b/alembic/versions/20240417_f532186a3d48_remove_deferredtasks_table.py @@ -5,6 +5,7 @@ Create Date: 2024-04-17 19:03:20.953330+00:00 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/alembic/versions/20240522_50746a3bd243_remove_update_search_index_work_.py b/alembic/versions/20240522_50746a3bd243_remove_update_search_index_work_.py index 34c53dedea..881bcad161 100644 --- a/alembic/versions/20240522_50746a3bd243_remove_update_search_index_work_.py +++ b/alembic/versions/20240522_50746a3bd243_remove_update_search_index_work_.py @@ -5,6 +5,7 @@ Create Date: 2024-05-22 19:08:51.390547+00:00 """ + from alembic import op # revision identifiers, used by Alembic. diff --git a/alembic/versions/20240612_7ba553f3f80d_remove_patron_last_loan_activity_sync.py b/alembic/versions/20240612_7ba553f3f80d_remove_patron_last_loan_activity_sync.py index 9aecc3d3ae..3825742b2f 100644 --- a/alembic/versions/20240612_7ba553f3f80d_remove_patron_last_loan_activity_sync.py +++ b/alembic/versions/20240612_7ba553f3f80d_remove_patron_last_loan_activity_sync.py @@ -5,6 +5,7 @@ Create Date: 2024-06-12 00:53:37.497861+00:00 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.dialects import postgresql diff --git a/alembic/versions/20240821_7a2fcaac8b63_add_loan_identifier_column_to_playtime_tables.py b/alembic/versions/20240821_7a2fcaac8b63_add_loan_identifier_column_to_playtime_tables.py index 0745d84b1c..b3d6dd2100 100644 --- a/alembic/versions/20240821_7a2fcaac8b63_add_loan_identifier_column_to_playtime_tables.py +++ b/alembic/versions/20240821_7a2fcaac8b63_add_loan_identifier_column_to_playtime_tables.py @@ -5,6 +5,7 @@ Create Date: 2024-08-21 23:23:48.085451+00:00 """ + import sqlalchemy as sa from alembic import op from sqlalchemy.orm.session import Session diff --git a/alembic/versions/20240905_350a29bf0ff0_update_existing_marcexporter_protocols.py b/alembic/versions/20240905_350a29bf0ff0_update_existing_marcexporter_protocols.py index e6e7b640c2..bde15e2aca 100644 --- a/alembic/versions/20240905_350a29bf0ff0_update_existing_marcexporter_protocols.py +++ b/alembic/versions/20240905_350a29bf0ff0_update_existing_marcexporter_protocols.py @@ -5,6 +5,7 @@ Create Date: 2024-09-05 16:04:45.789665+00:00 """ + from alembic import op # revision identifiers, used by Alembic. diff --git a/bin/informational/adobe-id-for-short-client-token b/bin/informational/adobe-id-for-short-client-token index 2fbd77cbde..09f99f474d 100755 --- a/bin/informational/adobe-id-for-short-client-token +++ b/bin/informational/adobe-id-for-short-client-token @@ -23,8 +23,7 @@ REGISTRY_RESPONSE_RE = re.compile( ) -class InvalidTokenException(Exception): - ... +class InvalidTokenException(Exception): ... def decompose_token(token): diff --git a/src/palace/manager/api/admin/controller/discovery_service_library_registrations.py b/src/palace/manager/api/admin/controller/discovery_service_library_registrations.py index b2b380e285..ef43e8994c 100644 --- a/src/palace/manager/api/admin/controller/discovery_service_library_registrations.py +++ b/src/palace/manager/api/admin/controller/discovery_service_library_registrations.py @@ -26,7 +26,6 @@ class DiscoveryServiceLibraryRegistrationsController(AdminPermissionsControllerMixin): - """List the libraries that have been registered with a specific OpdsRegistrationService, and allow the admin to register a library with a OpdsRegistrationService. diff --git a/src/palace/manager/api/admin/controller/integration_settings.py b/src/palace/manager/api/admin/controller/integration_settings.py index f345a5cfc0..0ed2b28c74 100644 --- a/src/palace/manager/api/admin/controller/integration_settings.py +++ b/src/palace/manager/api/admin/controller/integration_settings.py @@ -75,13 +75,13 @@ def _cached_protocols(self) -> dict[str, dict[str, Any]]: "settings": api.settings_class().configuration_form(self._db), } if issubclass(api, HasLibraryIntegrationConfiguration): - protocol[ - "library_settings" - ] = api.library_settings_class().configuration_form(self._db) + protocol["library_settings"] = ( + api.library_settings_class().configuration_form(self._db) + ) if issubclass(api, HasChildIntegrationConfiguration): - protocol[ - "child_settings" - ] = api.child_settings_class().configuration_form(self._db) + protocol["child_settings"] = ( + api.child_settings_class().configuration_form(self._db) + ) protocol.update(api.protocol_details(self._db)) protocols.append((name, protocol)) protocols.sort(key=lambda x: x[0]) diff --git a/src/palace/manager/api/admin/dashboard_stats.py b/src/palace/manager/api/admin/dashboard_stats.py index f841b2df8c..09af9d3a29 100644 --- a/src/palace/manager/api/admin/dashboard_stats.py +++ b/src/palace/manager/api/admin/dashboard_stats.py @@ -229,21 +229,25 @@ def _run_collections_stats_queries( return { c.id: _CollectionStatisticsQueryResults( - metered_title_counts=metered_title_counts[c.id] - if c.id in metered_title_counts - else {}, - unlimited_title_counts=unlimited_title_counts[c.id] - if c.id in unlimited_title_counts - else {}, - open_access_title_counts=open_access_title_counts[c.id] - if c.id in open_access_title_counts - else {}, - loanable_title_counts=loanable_title_counts[c.id] - if c.id in loanable_title_counts - else {}, - metered_license_stats=metered_license_stats[c.id] - if c.id in metered_license_stats - else {}, + metered_title_counts=( + metered_title_counts[c.id] if c.id in metered_title_counts else {} + ), + unlimited_title_counts=( + unlimited_title_counts[c.id] + if c.id in unlimited_title_counts + else {} + ), + open_access_title_counts=( + open_access_title_counts[c.id] + if c.id in open_access_title_counts + else {} + ), + loanable_title_counts=( + loanable_title_counts[c.id] if c.id in loanable_title_counts else {} + ), + metered_license_stats=( + metered_license_stats[c.id] if c.id in metered_license_stats else {} + ), ) for c in collections } @@ -364,12 +368,14 @@ def _gather_patron_stats( return { library.short_name: PatronStatistics( total=patron_count[library.id] if library.id in patron_count else 0, - with_active_loan=active_loans[library.id] - if library.id in active_loans - else 0, - with_active_loan_or_hold=active_loan_or_hold[library.id] - if library.id in active_loan_or_hold - else 0, + with_active_loan=( + active_loans[library.id] if library.id in active_loans else 0 + ), + with_active_loan_or_hold=( + active_loan_or_hold[library.id] + if library.id in active_loan_or_hold + else 0 + ), loans=loan_count[library.id] if library.id in loan_count else 0, holds=hold_count[library.id] if library.id in hold_count else 0, ) diff --git a/src/palace/manager/api/adobe_vendor_id.py b/src/palace/manager/api/adobe_vendor_id.py index bf32a94715..11175c0e39 100644 --- a/src/palace/manager/api/adobe_vendor_id.py +++ b/src/palace/manager/api/adobe_vendor_id.py @@ -36,7 +36,6 @@ class AuthdataUtility(LoggerMixin): - """Generate authdata JWTs as per the Vendor ID Service spec: https://docs.google.com/document/d/1j8nWPVmy95pJ_iU4UTC-QgHK2QhDUSdQ0OQTFR2NE_0 diff --git a/src/palace/manager/api/authentication/base.py b/src/palace/manager/api/authentication/base.py index 0e2c03c8e9..824abf8572 100644 --- a/src/palace/manager/api/authentication/base.py +++ b/src/palace/manager/api/authentication/base.py @@ -24,12 +24,10 @@ from palace.manager.util.problem_detail import ProblemDetail -class AuthProviderSettings(BaseSettings): - ... +class AuthProviderSettings(BaseSettings): ... -class AuthProviderLibrarySettings(BaseSettings): - ... +class AuthProviderLibrarySettings(BaseSettings): ... SettingsType = TypeVar("SettingsType", bound=AuthProviderSettings, covariant=True) diff --git a/src/palace/manager/api/authentication/basic.py b/src/palace/manager/api/authentication/basic.py index 76925bdf01..6cdcecc5ec 100644 --- a/src/palace/manager/api/authentication/basic.py +++ b/src/palace/manager/api/authentication/basic.py @@ -446,7 +446,7 @@ def testing_patron_or_bust(self, _db: Session) -> tuple[Patron, str | None]: ) raise IntegrationException(message, debug_message=debug_message) - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: """Verify the credentials of the test patron for this integration, and update its metadata. """ diff --git a/src/palace/manager/api/authentication/basic_token.py b/src/palace/manager/api/authentication/basic_token.py index 399709a6eb..5106bbb018 100644 --- a/src/palace/manager/api/authentication/basic_token.py +++ b/src/palace/manager/api/authentication/basic_token.py @@ -124,5 +124,5 @@ def identifies_individuals(cls): def label(cls) -> str: return "Library Barcode + Token" - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: raise NotImplementedError() diff --git a/src/palace/manager/api/authenticator.py b/src/palace/manager/api/authenticator.py index c384a52aa6..22d46e0113 100644 --- a/src/palace/manager/api/authenticator.py +++ b/src/palace/manager/api/authenticator.py @@ -71,9 +71,9 @@ def profile_document(self): adobe_drm = {} adobe_drm["drm:vendor"] = vendor_id adobe_drm["drm:clientToken"] = token - adobe_drm[ - "drm:scheme" - ] = "http://librarysimplified.org/terms/drm/scheme/ACS" + adobe_drm["drm:scheme"] = ( + "http://librarysimplified.org/terms/drm/scheme/ACS" + ) drm.append(adobe_drm) annotations_link = dict( @@ -143,9 +143,9 @@ def populate_authenticators( f"Library {library.name} ({library.id}) has no short name." ) continue - self.library_authenticators[ - library.short_name - ] = LibraryAuthenticator.from_config(_db, library, analytics) + self.library_authenticators[library.short_name] = ( + LibraryAuthenticator.from_config(_db, library, analytics) + ) def invoke_authenticator_method(self, method_name, *args, **kwargs): short_name = self.current_library_short_name @@ -197,11 +197,11 @@ def from_config( # Find all of this library's integrations with # the goal of authenticating patrons. - integrations: list[ - IntegrationLibraryConfiguration - ] = IntegrationLibraryConfiguration.for_library_and_goal( - _db, library, Goals.PATRON_AUTH_GOAL - ).all() + integrations: list[IntegrationLibraryConfiguration] = ( + IntegrationLibraryConfiguration.for_library_and_goal( + _db, library, Goals.PATRON_AUTH_GOAL + ).all() + ) # Turn each such integration into an AuthenticationProvider. for integration in integrations: @@ -227,8 +227,9 @@ def __init__( basic_auth_provider: BasicAuthenticationProvider | None = None, saml_providers: list[BaseSAMLAuthenticationProvider] | None = None, bearer_token_signing_secret: str | None = None, - integration_registry: None - | (IntegrationRegistry[AuthenticationProvider]) = None, + integration_registry: None | ( + IntegrationRegistry[AuthenticationProvider] + ) = None, ): """Initialize a LibraryAuthenticator from a list of AuthenticationProviders. @@ -269,9 +270,9 @@ def __init__( ] = {} self.basic_auth_provider: BasicAuthenticationProvider | None = None - self.access_token_authentication_provider: BasicTokenAuthenticationProvider | None = ( - None - ) + self.access_token_authentication_provider: ( + BasicTokenAuthenticationProvider | None + ) = None if basic_auth_provider: self.register_basic_auth_provider(basic_auth_provider) diff --git a/src/palace/manager/api/axis.py b/src/palace/manager/api/axis.py index 49d68367dc..8fe9873494 100644 --- a/src/palace/manager/api/axis.py +++ b/src/palace/manager/api/axis.py @@ -262,7 +262,7 @@ def authorization_headers(self) -> dict[str, str]: ) return dict(Authorization="Basic " + authorization_b64) - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: result = self.run_test("Refreshing bearer token", self.refresh_bearer_token) yield result if not result.success: @@ -648,7 +648,7 @@ def update_book( def _fetch_remote_availability( self, identifiers: list[Identifier] - ) -> Generator[tuple[Metadata, CirculationData], None, None]: + ) -> Generator[tuple[Metadata, CirculationData]]: """Retrieve availability information for the specified identifiers. :yield: A stream of (Metadata, CirculationData) 2-tuples. @@ -690,7 +690,7 @@ def _reap(self, identifier: Identifier) -> None: def recent_activity( self, since: datetime.datetime - ) -> Generator[tuple[Metadata, CirculationData], None, None]: + ) -> Generator[tuple[Metadata, CirculationData]]: """Find books that have had recent activity. :yield: A sequence of (Metadata, CirculationData) 2-tuples @@ -735,7 +735,6 @@ def _make_request( class Axis360CirculationMonitor(CollectionMonitor, TimelineMonitor): - """Maintain LicensePools for Axis 360 titles.""" SERVICE_NAME = "Axis 360 Circulation Monitor" @@ -1390,8 +1389,9 @@ def _raise_exception_on_error( cls, code: str | int, message: str, - custom_error_classes: None - | (Mapping[int | tuple[int, str], type[IntegrationException]]) = None, + custom_error_classes: None | ( + Mapping[int | tuple[int, str], type[IntegrationException]] + ) = None, ignore_error_codes: list[int] | None = None, ) -> tuple[int, str]: try: @@ -1435,8 +1435,9 @@ def raise_exception_on_error( self, e: _Element, ns: dict[str, str] | None, - custom_error_classes: None - | (Mapping[int | tuple[int, str], type[IntegrationException]]) = None, + custom_error_classes: None | ( + Mapping[int | tuple[int, str], type[IntegrationException]] + ) = None, ignore_error_codes: list[int] | None = None, ) -> tuple[int, str]: """Raise an error if the given lxml node represents an Axis 360 error diff --git a/src/palace/manager/api/bibliotheca.py b/src/palace/manager/api/bibliotheca.py index be8b1c2fab..1a9259739e 100644 --- a/src/palace/manager/api/bibliotheca.py +++ b/src/palace/manager/api/bibliotheca.py @@ -1024,7 +1024,6 @@ def process_one( class PatronCirculationParser(XMLParser): - """Parse Bibliotheca's patron circulation status document into a list of LoanInfo and HoldInfo objects. """ @@ -1117,7 +1116,6 @@ def process_one( class CheckoutResponseParser(DateResponseParser): - """Extract due date from a checkout response.""" @property @@ -1126,7 +1124,6 @@ def xpath_expression(self) -> str: class HoldResponseParser(DateResponseParser): - """Extract availability date from a hold response.""" @property @@ -1135,7 +1132,6 @@ def xpath_expression(self) -> str: class EventParser(BibliothecaParser): - """Parse Bibliotheca's event file format into our native event objects.""" EVENT_SOURCE = "Bibliotheca" @@ -1158,9 +1154,7 @@ def xpath_expression(self) -> str: def process_all( self, string: bytes | str, no_events_error=False - ) -> Generator[ - tuple[str, str, str | None, datetime, datetime | None, str], None, None - ]: + ) -> Generator[tuple[str, str, str | None, datetime, datetime | None, str]]: has_events = False for i in super().process_all(string): yield i @@ -1611,7 +1605,6 @@ def process_record(self, record, purchase_time): class BibliothecaEventMonitor(BibliothecaTimelineMonitor): - """Register CirculationEvents for Bibliotheca titles. When run, this monitor will look at recent events as a way of keeping @@ -1765,7 +1758,6 @@ def parse_command_line(cls, _db=None, cmd_args=None, *args, **kwargs): class BibliothecaBibliographicCoverageProvider(BibliographicCoverageProvider): - """Fill in bibliographic metadata for Bibliotheca records. This will occasionally fill in some availability information for a diff --git a/src/palace/manager/api/circulation_manager.py b/src/palace/manager/api/circulation_manager.py index d6d2d682b7..aabc6589f9 100644 --- a/src/palace/manager/api/circulation_manager.py +++ b/src/palace/manager/api/circulation_manager.py @@ -126,7 +126,9 @@ class CirculationManager(LoggerMixin): admin_dashboard_controller: DashboardController admin_patron_controller: PatronController admin_discovery_services_controller: DiscoveryServicesController - admin_discovery_service_library_registrations_controller: DiscoveryServiceLibraryRegistrationsController + admin_discovery_service_library_registrations_controller: ( + DiscoveryServiceLibraryRegistrationsController + ) admin_metadata_services_controller: MetadataServicesController admin_patron_auth_services_controller: PatronAuthServicesController admin_collection_settings_controller: CollectionSettingsController diff --git a/src/palace/manager/api/discovery/opds_registration.py b/src/palace/manager/api/discovery/opds_registration.py index 0b038adc2e..d5ff0032fe 100644 --- a/src/palace/manager/api/discovery/opds_registration.py +++ b/src/palace/manager/api/discovery/opds_registration.py @@ -105,15 +105,13 @@ def settings_class(cls) -> type[OpdsRegistrationServiceSettings]: @classmethod @overload - def for_integration(cls, _db: Session, integration: int) -> Self | None: - ... + def for_integration(cls, _db: Session, integration: int) -> Self | None: ... @classmethod @overload def for_integration( cls, _db: Session, integration: IntegrationConfiguration - ) -> Self: - ... + ) -> Self: ... @classmethod def for_integration( diff --git a/src/palace/manager/api/enki.py b/src/palace/manager/api/enki.py index bd04619e7a..fb13bc6c88 100644 --- a/src/palace/manager/api/enki.py +++ b/src/palace/manager/api/enki.py @@ -170,7 +170,7 @@ def enki_library_id(self, library: Library) -> str | None: return None return settings.enki_library_id - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: now = utc_now() def count_recent_loans_and_holds() -> str: @@ -290,7 +290,7 @@ def _minutes_since(cls, since: datetime.datetime) -> int: def recent_activity( self, start: datetime.datetime, end: datetime.datetime - ) -> Generator[CirculationData, None, None]: + ) -> Generator[CirculationData]: """Find circulation events from a certain timeframe that affected loans or holds. @@ -318,9 +318,7 @@ def recent_activity( if data: yield data - def updated_titles( - self, since: datetime.datetime - ) -> Generator[Metadata, None, None]: + def updated_titles(self, since: datetime.datetime) -> Generator[Metadata]: """Find recent changes to book metadata. NOTE: getUpdateTitles will return a maximum of 1000 items, so @@ -372,9 +370,7 @@ def get_item(self, enki_id: str | None) -> Metadata | None: return BibliographicParser().extract_bibliographic(book) return None - def get_all_titles( - self, strt: int = 0, qty: int = 10 - ) -> Generator[Metadata, None, None]: + def get_all_titles(self, strt: int = 0, qty: int = 10) -> Generator[Metadata]: """Retrieve a single page of items from the Enki collection. Iterating over the entire collection is very expensive and @@ -531,7 +527,7 @@ def parse_fulfill_result( def patron_activity( self, patron: Patron, pin: str | None - ) -> Generator[LoanInfo | HoldInfo, None, None]: + ) -> Generator[LoanInfo | HoldInfo]: enki_library_id = self.enki_library_id(patron.library) response = self.patron_request( patron.authorization_identifier, pin, enki_library_id @@ -627,7 +623,7 @@ class BibliographicParser(LoggerMixin): def process_all( self, json_data: bytes | str | Mapping[str, Any] - ) -> Generator[Metadata, None, None]: + ) -> Generator[Metadata]: data = ( json.loads(json_data) if isinstance(json_data, (bytes, str)) else json_data ) diff --git a/src/palace/manager/api/lanes.py b/src/palace/manager/api/lanes.py index 6b2c37f30b..f532d4dbea 100644 --- a/src/palace/manager/api/lanes.py +++ b/src/palace/manager/api/lanes.py @@ -185,20 +185,20 @@ def lane_from_genres( # Now that we have sublanes we don't care about subgenres anymore. genres = [ - genre.get("name") - if isinstance(genre, dict) - else genre.name - if isinstance(genre, GenreData) - else genre + ( + genre.get("name") + if isinstance(genre, dict) + else genre.name if isinstance(genre, GenreData) else genre + ) for genre in genres ] exclude_genres = [ - genre.get("name") - if isinstance(genre, dict) - else genre.name - if isinstance(genre, GenreData) - else genre + ( + genre.get("name") + if isinstance(genre, dict) + else genre.name if isinstance(genre, GenreData) else genre + ) for genre in exclude_genres or [] ] diff --git a/src/palace/manager/api/lcp/hash.py b/src/palace/manager/api/lcp/hash.py index b7fe7e75f1..3d90a546cd 100644 --- a/src/palace/manager/api/lcp/hash.py +++ b/src/palace/manager/api/lcp/hash.py @@ -25,8 +25,7 @@ def __init__(self, hashing_algorithm: HashingAlgorithm) -> None: self._hashing_algorithm = hashing_algorithm @abstractmethod - def hash(self, value: str) -> str: - ... + def hash(self, value: str) -> str: ... class UniversalHasher(Hasher): diff --git a/src/palace/manager/api/metadata/base.py b/src/palace/manager/api/metadata/base.py index 0e39cb5f0a..fb8544ef5e 100644 --- a/src/palace/manager/api/metadata/base.py +++ b/src/palace/manager/api/metadata/base.py @@ -11,8 +11,7 @@ from palace.manager.integration.settings import BaseSettings -class MetadataServiceSettings(BaseSettings): - ... +class MetadataServiceSettings(BaseSettings): ... SettingsType = TypeVar("SettingsType", bound=MetadataServiceSettings, covariant=True) @@ -45,8 +44,7 @@ def protocols(cls) -> list[str]: @classmethod @abstractmethod - def multiple_services_allowed(cls) -> bool: - ... + def multiple_services_allowed(cls) -> bool: ... MetadataServiceType = MetadataService[MetadataServiceSettings] diff --git a/src/palace/manager/api/metadata/novelist.py b/src/palace/manager/api/metadata/novelist.py index cb9d2cbbff..5fe38d0eff 100644 --- a/src/palace/manager/api/metadata/novelist.py +++ b/src/palace/manager/api/metadata/novelist.py @@ -72,8 +72,7 @@ class NoveListApiSettings(MetadataServiceSettings): ) -class NoveListApiLibrarySettings(BaseSettings): - ... +class NoveListApiLibrarySettings(BaseSettings): ... class NoveListAPI( @@ -635,9 +634,9 @@ def get_items_from_query(self, library: Library) -> list[dict[str, str]]: def create_item_object( self, - object: Row - | tuple[str, str, str, str, str, datetime.date, str, str, str] - | None, + object: ( + Row | tuple[str, str, str, str, str, datetime.date, str, str, str] | None + ), currentIdentifier: str | None, existingItem: dict[str, str] | None, ) -> tuple[str | None, dict[str, str] | None, dict[str, str] | None, bool]: diff --git a/src/palace/manager/api/metadata/nyt.py b/src/palace/manager/api/metadata/nyt.py index 7c5a77fdab..98a742fb57 100644 --- a/src/palace/manager/api/metadata/nyt.py +++ b/src/palace/manager/api/metadata/nyt.py @@ -138,7 +138,7 @@ def do_get( def multiple_services_allowed(cls) -> bool: return False - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: yield self.run_test("Getting list of best-seller lists", self.list_of_lists) def request(self, path: str, max_age: timedelta = LIST_MAX_AGE) -> dict[str, Any]: @@ -251,7 +251,7 @@ def medium(self) -> str | None: return Edition.BOOK_MEDIUM @property - def all_dates(self) -> Generator[datetime, None, None]: + def all_dates(self) -> Generator[datetime]: """Yield a list of estimated dates when new editions of this list were probably published. """ diff --git a/src/palace/manager/api/millenium_patron.py b/src/palace/manager/api/millenium_patron.py index befdeb68d5..126391630f 100644 --- a/src/palace/manager/api/millenium_patron.py +++ b/src/palace/manager/api/millenium_patron.py @@ -601,7 +601,6 @@ def extract_postal_code(cls, address): class MockMilleniumPatronAPI(MilleniumPatronAPI): - """This mocks the API on a higher level than the HTTP level. It is not used in the tests of the MilleniumPatronAPI class. It diff --git a/src/palace/manager/api/odl/auth.py b/src/palace/manager/api/odl/auth.py index e4c3ff7666..e5ffbd8e0e 100644 --- a/src/palace/manager/api/odl/auth.py +++ b/src/palace/manager/api/odl/auth.py @@ -63,23 +63,19 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: @property @abstractmethod - def _username(self) -> str: - ... + def _username(self) -> str: ... @property @abstractmethod - def _password(self) -> str: - ... + def _password(self) -> str: ... @property @abstractmethod - def _auth_type(self) -> OPDS2AuthType: - ... + def _auth_type(self) -> OPDS2AuthType: ... @property @abstractmethod - def _feed_url(self) -> str: - ... + def _feed_url(self) -> str: ... @staticmethod def _no_auth_get( diff --git a/src/palace/manager/api/odl/importer.py b/src/palace/manager/api/odl/importer.py index a391998604..014966771b 100644 --- a/src/palace/manager/api/odl/importer.py +++ b/src/palace/manager/api/odl/importer.py @@ -119,11 +119,13 @@ def create_format_data(format: FormatData) -> FormatData: ) new_formats = [ - create_format_data(format) - if format.content_type in supported_media_types - and format.drm_scheme is None - and format.link.rel == Hyperlink.GENERIC_OPDS_ACQUISITION - else format + ( + create_format_data(format) + if format.content_type in supported_media_types + and format.drm_scheme is None + and format.link.rel == Hyperlink.GENERIC_OPDS_ACQUISITION + else format + ) for format in circulation.formats ] diff --git a/src/palace/manager/api/opds_for_distributors.py b/src/palace/manager/api/opds_for_distributors.py index 30505c3638..7216529829 100644 --- a/src/palace/manager/api/opds_for_distributors.py +++ b/src/palace/manager/api/opds_for_distributors.py @@ -123,7 +123,7 @@ def __init__(self, _db: Session, collection: Collection): self.feed_url = settings.external_account_id self.auth_url: str | None = None - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: """Try to get a token.""" yield self.run_test("Negotiate a fulfillment token", self._get_token, _db) diff --git a/src/palace/manager/api/routes.py b/src/palace/manager/api/routes.py index 7429e05562..d802d6cc56 100644 --- a/src/palace/manager/api/routes.py +++ b/src/palace/manager/api/routes.py @@ -588,9 +588,9 @@ def application_version(): @app.route("/heartbeat") def heartbeat(): version_info = application_version() - version_info[ - "WARNING" - ] = "The /heartbeat endpoint is deprecated. Please use /version.json instead." + version_info["WARNING"] = ( + "The /heartbeat endpoint is deprecated. Please use /version.json instead." + ) return version_info diff --git a/src/palace/manager/api/s3_analytics_provider.py b/src/palace/manager/api/s3_analytics_provider.py index f1beed7cbb..557e2f3965 100644 --- a/src/palace/manager/api/s3_analytics_provider.py +++ b/src/palace/manager/api/s3_analytics_provider.py @@ -86,11 +86,13 @@ def _create_event_object( "publisher": edition.publisher if edition else None, "imprint": edition.imprint if edition else None, "issued": edition.issued if edition else None, - "published": datetime.datetime.combine( - edition.published, datetime.datetime.min.time() - ) - if edition and edition.published - else None, + "published": ( + datetime.datetime.combine( + edition.published, datetime.datetime.min.time() + ) + if edition and edition.published + else None + ), "medium": edition.medium if edition else None, "collection": collection.name if collection else None, "identifier_type": identifier.type if identifier else None, @@ -103,22 +105,22 @@ def _create_event_object( "quality": work.quality if work else None, "rating": work.rating if work else None, "popularity": work.popularity if work else None, - "genre": ", ".join(map(lambda genre: genre.name, work.genres)) - if work - else None, - "availability_time": license_pool.availability_time - if license_pool - else None, + "genre": ( + ", ".join(map(lambda genre: genre.name, work.genres)) if work else None + ), + "availability_time": ( + license_pool.availability_time if license_pool else None + ), "licenses_owned": license_pool.licenses_owned if license_pool else None, - "licenses_available": license_pool.licenses_available - if license_pool - else None, - "licenses_reserved": license_pool.licenses_reserved - if license_pool - else None, - "patrons_in_hold_queue": license_pool.patrons_in_hold_queue - if license_pool - else None, + "licenses_available": ( + license_pool.licenses_available if license_pool else None + ), + "licenses_reserved": ( + license_pool.licenses_reserved if license_pool else None + ), + "patrons_in_hold_queue": ( + license_pool.patrons_in_hold_queue if license_pool else None + ), # TODO: We no longer support self-hosted books, so this should always be False. # this value is still included in the response for backwards compatibility, # but should be removed in a future release. diff --git a/src/palace/manager/api/saml/configuration/model.py b/src/palace/manager/api/saml/configuration/model.py index 7f92d06c82..dc008766c1 100644 --- a/src/palace/manager/api/saml/configuration/model.py +++ b/src/palace/manager/api/saml/configuration/model.py @@ -371,8 +371,7 @@ def validate_patron_id_regular_expression(cls, v: Pattern): return v -class SAMLWebSSOAuthLibrarySettings(AuthProviderLibrarySettings): - ... +class SAMLWebSSOAuthLibrarySettings(AuthProviderLibrarySettings): ... class SAMLOneLoginConfiguration: @@ -408,9 +407,9 @@ def __init__(self, configuration: SAMLWebSSOAuthSettings): self._configuration = configuration self._service_provider_loaded: SAMLServiceProviderMetadata | None = None self._service_provider_settings: dict[str, Any] | None = None - self._identity_providers_loaded: None | ( - list[SAMLIdentityProviderMetadata] - ) = None + self._identity_providers_loaded: None | (list[SAMLIdentityProviderMetadata]) = ( + None + ) self._identity_providers_settings: dict[str, dict[str, Any]] = {} self._metadata_parser = SAMLMetadataParser() @@ -552,9 +551,9 @@ def _get_identity_provider_settings( and identity_provider.signing_certificates[0] == identity_provider.encryption_certificates[0] ): - onelogin_identity_provider[self.IDP][ - self.X509_CERT - ] = identity_provider.signing_certificates[0] + onelogin_identity_provider[self.IDP][self.X509_CERT] = ( + identity_provider.signing_certificates[0] + ) else: if len(identity_provider.signing_certificates) > 0: if self.X509_CERT_MULTI not in onelogin_identity_provider[self.IDP]: @@ -590,12 +589,12 @@ def _get_service_provider_settings( self.BINDING: service_provider.acs_service.binding.value, }, self.NAME_ID_FORMAT: service_provider.name_id_format, - self.X509_CERT: service_provider.certificate - if service_provider.certificate - else "", - self.PRIVATE_KEY: service_provider.private_key - if service_provider.private_key - else "", + self.X509_CERT: ( + service_provider.certificate if service_provider.certificate else "" + ), + self.PRIVATE_KEY: ( + service_provider.private_key if service_provider.private_key else "" + ), }, self.SECURITY: { self.AUTHN_REQUESTS_SIGNED: service_provider.authn_requests_signed diff --git a/src/palace/manager/api/saml/metadata/parser.py b/src/palace/manager/api/saml/metadata/parser.py index 2b96b87659..7f74950a0d 100644 --- a/src/palace/manager/api/saml/metadata/parser.py +++ b/src/palace/manager/api/saml/metadata/parser.py @@ -78,15 +78,15 @@ def __init__(self, skip_incorrect_providers=False): # Add missing namespaces to be able to parse mdui:UIInfoType OneLogin_Saml2_Constants.NS_PREFIX_MDUI = "mdui" OneLogin_Saml2_Constants.NS_MDUI = "urn:oasis:names:tc:SAML:metadata:ui" - OneLogin_Saml2_Constants.NSMAP[ - OneLogin_Saml2_Constants.NS_PREFIX_MDUI - ] = OneLogin_Saml2_Constants.NS_MDUI + OneLogin_Saml2_Constants.NSMAP[OneLogin_Saml2_Constants.NS_PREFIX_MDUI] = ( + OneLogin_Saml2_Constants.NS_MDUI + ) OneLogin_Saml2_Constants.NS_PREFIX_ALG = "alg" OneLogin_Saml2_Constants.NS_ALG = "urn:oasis:names:tc:SAML:metadata:algsupport" - OneLogin_Saml2_Constants.NSMAP[ - OneLogin_Saml2_Constants.NS_PREFIX_ALG - ] = OneLogin_Saml2_Constants.NS_ALG + OneLogin_Saml2_Constants.NSMAP[OneLogin_Saml2_Constants.NS_PREFIX_ALG] = ( + OneLogin_Saml2_Constants.NS_ALG + ) def _convert_xml_string_to_dom( self, xml_metadata: str | bytes diff --git a/src/palace/manager/api/saml/python_expression_dsl/evaluator.py b/src/palace/manager/api/saml/python_expression_dsl/evaluator.py index d2fd306060..c4c1a56795 100644 --- a/src/palace/manager/api/saml/python_expression_dsl/evaluator.py +++ b/src/palace/manager/api/saml/python_expression_dsl/evaluator.py @@ -234,9 +234,11 @@ def visit(self, node: Identifier): value = self.BUILTIN_FUNCTIONS[node.value] else: value = self._get_attribute_value( - self._current_scope - if self._current_scope is not None - else self._context, + ( + self._current_scope + if self._current_scope is not None + else self._context + ), node.value, ) diff --git a/src/palace/manager/api/selftest.py b/src/palace/manager/api/selftest.py index eb13c83122..be9f6a2104 100644 --- a/src/palace/manager/api/selftest.py +++ b/src/palace/manager/api/selftest.py @@ -127,8 +127,7 @@ class HasCollectionSelfTests(HasPatronSelfTests, ABC): @property @abstractmethod - def collection(self) -> Collection | None: - ... + def collection(self) -> Collection | None: ... def integration(self, _db: Session) -> IntegrationConfiguration | None: if not self.collection: @@ -156,7 +155,7 @@ def _no_delivery_mechanisms_test(self): else: return "All titles in this collection have delivery mechanisms." - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: yield self.run_test( "Checking for titles that have no delivery mechanisms.", self._no_delivery_mechanisms_test, diff --git a/src/palace/manager/api/sirsidynix_authentication_provider.py b/src/palace/manager/api/sirsidynix_authentication_provider.py index bab92449e0..daedf802d1 100644 --- a/src/palace/manager/api/sirsidynix_authentication_provider.py +++ b/src/palace/manager/api/sirsidynix_authentication_provider.py @@ -364,7 +364,7 @@ def api_patron_status_info( return False return response.json() - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: """Verify the credentials of the test patron for this integration, and update its metadata. """ diff --git a/src/palace/manager/api/web_publication_manifest.py b/src/palace/manager/api/web_publication_manifest.py index ec0b8d6819..eaeb612215 100644 --- a/src/palace/manager/api/web_publication_manifest.py +++ b/src/palace/manager/api/web_publication_manifest.py @@ -1,5 +1,6 @@ """Vendor-specific variants of the standard Web Publication Manifest classes. """ + from palace.manager.sqlalchemy.model.licensing import DeliveryMechanism from palace.manager.sqlalchemy.model.resource import Representation from palace.manager.util.web_publication_manifest import AudiobookManifest diff --git a/src/palace/manager/celery/session.py b/src/palace/manager/celery/session.py index 4a991f21ae..cec5362b5b 100644 --- a/src/palace/manager/celery/session.py +++ b/src/palace/manager/celery/session.py @@ -17,7 +17,7 @@ def session_maker(self) -> sessionmaker[Session]: """ @contextmanager - def session(self) -> Generator[Session, None, None]: + def session(self) -> Generator[Session]: """ Starts a session and yields it to the caller. The session is closed when the context manager exits. @@ -28,7 +28,7 @@ def session(self) -> Generator[Session, None, None]: yield session @contextmanager - def transaction(self) -> Generator[Session, None, None]: + def transaction(self) -> Generator[Session]: """ Start a new transaction and yield a session to the caller. The transaction will be committed when the context manager exits. If an exception is raised, the transaction diff --git a/src/palace/manager/celery/tasks/search.py b/src/palace/manager/celery/tasks/search.py index 3df912173e..600e6f6cf9 100644 --- a/src/palace/manager/celery/tasks/search.py +++ b/src/palace/manager/celery/tasks/search.py @@ -57,8 +57,7 @@ def add_documents_to_index( raise task.retry(countdown=wait_time) -class FailedToIndex(BasePalaceException): - ... +class FailedToIndex(BasePalaceException): ... @shared_task(queue=QueueNames.default, bind=True, max_retries=4) diff --git a/src/palace/manager/core/app_server.py b/src/palace/manager/core/app_server.py index 630b697440..096bb49fa6 100644 --- a/src/palace/manager/core/app_server.py +++ b/src/palace/manager/core/app_server.py @@ -1,4 +1,5 @@ """Implement logic common to more than one of the Simplified applications.""" + from __future__ import annotations import gzip diff --git a/src/palace/manager/core/classifier/keyword.py b/src/palace/manager/core/classifier/keyword.py index 56c20ccd5e..89a6d60fea 100644 --- a/src/palace/manager/core/classifier/keyword.py +++ b/src/palace/manager/core/classifier/keyword.py @@ -41,7 +41,6 @@ def __str__(self): class KeywordBasedClassifier(AgeOrGradeClassifier): - """Classify a book based on keywords.""" # We have to handle these first because otherwise '\bfiction\b' diff --git a/src/palace/manager/core/classifier/simplified.py b/src/palace/manager/core/classifier/simplified.py index b3fb77818a..c0583b2041 100644 --- a/src/palace/manager/core/classifier/simplified.py +++ b/src/palace/manager/core/classifier/simplified.py @@ -67,6 +67,6 @@ def is_fiction(cls, identifier, name): Classifier.classifiers[Classifier.SIMPLIFIED_GENRE] = SimplifiedGenreClassifier -Classifier.classifiers[ - Classifier.SIMPLIFIED_FICTION_STATUS -] = SimplifiedFictionClassifier +Classifier.classifiers[Classifier.SIMPLIFIED_FICTION_STATUS] = ( + SimplifiedFictionClassifier +) diff --git a/src/palace/manager/core/coverage.py b/src/palace/manager/core/coverage.py index 53cf0e5ad8..31239ce913 100644 --- a/src/palace/manager/core/coverage.py +++ b/src/palace/manager/core/coverage.py @@ -92,7 +92,6 @@ def to_equivalency_coverage_record( class CoverageProviderProgress(TimestampData): - """A TimestampData optimized for the special needs of CoverageProviders. """ @@ -130,7 +129,6 @@ def achievements(self, value): class BaseCoverageProvider: - """Run certain objects through an algorithm. If the algorithm returns success, add a coverage record for that object, so the object doesn't need to be processed again. If the algorithm returns a @@ -597,7 +595,6 @@ def process_item(self, item): class IdentifierCoverageProvider(BaseCoverageProvider): - """Run Identifiers of certain types (ISBN, Overdrive, OCLC Number, etc.) through an algorithm associated with a certain DataSource. @@ -1393,7 +1390,6 @@ def handle_success(self, identifier): class WorkCoverageProvider(BaseCoverageProvider): - """Perform coverage operations on Works rather than Identifiers.""" @classmethod diff --git a/src/palace/manager/core/entrypoint.py b/src/palace/manager/core/entrypoint.py index bddf008997..df88280187 100644 --- a/src/palace/manager/core/entrypoint.py +++ b/src/palace/manager/core/entrypoint.py @@ -2,7 +2,6 @@ class EntryPoint: - """A EntryPoint is a top-level entry point into a library's Lane structure that may apply additional filters to the Lane structure. diff --git a/src/palace/manager/core/exceptions.py b/src/palace/manager/core/exceptions.py index 834ee166c1..03434fcd59 100644 --- a/src/palace/manager/core/exceptions.py +++ b/src/palace/manager/core/exceptions.py @@ -10,8 +10,7 @@ def __init__(self, message: str | None = None): self.message = message -class PalaceValueError(BasePalaceException, ValueError): - ... +class PalaceValueError(BasePalaceException, ValueError): ... class IntegrationException(BasePalaceException): diff --git a/src/palace/manager/core/external_list.py b/src/palace/manager/core/external_list.py index e3f3650c01..d345c85f07 100644 --- a/src/palace/manager/core/external_list.py +++ b/src/palace/manager/core/external_list.py @@ -14,7 +14,6 @@ class TitleFromExternalList: - """This class helps you convert data from external lists into Simplified Edition and CustomListEntry objects. """ diff --git a/src/palace/manager/core/metadata_layer.py b/src/palace/manager/core/metadata_layer.py index a334bd37f4..c9b9ca7dba 100644 --- a/src/palace/manager/core/metadata_layer.py +++ b/src/palace/manager/core/metadata_layer.py @@ -6,6 +6,7 @@ model. Doing a third-party integration should be as simple as putting the information into this format. """ + import csv import datetime import logging @@ -1079,7 +1080,6 @@ def _availability_needs_update(self, pool): class Metadata: - """A (potentially partial) set of metadata for a published work.""" log = logging.getLogger("Abstract metadata layer") @@ -1876,7 +1876,6 @@ class CSVFormatError(csv.Error): class CSVMetadataImporter: - """Turn a CSV file into a list of Metadata objects.""" log = logging.getLogger("CSV metadata importer") diff --git a/src/palace/manager/core/monitor.py b/src/palace/manager/core/monitor.py index 6236858a57..3c4c1278dd 100644 --- a/src/palace/manager/core/monitor.py +++ b/src/palace/manager/core/monitor.py @@ -804,7 +804,6 @@ def __init__(self, failed_providers): class CustomListEntryWorkUpdateMonitor(CustomListEntrySweepMonitor): - """Set or reset the Work associated with each custom list entry.""" SERVICE_NAME = "Update Works for custom list entries" diff --git a/src/palace/manager/core/opds_import.py b/src/palace/manager/core/opds_import.py index e3677411ed..c11a0480fd 100644 --- a/src/palace/manager/core/opds_import.py +++ b/src/palace/manager/core/opds_import.py @@ -392,32 +392,26 @@ def __init__( @classmethod @abstractmethod - def settings_class(cls) -> type[SettingsType]: - ... + def settings_class(cls) -> type[SettingsType]: ... @abstractmethod def extract_feed_data( self, feed: str | bytes, feed_url: str | None = None - ) -> tuple[dict[str, Metadata], dict[str, list[CoverageFailure]]]: - ... + ) -> tuple[dict[str, Metadata], dict[str, list[CoverageFailure]]]: ... @abstractmethod def extract_last_update_dates( self, feed: str | bytes | FeedParserDict - ) -> list[tuple[str | None, datetime | None]]: - ... + ) -> list[tuple[str | None, datetime | None]]: ... @abstractmethod - def extract_next_links(self, feed: str | bytes) -> list[str]: - ... + def extract_next_links(self, feed: str | bytes) -> list[str]: ... @overload - def parse_identifier(self, identifier: str) -> Identifier: - ... + def parse_identifier(self, identifier: str) -> Identifier: ... @overload - def parse_identifier(self, identifier: str | None) -> Identifier | None: - ... + def parse_identifier(self, identifier: str | None) -> Identifier | None: ... def parse_identifier(self, identifier: str | None) -> Identifier | None: """Parse the identifier and return an Identifier object representing it. @@ -538,9 +532,7 @@ def update_work_for_edition( # background, and that's good enough. return pool, work - def import_from_feed( - self, feed: str | bytes, feed_url: str | None = None - ) -> tuple[ + def import_from_feed(self, feed: str | bytes, feed_url: str | None = None) -> tuple[ list[Edition], list[LicensePool], list[Work], @@ -839,14 +831,12 @@ def extract_feed_data( @overload def handle_failure( self, urn: str, failure: Identifier - ) -> tuple[Identifier, Identifier]: - ... + ) -> tuple[Identifier, Identifier]: ... @overload def handle_failure( self, urn: str, failure: CoverageFailure - ) -> tuple[Identifier, CoverageFailure]: - ... + ) -> tuple[Identifier, CoverageFailure]: ... def handle_failure( self, urn: str, failure: Identifier | CoverageFailure @@ -1184,7 +1174,7 @@ def rights_uri_from_entry_tag(cls, entry: Element) -> str | None: @classmethod def extract_messages( cls, parser: OPDSXMLParser, feed_tag: str - ) -> Generator[OPDSMessage, None, None]: + ) -> Generator[OPDSMessage]: """Extract tags from an OPDS feed and convert them into OPDSMessage objects. """ @@ -1220,7 +1210,7 @@ def extract_messages( @classmethod def coveragefailures_from_messages( cls, data_source: DataSource, parser: OPDSXMLParser, feed_tag: str - ) -> Generator[CoverageFailure, None, None]: + ) -> Generator[CoverageFailure]: """Extract CoverageFailure objects from a parsed OPDS document. This allows us to determine the fate of books which could not become tags. diff --git a/src/palace/manager/core/selftest.py b/src/palace/manager/core/selftest.py index 5e152c861c..69ce87f266 100644 --- a/src/palace/manager/core/selftest.py +++ b/src/palace/manager/core/selftest.py @@ -1,5 +1,6 @@ """Define the interfaces used by integration self-tests. """ + from __future__ import annotations import sys @@ -299,7 +300,7 @@ def load_self_test_results( return integration.self_test_results @abstractmethod - def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None]: + def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult]: """Run the self-tests. :return: A generator that yields SelfTestResult objects. @@ -307,5 +308,4 @@ def _run_self_tests(self, _db: Session) -> Generator[SelfTestResult, None, None] ... @abstractmethod - def integration(self, _db: Session) -> IntegrationConfiguration | None: - ... + def integration(self, _db: Session) -> IntegrationConfiguration | None: ... diff --git a/src/palace/manager/customlists/importer.py b/src/palace/manager/customlists/importer.py index cb3f101d19..9090e0f418 100644 --- a/src/palace/manager/customlists/importer.py +++ b/src/palace/manager/customlists/importer.py @@ -115,7 +115,9 @@ def _process_check_book( ) """Check that the book on the target CM has a matching ID and title.""" - server_work_endpoint: str = f"{self._server_base}/{self._library_name}/admin/works/{book.id_type()}/{book.id_value()}" + server_work_endpoint: str = ( + f"{self._server_base}/{self._library_name}/admin/works/{book.id_type()}/{book.id_value()}" + ) response = self._session.get(server_work_endpoint) if response.status_code == 404: problem_missing = CustomListProblemBookMissing.create( diff --git a/src/palace/manager/feed/acquisition.py b/src/palace/manager/feed/acquisition.py index 9450d201cb..fdef9abaa4 100644 --- a/src/palace/manager/feed/acquisition.py +++ b/src/palace/manager/feed/acquisition.py @@ -1,4 +1,5 @@ """OPDS feeds, they can be serialized to either OPDS 1 or OPDS 2""" + from __future__ import annotations import logging @@ -136,7 +137,7 @@ def make_link(ep: type[EntryPoint]) -> str: @classmethod def facet_links( cls, annotator: CirculationManagerAnnotator, facets: FacetsWithEntryPoint - ) -> Generator[Link, None, None]: + ) -> Generator[Link]: """Create links for this feed's navigational facet groups. This does not create links for the entry point facet group, @@ -499,9 +500,9 @@ def active_loans_for( active_holds_by_work: dict[Work, Hold] = {} for work, list_of_holds in all_holds_by_work.items(): - active_holds_by_work[ - work - ] = LibraryLoanAndHoldAnnotator.choose_best_hold_for_work(list_of_holds) + active_holds_by_work[work] = ( + LibraryLoanAndHoldAnnotator.choose_best_hold_for_work(list_of_holds) + ) if not annotator: annotator = LibraryLoanAndHoldAnnotator( diff --git a/src/palace/manager/feed/annotator/circulation.py b/src/palace/manager/feed/annotator/circulation.py index d5963d2d3f..dd4dbcf645 100644 --- a/src/palace/manager/feed/annotator/circulation.py +++ b/src/palace/manager/feed/annotator/circulation.py @@ -413,8 +413,9 @@ def acquisition_links( can_hold: bool = True, can_revoke_hold: bool = True, set_mechanism_at_borrow: bool = False, - direct_fulfillment_delivery_mechanisms: None - | (list[LicensePoolDeliveryMechanism]) = None, + direct_fulfillment_delivery_mechanisms: None | ( + list[LicensePoolDeliveryMechanism] + ) = None, add_open_access_links: bool = True, ) -> list[Acquisition]: """Generate a number of tags that enumerate all acquisition @@ -1248,8 +1249,9 @@ def acquisition_links( # type: ignore [override] active_hold: Hold | None, active_fulfillment: Any | None, identifier: Identifier, - direct_fulfillment_delivery_mechanisms: None - | (list[LicensePoolDeliveryMechanism]) = None, + direct_fulfillment_delivery_mechanisms: None | ( + list[LicensePoolDeliveryMechanism] + ) = None, mock_api: Any | None = None, ) -> list[Acquisition]: """Generate one or more tags that can be used to borrow, @@ -1569,9 +1571,9 @@ def add_patron(self, feed: FeedData) -> None: if self.patron.username: patron_details["username"] = self.patron.username if self.patron.authorization_identifier: - patron_details[ - "authorizationIdentifier" - ] = self.patron.authorization_identifier + patron_details["authorizationIdentifier"] = ( + self.patron.authorization_identifier + ) patron_tag = FeedEntryType.create(**patron_details) feed.metadata.patron = patron_tag diff --git a/src/palace/manager/feed/base.py b/src/palace/manager/feed/base.py index d731e49244..7877719af8 100644 --- a/src/palace/manager/feed/base.py +++ b/src/palace/manager/feed/base.py @@ -5,9 +5,7 @@ class FeedInterface(ABC): @abstractmethod - def generate_feed(self) -> None: - ... + def generate_feed(self) -> None: ... @abstractmethod - def as_response(self) -> Response: - ... + def as_response(self) -> Response: ... diff --git a/src/palace/manager/feed/serializer/base.py b/src/palace/manager/feed/serializer/base.py index 836be63a1e..e120645cdb 100644 --- a/src/palace/manager/feed/serializer/base.py +++ b/src/palace/manager/feed/serializer/base.py @@ -10,23 +10,18 @@ class SerializerInterface(ABC, Generic[T]): @classmethod @abstractmethod - def to_string(cls, data: T) -> str: - ... + def to_string(cls, data: T) -> str: ... @abstractmethod def serialize_feed( self, feed: FeedData, precomposed_entries: list[OPDSMessage] | None = None - ) -> str: - ... + ) -> str: ... @abstractmethod - def serialize_work_entry(self, entry: WorkEntryData) -> T: - ... + def serialize_work_entry(self, entry: WorkEntryData) -> T: ... @abstractmethod - def serialize_opds_message(self, message: OPDSMessage) -> T: - ... + def serialize_opds_message(self, message: OPDSMessage) -> T: ... @abstractmethod - def content_type(self) -> str: - ... + def content_type(self) -> str: ... diff --git a/src/palace/manager/feed/types.py b/src/palace/manager/feed/types.py index eed9683954..e50a72d903 100644 --- a/src/palace/manager/feed/types.py +++ b/src/palace/manager/feed/types.py @@ -18,7 +18,7 @@ @dataclass class BaseModel: - def _vars(self) -> Generator[tuple[str, Any], None, None]: + def _vars(self) -> Generator[tuple[str, Any]]: """Yield attributes as a tuple""" _attrs = vars(self) for name, value in _attrs.items(): @@ -38,7 +38,7 @@ def asdict(self) -> dict[str, Any]: attrs[name] = value return attrs - def __iter__(self) -> Generator[tuple[str, Any], None, None]: + def __iter__(self) -> Generator[tuple[str, Any]]: """Allow attribute iteration""" yield from self._vars() @@ -68,7 +68,7 @@ def add_attributes(self, attrs: dict[str, Any]) -> None: for name, data in attrs.items(): setattr(self, name, data) - def children(self) -> Generator[tuple[str, FeedEntryType], None, None]: + def children(self) -> Generator[tuple[str, FeedEntryType]]: """Yield all FeedEntryType attributes""" for name, value in self: if isinstance(value, self.__class__): diff --git a/src/palace/manager/integration/settings.py b/src/palace/manager/integration/settings.py index a828fb2a33..3c74557844 100644 --- a/src/palace/manager/integration/settings.py +++ b/src/palace/manager/integration/settings.py @@ -75,8 +75,9 @@ def FormField( validation_alias: str | AliasPath | AliasChoices | None = _Unset, serialization_alias: str | None = _Unset, title: str | None = _Unset, - field_title_generator: typing_extensions.Callable[[str, FieldInfo], str] - | None = _Unset, + field_title_generator: ( + typing_extensions.Callable[[str, FieldInfo], str] | None + ) = _Unset, description: str | None = _Unset, examples: list[Any] | None = _Unset, exclude: bool | None = _Unset, @@ -216,9 +217,11 @@ class ConfigurationFormItem: # When the type is SELECT, LIST, or MENU, the options are used to populate the # field in the admin interface. This can either be a callable that returns a # dictionary of options or a dictionary of options. - options: Callable[ - [Session], ConfigurationFormOptionsType - ] | ConfigurationFormOptionsType | None = None + options: ( + Callable[[Session], ConfigurationFormOptionsType] + | ConfigurationFormOptionsType + | None + ) = None # Required is usually determined by the Pydantic model, but can be overridden # here, in the case where a field would not be required in the model, but is diff --git a/src/palace/manager/marc/exporter.py b/src/palace/manager/marc/exporter.py index 84c4c0b883..5b2ead5e82 100644 --- a/src/palace/manager/marc/exporter.py +++ b/src/palace/manager/marc/exporter.py @@ -373,7 +373,7 @@ def create_marc_upload_records( @staticmethod def files_for_cleanup( session: Session, registry: CatalogServicesRegistry - ) -> Generator[MarcFile, None, None]: + ) -> Generator[MarcFile]: # Files for collections or libraries that have had exports disabled. existing = { (row.collection_id, row.library_id) diff --git a/src/palace/manager/scripts/informational.py b/src/palace/manager/scripts/informational.py index 9c5fe4670d..6514c04188 100644 --- a/src/palace/manager/scripts/informational.py +++ b/src/palace/manager/scripts/informational.py @@ -561,7 +561,6 @@ def languages(self, library): class DisappearingBookReportScript(Script): - """Print a TSV-format report on books that used to be in the collection, or should be in the collection, but aren't. """ diff --git a/src/palace/manager/scripts/metadata.py b/src/palace/manager/scripts/metadata.py index c1294a4722..ae6a5e074e 100644 --- a/src/palace/manager/scripts/metadata.py +++ b/src/palace/manager/scripts/metadata.py @@ -6,7 +6,6 @@ class MetadataCalculationScript(Script): - """Force calculate_presentation() to be called on some set of Editions. This assumes that the metadata is in already in the database and diff --git a/src/palace/manager/scripts/playtime_entries.py b/src/palace/manager/scripts/playtime_entries.py index b73c96e305..7b929f14ed 100644 --- a/src/palace/manager/scripts/playtime_entries.py +++ b/src/palace/manager/scripts/playtime_entries.py @@ -29,8 +29,7 @@ class Writer(Protocol): """CSV Writer protocol.""" - def writerow(self, row: Iterable[Any]) -> Any: - ... + def writerow(self, row: Iterable[Any]) -> Any: ... class PlaytimeEntriesSummationScript(Script): diff --git a/src/palace/manager/search/v5.py b/src/palace/manager/search/v5.py index e95ec14b4c..930c4fa3fb 100644 --- a/src/palace/manager/search/v5.py +++ b/src/palace/manager/search/v5.py @@ -295,7 +295,7 @@ def mapping_document(self) -> SearchMappingDocument: analyzer=dict(self._analyzers), ) document.properties = self._fields - document.scripts[ - self.script_name("work_last_update") - ] = SearchV5.WORK_LAST_UPDATE_SCRIPT + document.scripts[self.script_name("work_last_update")] = ( + SearchV5.WORK_LAST_UPDATE_SCRIPT + ) return document diff --git a/src/palace/manager/service/email/email.py b/src/palace/manager/service/email/email.py index 04373e10fb..c0ce06a60c 100644 --- a/src/palace/manager/service/email/email.py +++ b/src/palace/manager/service/email/email.py @@ -62,5 +62,4 @@ def __call__( html: str | None = None, text: str | None = None, attachments: Mapping[str, str | os.PathLike[Any] | bytes] | None = None, - ) -> EmailMessage: - ... + ) -> EmailMessage: ... diff --git a/src/palace/manager/service/integration_registry/base.py b/src/palace/manager/service/integration_registry/base.py index badb9a809e..0f4146ca46 100644 --- a/src/palace/manager/service/integration_registry/base.py +++ b/src/palace/manager/service/integration_registry/base.py @@ -66,12 +66,10 @@ def register( return integration @overload - def get(self, protocol: str, default: None = ...) -> type[T] | None: - ... + def get(self, protocol: str, default: None = ...) -> type[T] | None: ... @overload - def get(self, protocol: str, default: V) -> type[T] | V: - ... + def get(self, protocol: str, default: V) -> type[T] | V: ... def get(self, protocol: str, default: V | None = None) -> type[T] | V | None: """Look up an integration class by protocol.""" @@ -80,16 +78,13 @@ def get(self, protocol: str, default: V | None = None) -> type[T] | V | None: return self[protocol] @overload - def get_protocol(self, integration: type[T], default: None = ...) -> str | None: - ... + def get_protocol(self, integration: type[T], default: None = ...) -> str | None: ... @overload - def get_protocol(self, integration: type[T], default: Literal[False]) -> str: - ... + def get_protocol(self, integration: type[T], default: Literal[False]) -> str: ... @overload - def get_protocol(self, integration: type[T], default: V) -> str | V: - ... + def get_protocol(self, integration: type[T], default: V) -> str | V: ... def get_protocol( self, integration: type[T], default: V | None | Literal[False] = None @@ -106,16 +101,15 @@ def get_protocol( @overload def get_protocols( self, integration: type[T], default: None = ... - ) -> list[str] | None: - ... + ) -> list[str] | None: ... @overload - def get_protocols(self, integration: type[T], default: Literal[False]) -> list[str]: - ... + def get_protocols( + self, integration: type[T], default: Literal[False] + ) -> list[str]: ... @overload - def get_protocols(self, integration: type[T], default: V) -> list[str] | V: - ... + def get_protocols(self, integration: type[T], default: V) -> list[str] | V: ... def get_protocols( self, integration: type[T], default: V | None | Literal[False] = None diff --git a/src/palace/manager/service/redis/exception.py b/src/palace/manager/service/redis/exception.py index 4159e6aca9..de77279eb5 100644 --- a/src/palace/manager/service/redis/exception.py +++ b/src/palace/manager/service/redis/exception.py @@ -1,9 +1,7 @@ from palace.manager.core.exceptions import BasePalaceException -class RedisKeyError(BasePalaceException, TypeError): - ... +class RedisKeyError(BasePalaceException, TypeError): ... -class RedisValueError(BasePalaceException, ValueError): - ... +class RedisValueError(BasePalaceException, ValueError): ... diff --git a/src/palace/manager/service/redis/key.py b/src/palace/manager/service/redis/key.py index 17d548a72c..eba10429ef 100644 --- a/src/palace/manager/service/redis/key.py +++ b/src/palace/manager/service/redis/key.py @@ -23,8 +23,7 @@ def redis_key_from_id(cls, id_: int | None) -> str: @runtime_checkable class SupportsRedisKey(Protocol): - def redis_key(self) -> str: - ... + def redis_key(self) -> str: ... class RedisKeyGenerator: diff --git a/src/palace/manager/service/redis/models/marc.py b/src/palace/manager/service/redis/models/marc.py index 713a90a56d..6b881e4ac9 100644 --- a/src/palace/manager/service/redis/models/marc.py +++ b/src/palace/manager/service/redis/models/marc.py @@ -123,9 +123,7 @@ def _parts_path(self, upload_key: str) -> str: return f"{upload_path}.parts" @contextmanager - def _pipeline( - self, begin_transaction: bool = True - ) -> Generator[Pipeline, None, None]: + def _pipeline(self, begin_transaction: bool = True) -> Generator[Pipeline]: with self._redis_client.pipeline() as pipe: pipe.watch(self.key) fetched_data = self._parse_multi( diff --git a/src/palace/manager/service/redis/models/patron_activity.py b/src/palace/manager/service/redis/models/patron_activity.py index 3b4d79b5ad..ca5992d621 100644 --- a/src/palace/manager/service/redis/models/patron_activity.py +++ b/src/palace/manager/service/redis/models/patron_activity.py @@ -20,8 +20,7 @@ from backports.strenum import StrEnum -class PatronActivityError(BasePalaceException, RuntimeError): - ... +class PatronActivityError(BasePalaceException, RuntimeError): ... class PatronActivityStatus: diff --git a/src/palace/manager/service/redis/redis.py b/src/palace/manager/service/redis/redis.py index ca602534d4..802b1127dd 100644 --- a/src/palace/manager/service/redis/redis.py +++ b/src/palace/manager/service/redis/redis.py @@ -127,8 +127,7 @@ def _check_prefix(self, *args: Any) -> None: @property @abstractmethod - def _prefix(self) -> str: - ... + def _prefix(self) -> str: ... class Redis(RedisClient, RedisPrefixCheckMixin): diff --git a/src/palace/manager/sqlalchemy/hassessioncache.py b/src/palace/manager/sqlalchemy/hassessioncache.py index 0a2bd4c5fe..4448759a9d 100644 --- a/src/palace/manager/sqlalchemy/hassessioncache.py +++ b/src/palace/manager/sqlalchemy/hassessioncache.py @@ -37,12 +37,10 @@ class HasSessionCache(LoggerMixin): @property @abstractmethod - def id(self) -> Mapped[int]: - ... + def id(self) -> Mapped[int]: ... @abstractmethod - def cache_key(self) -> Hashable: - ... + def cache_key(self) -> Hashable: ... @classmethod def cache_warm( diff --git a/src/palace/manager/sqlalchemy/model/circulationevent.py b/src/palace/manager/sqlalchemy/model/circulationevent.py index dd03d006f2..b41d846eda 100644 --- a/src/palace/manager/sqlalchemy/model/circulationevent.py +++ b/src/palace/manager/sqlalchemy/model/circulationevent.py @@ -11,7 +11,6 @@ class CirculationEvent(Base): - """Changes to a license pool's circulation status. We log these so we can measure things like the velocity of individual books. diff --git a/src/palace/manager/sqlalchemy/model/collection.py b/src/palace/manager/sqlalchemy/model/collection.py index ca20612f16..e59f646f15 100644 --- a/src/palace/manager/sqlalchemy/model/collection.py +++ b/src/palace/manager/sqlalchemy/model/collection.py @@ -47,7 +47,6 @@ class Collection(Base, HasSessionCache, RedisKeyMixin): - """A Collection is a set of LicensePools obtained through some mechanism.""" __tablename__ = "collections" @@ -448,7 +447,7 @@ def data_source(self, new_value: DataSource | str) -> None: ) @property - def parents(self) -> Generator[Collection, None, None]: + def parents(self) -> Generator[Collection]: if not self.parent_id: return None diff --git a/src/palace/manager/sqlalchemy/model/datasource.py b/src/palace/manager/sqlalchemy/model/datasource.py index 07d5fc4e65..fa12285ca2 100644 --- a/src/palace/manager/sqlalchemy/model/datasource.py +++ b/src/palace/manager/sqlalchemy/model/datasource.py @@ -34,7 +34,6 @@ class DataSource(Base, HasSessionCache, DataSourceConstants): - """A source for information about books, and possibly the books themselves.""" __tablename__ = "datasources" diff --git a/src/palace/manager/sqlalchemy/model/edition.py b/src/palace/manager/sqlalchemy/model/edition.py index 002156e109..33893241e5 100644 --- a/src/palace/manager/sqlalchemy/model/edition.py +++ b/src/palace/manager/sqlalchemy/model/edition.py @@ -45,7 +45,6 @@ class Edition(Base, EditionConstants): - """A lightly schematized collection of metadata for a work, or an edition of a work, or a book, or whatever. If someone thinks of it as a "book" with a "title" it can go in here. diff --git a/src/palace/manager/sqlalchemy/model/identifier.py b/src/palace/manager/sqlalchemy/model/identifier.py index dfea81b25c..68eba02c15 100644 --- a/src/palace/manager/sqlalchemy/model/identifier.py +++ b/src/palace/manager/sqlalchemy/model/identifier.py @@ -578,8 +578,7 @@ def parse_urn( identifier_string: str, must_support_license_pools: bool = False, autocreate=True, - ) -> tuple[Identifier, bool]: - ... + ) -> tuple[Identifier, bool]: ... @classmethod @overload @@ -589,8 +588,7 @@ def parse_urn( identifier_string: str | None, must_support_license_pools: bool = False, autocreate=True, - ) -> tuple[Identifier | None, bool | None]: - ... + ) -> tuple[Identifier | None, bool | None]: ... @classmethod def parse_urn( diff --git a/src/palace/manager/sqlalchemy/model/integration.py b/src/palace/manager/sqlalchemy/model/integration.py index 405650e4a4..40c5552fe0 100644 --- a/src/palace/manager/sqlalchemy/model/integration.py +++ b/src/palace/manager/sqlalchemy/model/integration.py @@ -70,14 +70,14 @@ def context_update(self, new_context: dict[str, Any]) -> None: # Self test results, stored as json. self_test_results = Column(JSONB, nullable=False, default=dict) - library_configurations: Mapped[ - list[IntegrationLibraryConfiguration] - ] = relationship( - "IntegrationLibraryConfiguration", - back_populates="parent", - uselist=True, - cascade="all, delete-orphan", - passive_deletes=True, + library_configurations: Mapped[list[IntegrationLibraryConfiguration]] = ( + relationship( + "IntegrationLibraryConfiguration", + back_populates="parent", + uselist=True, + cascade="all, delete-orphan", + passive_deletes=True, + ) ) collection: Mapped[Collection] = relationship( diff --git a/src/palace/manager/sqlalchemy/model/key.py b/src/palace/manager/sqlalchemy/model/key.py index 0da68f0379..2645b427e5 100644 --- a/src/palace/manager/sqlalchemy/model/key.py +++ b/src/palace/manager/sqlalchemy/model/key.py @@ -45,8 +45,7 @@ def get_key( key_id: str | uuid.UUID | None = None, *, raise_exception: Literal[True] = True, - ) -> Self: - ... + ) -> Self: ... @classmethod @overload @@ -57,8 +56,7 @@ def get_key( key_id: str | uuid.UUID | None = None, *, raise_exception: bool = False, - ) -> Self | None: - ... + ) -> Self | None: ... @classmethod def get_key( diff --git a/src/palace/manager/sqlalchemy/model/lane.py b/src/palace/manager/sqlalchemy/model/lane.py index ce30f0a8d8..6bcd34a652 100644 --- a/src/palace/manager/sqlalchemy/model/lane.py +++ b/src/palace/manager/sqlalchemy/model/lane.py @@ -890,7 +890,6 @@ def modify_database_query(self, _db, qu): class FeaturedFacets(FacetsWithEntryPoint): - """A simple faceting object that configures a query so that the 'most featurable' items are at the front. diff --git a/src/palace/manager/sqlalchemy/model/library.py b/src/palace/manager/sqlalchemy/model/library.py index 14692d3aae..d4b8b1c0ea 100644 --- a/src/palace/manager/sqlalchemy/model/library.py +++ b/src/palace/manager/sqlalchemy/model/library.py @@ -311,13 +311,13 @@ def update_settings(self, new_settings: LibrarySettings) -> None: integration_settings_update(LibrarySettings, self, new_settings, merge=True) @property - def all_collections(self) -> Generator[Collection, None, None]: + def all_collections(self) -> Generator[Collection]: for collection in self.collections: yield collection yield from collection.parents @property - def entrypoints(self) -> Generator[type[EntryPoint] | None, None, None]: + def entrypoints(self) -> Generator[type[EntryPoint] | None]: """The EntryPoints enabled for this library.""" values = self.settings.enabled_entry_points for v in values: diff --git a/src/palace/manager/sqlalchemy/model/licensing.py b/src/palace/manager/sqlalchemy/model/licensing.py index 62a8c508fe..a391455ad2 100644 --- a/src/palace/manager/sqlalchemy/model/licensing.py +++ b/src/palace/manager/sqlalchemy/model/licensing.py @@ -351,8 +351,7 @@ def for_foreign_id( foreign_id, rights_status=None, collection=None, - ) -> tuple[LicensePool, bool]: - ... + ) -> tuple[LicensePool, bool]: ... @classmethod @overload @@ -365,8 +364,7 @@ def for_foreign_id( rights_status, collection, autocreate: Literal[False], - ) -> tuple[LicensePool | None, bool]: - ... + ) -> tuple[LicensePool | None, bool]: ... @classmethod def for_foreign_id( @@ -1734,12 +1732,12 @@ class DeliveryMechanism(Base, HasSessionCache): if _media_type is not None and _drm == NO_DRM: default_client_can_fulfill_lookup.add((_media_type, BEARER_TOKEN)) - license_pool_delivery_mechanisms: Mapped[ - list[LicensePoolDeliveryMechanism] - ] = relationship( - "LicensePoolDeliveryMechanism", - back_populates="delivery_mechanism", - uselist=True, + license_pool_delivery_mechanisms: Mapped[list[LicensePoolDeliveryMechanism]] = ( + relationship( + "LicensePoolDeliveryMechanism", + back_populates="delivery_mechanism", + uselist=True, + ) ) __table_args__ = (UniqueConstraint("content_type", "drm_scheme"),) @@ -1988,9 +1986,9 @@ class RightsStatus(Base): name = Column(String, index=True) # One RightsStatus may apply to many LicensePoolDeliveryMechanisms. - licensepooldeliverymechanisms: Mapped[ - list[LicensePoolDeliveryMechanism] - ] = relationship("LicensePoolDeliveryMechanism", backref="rights_status") + licensepooldeliverymechanisms: Mapped[list[LicensePoolDeliveryMechanism]] = ( + relationship("LicensePoolDeliveryMechanism", backref="rights_status") + ) # One RightsStatus may apply to many Resources. resources: Mapped[list[Resource]] = relationship( diff --git a/src/palace/manager/sqlalchemy/model/resource.py b/src/palace/manager/sqlalchemy/model/resource.py index ddb398c875..2e113ada33 100644 --- a/src/palace/manager/sqlalchemy/model/resource.py +++ b/src/palace/manager/sqlalchemy/model/resource.py @@ -81,12 +81,12 @@ class Resource(Base): # Many LicensePools (but probably one at most) may use this # resource in a delivery mechanism. - licensepooldeliverymechanisms: Mapped[ - list[LicensePoolDeliveryMechanism] - ] = relationship( - "LicensePoolDeliveryMechanism", - back_populates="resource", - foreign_keys=[LicensePoolDeliveryMechanism.resource_id], + licensepooldeliverymechanisms: Mapped[list[LicensePoolDeliveryMechanism]] = ( + relationship( + "LicensePoolDeliveryMechanism", + back_populates="resource", + foreign_keys=[LicensePoolDeliveryMechanism.resource_id], + ) ) links: Mapped[list[Hyperlink]] = relationship("Hyperlink", backref="resource") diff --git a/src/palace/manager/sqlalchemy/util.py b/src/palace/manager/sqlalchemy/util.py index 4862680e3a..63ef608ac4 100644 --- a/src/palace/manager/sqlalchemy/util.py +++ b/src/palace/manager/sqlalchemy/util.py @@ -19,7 +19,7 @@ @contextmanager def pg_advisory_lock( connection: Connection | Session, lock_id: int | None -) -> Generator[None, None, None]: +) -> Generator[None]: """ Application wide locking based on Lock IDs diff --git a/src/palace/manager/util/__init__.py b/src/palace/manager/util/__init__.py index 4aff1c8a89..88528af810 100644 --- a/src/palace/manager/util/__init__.py +++ b/src/palace/manager/util/__init__.py @@ -519,7 +519,7 @@ def first_or_default(collection: Iterable, default: Any | None = None) -> Any: def chunks( lst: Sequence[T], chunk_size: int, start_index: int = 0 -) -> Generator[Sequence[T], None, None]: +) -> Generator[Sequence[T]]: """Yield successive n-sized chunks from lst.""" length = len(lst) diff --git a/src/palace/manager/util/aes.py b/src/palace/manager/util/aes.py index f731c50e90..ee2967375a 100644 --- a/src/palace/manager/util/aes.py +++ b/src/palace/manager/util/aes.py @@ -8,12 +8,10 @@ class CryptBase: @abstractmethod - def encrypt(self, content: bytes) -> bytes: - ... + def encrypt(self, content: bytes) -> bytes: ... @abstractmethod - def decrypt(self, content: bytes) -> bytes: - ... + def decrypt(self, content: bytes) -> bytes: ... class CryptAESCBC(CryptBase): diff --git a/src/palace/manager/util/authentication_for_opds.py b/src/palace/manager/util/authentication_for_opds.py index dfcb899d75..e22b031077 100644 --- a/src/palace/manager/util/authentication_for_opds.py +++ b/src/palace/manager/util/authentication_for_opds.py @@ -28,8 +28,7 @@ def authentication_flow_document(self, _db: Session) -> dict[str, Any]: return data @abstractmethod - def _authentication_flow_document(self, _db: Session) -> dict[str, Any]: - ... + def _authentication_flow_document(self, _db: Session) -> dict[str, Any]: ... class AuthenticationForOPDSDocument: diff --git a/src/palace/manager/util/datetime_helpers.py b/src/palace/manager/util/datetime_helpers.py index 9603ead7a8..5189cc452f 100644 --- a/src/palace/manager/util/datetime_helpers.py +++ b/src/palace/manager/util/datetime_helpers.py @@ -49,13 +49,11 @@ def utc_now() -> datetime.datetime: @overload -def to_utc(dt: datetime.datetime) -> datetime.datetime: - ... +def to_utc(dt: datetime.datetime) -> datetime.datetime: ... @overload -def to_utc(dt: datetime.datetime | None) -> datetime.datetime | None: - ... +def to_utc(dt: datetime.datetime | None) -> datetime.datetime | None: ... def to_utc(dt: datetime.datetime | None) -> datetime.datetime | None: diff --git a/src/palace/manager/util/flask_util.py b/src/palace/manager/util/flask_util.py index 71c7420bc4..e01ce29589 100644 --- a/src/palace/manager/util/flask_util.py +++ b/src/palace/manager/util/flask_util.py @@ -1,4 +1,5 @@ """Utilities for Flask applications.""" + import datetime import json import time diff --git a/src/palace/manager/util/http.py b/src/palace/manager/util/http.py index be31add28a..fea3938f18 100644 --- a/src/palace/manager/util/http.py +++ b/src/palace/manager/util/http.py @@ -246,11 +246,9 @@ def _request_with_timeout( # Make sure headers are encoded as utf-8 kwargs["headers"] = { - k.encode() - if isinstance(k, str) - else k: v.encode() - if isinstance(v, str) - else v + k.encode() if isinstance(k, str) else k: ( + v.encode() if isinstance(v, str) else v + ) for k, v in headers.items() } diff --git a/src/palace/manager/util/languages.py b/src/palace/manager/util/languages.py index 346d23be03..bf8c0eed0f 100644 --- a/src/palace/manager/util/languages.py +++ b/src/palace/manager/util/languages.py @@ -1,6 +1,5 @@ """Data and functions for dealing with language names and codes.""" - import re from collections import defaultdict from re import Pattern diff --git a/src/palace/manager/util/notifications.py b/src/palace/manager/util/notifications.py index 1661d31f4b..7e731dc884 100644 --- a/src/palace/manager/util/notifications.py +++ b/src/palace/manager/util/notifications.py @@ -181,9 +181,9 @@ def send_holds_notifications(self, holds: list[Hold]) -> list[str]: if hold.patron.external_identifier: data["external_identifier"] = hold.patron.external_identifier if hold.patron.authorization_identifier: - data[ - "authorization_identifier" - ] = hold.patron.authorization_identifier + data["authorization_identifier"] = ( + hold.patron.authorization_identifier + ) resp = self.send_messages( tokens, messaging.Notification(title=title, body=body), data diff --git a/src/palace/manager/util/problem_detail.py b/src/palace/manager/util/problem_detail.py index 02ca4ad2e4..c8e579f374 100644 --- a/src/palace/manager/util/problem_detail.py +++ b/src/palace/manager/util/problem_detail.py @@ -2,6 +2,7 @@ As per http://datatracker.ietf.org/doc/draft-ietf-appsawg-http-problem/ """ + from __future__ import annotations import json as j @@ -40,7 +41,6 @@ class ProblemDetailModel(BaseModel): class ProblemDetail: - """A common type of problem.""" JSON_MEDIA_TYPE = JSON_MEDIA_TYPE diff --git a/src/palace/manager/util/summary.py b/src/palace/manager/util/summary.py index e447911ed0..a16f7b94c8 100644 --- a/src/palace/manager/util/summary.py +++ b/src/palace/manager/util/summary.py @@ -9,7 +9,6 @@ class SummaryEvaluator: - """Evaluate summaries of a book to find a usable summary. A usable summary will have good coverage of the popular noun diff --git a/src/palace/manager/util/web_publication_manifest.py b/src/palace/manager/util/web_publication_manifest.py index 8c90dc21c8..c659e24794 100644 --- a/src/palace/manager/util/web_publication_manifest.py +++ b/src/palace/manager/util/web_publication_manifest.py @@ -3,7 +3,6 @@ (https://github.com/HadrienGardeur/audiobook-manifest). """ - import json diff --git a/src/palace/manager/util/xmlparser.py b/src/palace/manager/util/xmlparser.py index 653719bc7f..8a88bf26d0 100644 --- a/src/palace/manager/util/xmlparser.py +++ b/src/palace/manager/util/xmlparser.py @@ -14,7 +14,6 @@ class XMLParser: - """Helper functions to process XML data.""" NAMESPACES: dict[str, str] = {} @@ -101,7 +100,7 @@ def _process_all( xpath_expression: str, namespaces: dict[str, str], handler: Callable[[_Element, dict[str, str]], T | None], - ) -> Generator[T, None, None]: + ) -> Generator[T]: """ Process all elements matching the given XPath expression. Calling the given handler function on each element and yielding the result @@ -123,7 +122,7 @@ class XMLProcessor(XMLParser, Generic[T], ABC): def process_all( self, xml: str | bytes | _ElementTree, - ) -> Generator[T, None, None]: + ) -> Generator[T]: """ Process all elements matching the given XPath expression. Calling process_one on each element and yielding the result if it is not None. diff --git a/tests/fixtures/database.py b/tests/fixtures/database.py index 4ae9f88183..a249e3c04f 100644 --- a/tests/fixtures/database.py +++ b/tests/fixtures/database.py @@ -194,7 +194,7 @@ def url(self) -> str: return str(self._config_url.set(database=self.database_name)) @contextmanager - def _db_connection(self) -> Generator[Connection, None, None]: + def _db_connection(self) -> Generator[Connection]: """ Databases need to be created and dropped outside a transaction. This method provides a connection to database URL provided in the configuration that is not @@ -228,7 +228,7 @@ def _drop_db(self) -> None: connection.execute(text(f"DROP DATABASE {self.database_name}")) @contextmanager - def patch_database_url(self) -> Generator[None, None, None]: + def patch_database_url(self) -> Generator[None]: """ This method patches the database URL, so any code that uses it will use the worker specific database. """ @@ -237,7 +237,7 @@ def patch_database_url(self) -> Generator[None, None, None]: @classmethod @contextmanager - def fixture(cls, test_id: TestIdFixture) -> Generator[Self, None, None]: + def fixture(cls, test_id: TestIdFixture) -> Generator[Self]: db_name_fixture = cls(test_id) db_name_fixture._create_db() try: @@ -249,7 +249,7 @@ def fixture(cls, test_id: TestIdFixture) -> Generator[Self, None, None]: @pytest.fixture(scope="session") def database_creation( session_test_id: TestIdFixture, -) -> Generator[DatabaseCreationFixture, None, None]: +) -> Generator[DatabaseCreationFixture]: """ This is a session scoped fixture that provides a unique database for each worker in the test run. """ @@ -260,7 +260,7 @@ def database_creation( @pytest.fixture(scope="function") def function_database_creation( function_test_id: TestIdFixture, -) -> Generator[DatabaseCreationFixture, None, None]: +) -> Generator[DatabaseCreationFixture]: """ This is a function scoped fixture that provides a unique database for each test function. @@ -319,7 +319,7 @@ def _close(self): self.engine.dispose() @contextmanager - def patch_engine(self) -> Generator[None, None, None]: + def patch_engine(self) -> Generator[None]: """ This method patches the SessionManager to use the engine provided by this fixture. @@ -333,7 +333,7 @@ def patch_engine(self) -> Generator[None, None, None]: yield @contextmanager - def patch_engine_error(self) -> Generator[None, None, None]: + def patch_engine_error(self) -> Generator[None]: """ This method patches the SessionManager to raise an exception when the engine is accessed. This is useful when the tests should not be accessing the engine directly. @@ -349,9 +349,7 @@ def patch_engine_error(self) -> Generator[None, None, None]: @classmethod @contextmanager - def fixture( - cls, database_name: DatabaseCreationFixture - ) -> Generator[Self, None, None]: + def fixture(cls, database_name: DatabaseCreationFixture) -> Generator[Self]: db_fixture = cls(database_name) db_fixture.drop_existing_schema() db_fixture._load_model_classes() @@ -365,7 +363,7 @@ def fixture( @pytest.fixture(scope="session") def database( database_creation: DatabaseCreationFixture, -) -> Generator[DatabaseFixture, None, None]: +) -> Generator[DatabaseFixture]: """ This is a session scoped fixture that provides a unique database engine and connection for each worker in the test run. @@ -377,7 +375,7 @@ def database( @pytest.fixture(scope="function") def function_database( function_database_creation: DatabaseCreationFixture, -) -> Generator[DatabaseFixture, None, None]: +) -> Generator[DatabaseFixture]: """ This is a function scoped fixture that provides a unique database engine and connection for each test. This is resource intensive, so it should only be used when necessary. @@ -421,7 +419,7 @@ def _make_default_library(self) -> Library: @contextmanager def fixture( cls, database: DatabaseFixture, services: ServicesFixture - ) -> Generator[Self, None, None]: + ) -> Generator[Self]: db = cls(database, services) try: yield db @@ -1229,7 +1227,7 @@ def db( database: DatabaseFixture, services_fixture: ServicesFixture, work_queue_indexing: WorkQueueIndexingFixture, -) -> Generator[DatabaseTransactionFixture, None, None]: +) -> Generator[DatabaseTransactionFixture]: with DatabaseTransactionFixture.fixture(database, services_fixture) as db: with ( database.patch_engine_error(), @@ -1281,7 +1279,7 @@ def __call__(self) -> Session: return self._session @contextmanager - def begin(self) -> Generator[Session, None, None]: + def begin(self) -> Generator[Session]: with self._session.begin_nested(): yield self._session diff --git a/tests/fixtures/flask.py b/tests/fixtures/flask.py index 485ae98c52..fe06cc3016 100644 --- a/tests/fixtures/flask.py +++ b/tests/fixtures/flask.py @@ -40,7 +40,7 @@ def test_request_context( admin: Admin | None = None, library: Library | None = None, **kwargs: Any, - ) -> Generator[RequestContext, None, None]: + ) -> Generator[RequestContext]: with self.app.test_request_context(*args, **kwargs) as c: self.db.session.begin_nested() flask.request.library = library # type: ignore[attr-defined] @@ -59,7 +59,7 @@ def test_request_context( @contextmanager def test_request_context_system_admin( self, *args: Any, **kwargs: Any - ) -> Generator[RequestContext, None, None]: + ) -> Generator[RequestContext]: admin = self.admin_user() with self.test_request_context(*args, **kwargs, admin=admin) as c: yield c diff --git a/tests/fixtures/s3.py b/tests/fixtures/s3.py index 73023b2623..3236b62b8d 100644 --- a/tests/fixtures/s3.py +++ b/tests/fixtures/s3.py @@ -70,8 +70,7 @@ def _upload_complete(self) -> None: self.key, self.content, self.media_type ) - def _upload_abort(self) -> None: - ... + def _upload_abort(self) -> None: ... @dataclass @@ -178,8 +177,7 @@ def __call__( region: str | None = None, bucket: str | None = None, url_template: str | None = None, - ) -> S3Service: - ... + ) -> S3Service: ... class S3ServiceFixture: @@ -297,9 +295,7 @@ def close(self): @pytest.fixture -def s3_service_integration_fixture() -> ( - Generator[S3ServiceIntegrationFixture, None, None] -): +def s3_service_integration_fixture() -> Generator[S3ServiceIntegrationFixture]: fixture = S3ServiceIntegrationFixture() yield fixture fixture.close() diff --git a/tests/fixtures/search.py b/tests/fixtures/search.py index 430e606c1c..6f70ba160c 100644 --- a/tests/fixtures/search.py +++ b/tests/fixtures/search.py @@ -102,7 +102,7 @@ def external_search_fixture( db: DatabaseTransactionFixture, services_fixture: ServicesFixture, function_test_id: TestIdFixture, -) -> Generator[ExternalSearchFixture, None, None]: +) -> Generator[ExternalSearchFixture]: """Ask for an external search system.""" """Note: You probably want EndToEndSearchFixture instead.""" with ExternalSearchFixture.fixture( @@ -257,7 +257,7 @@ def fixture(cls, search_fixture: ExternalSearchFixture): @pytest.fixture(scope="function") def end_to_end_search_fixture( external_search_fixture: ExternalSearchFixture, -) -> Generator[EndToEndSearchFixture, None, None]: +) -> Generator[EndToEndSearchFixture]: """Ask for an external search system that can be populated with data for end-to-end tests.""" with EndToEndSearchFixture.fixture(external_search_fixture) as fixture: yield fixture @@ -293,7 +293,7 @@ def fixture(cls, db: DatabaseTransactionFixture, services: Services): @pytest.fixture(scope="function") def external_search_fake_fixture( db: DatabaseTransactionFixture, services_fixture: ServicesFixture -) -> Generator[ExternalSearchFixtureFake, None, None]: +) -> Generator[ExternalSearchFixtureFake]: """Ask for an external search system that can be populated with data for end-to-end tests.""" with ExternalSearchFixtureFake.fixture(db, services_fixture.services) as fixture: yield fixture @@ -347,6 +347,6 @@ def fixture(cls): @pytest.fixture(scope="function") -def work_queue_indexing() -> Generator[WorkQueueIndexingFixture, None, None]: +def work_queue_indexing() -> Generator[WorkQueueIndexingFixture]: with WorkQueueIndexingFixture.fixture() as fixture: yield fixture diff --git a/tests/fixtures/services.py b/tests/fixtures/services.py index 1da191a600..b4a38291cf 100644 --- a/tests/fixtures/services.py +++ b/tests/fixtures/services.py @@ -30,7 +30,7 @@ @contextmanager def mock_services_container( services_container: Services, -) -> Generator[None, None, None]: +) -> Generator[None]: from palace.manager.service import container container._container_instance = services_container @@ -201,7 +201,7 @@ def set_base_url(self, base_url: str | None) -> None: self.set_sitewide_config_option("base_url", base_url) @contextmanager - def wired(self) -> Generator[None, None, None]: + def wired(self) -> Generator[None]: wire_container(self.services) try: yield @@ -217,7 +217,7 @@ def services_fixture( services_analytics_fixture: ServicesAnalyticsFixture, services_email_fixture: ServicesEmailFixture, services_celery_fixture: ServicesCeleryFixture, -) -> Generator[ServicesFixture, None, None]: +) -> Generator[ServicesFixture]: fixture = ServicesFixture( logging=services_logging_fixture, storage=services_storage_fixture, @@ -233,6 +233,6 @@ def services_fixture( @pytest.fixture def services_fixture_wired( services_fixture: ServicesFixture, -) -> Generator[ServicesFixture, None, None]: +) -> Generator[ServicesFixture]: with services_fixture.wired(): yield services_fixture diff --git a/tests/manager/api/admin/controller/test_discovery_services.py b/tests/manager/api/admin/controller/test_discovery_services.py index b9c4508f51..5471558668 100644 --- a/tests/manager/api/admin/controller/test_discovery_services.py +++ b/tests/manager/api/admin/controller/test_discovery_services.py @@ -52,7 +52,6 @@ def controller_fixture( class TestDiscoveryServices: - """Test the controller functions that list and create new discovery services. """ diff --git a/tests/manager/api/admin/controller/test_integration_settings.py b/tests/manager/api/admin/controller/test_integration_settings.py index 6528d4063e..ee2e8c1059 100644 --- a/tests/manager/api/admin/controller/test_integration_settings.py +++ b/tests/manager/api/admin/controller/test_integration_settings.py @@ -28,20 +28,16 @@ def settings_class(cls) -> type[BaseSettings]: return BaseSettings -class MockIntegration1(MockIntegrationBase): - ... +class MockIntegration1(MockIntegrationBase): ... -class MockIntegration2(MockIntegrationBase): - ... +class MockIntegration2(MockIntegrationBase): ... -class MockIntegration3(MockIntegrationBase): - ... +class MockIntegration3(MockIntegrationBase): ... -class MockController(IntegrationSettingsController[MockIntegrationBase]): - ... +class MockController(IntegrationSettingsController[MockIntegrationBase]): ... class IntegrationSettingsControllerFixture: diff --git a/tests/manager/api/controller/test_index.py b/tests/manager/api/controller/test_index.py index a3668ee492..b88227239f 100644 --- a/tests/manager/api/controller/test_index.py +++ b/tests/manager/api/controller/test_index.py @@ -110,9 +110,9 @@ def test_authentication_document( assert library_name == doc["title"] # Verify that the authentication document cache is working. - circulation_fixture.manager.authentication_for_opds_documents[ - library_name - ] = "Cached value" + circulation_fixture.manager.authentication_for_opds_documents[library_name] = ( + "Cached value" + ) with circulation_fixture.request_context_with_library( "/", headers=dict(Authorization=circulation_fixture.invalid_auth) ): diff --git a/tests/manager/api/controller/test_loan.py b/tests/manager/api/controller/test_loan.py index e4474ce8a1..5e0d892f83 100644 --- a/tests/manager/api/controller/test_loan.py +++ b/tests/manager/api/controller/test_loan.py @@ -186,9 +186,9 @@ class MockLibraryAuthenticator: short_name = loan_fixture.db.default_library().short_name assert short_name is not None - loan_fixture.manager.auth.library_authenticators[ - short_name - ] = MockLibraryAuthenticator() + loan_fixture.manager.auth.library_authenticators[short_name] = ( + MockLibraryAuthenticator() + ) def mock_can_fulfill_without_loan(patron, pool, lpdm): self.called_with = (patron, pool, lpdm) @@ -986,9 +986,12 @@ def test_fulfill_without_single_item_feed(self, loan_fixture: LoanFixture): authenticated = controller.authenticated_patron_from_request() assert isinstance(authenticated, Patron) loan_fixture.pool.loan_to(authenticated) - with patch( - "palace.manager.api.controller.opds_feed.OPDSAcquisitionFeed.single_entry_loans_feed" - ) as feed, patch.object(circulation, "fulfill") as fulfill: + with ( + patch( + "palace.manager.api.controller.opds_feed.OPDSAcquisitionFeed.single_entry_loans_feed" + ) as feed, + patch.object(circulation, "fulfill") as fulfill, + ): fulfill.return_value = MagicMock(spec=RedirectFulfillment) # The single_item_feed must return this error feed.return_value = NOT_FOUND_ON_REMOTE diff --git a/tests/manager/api/metadata/test_nyt.py b/tests/manager/api/metadata/test_nyt.py index bf497a7834..c062fd3e24 100644 --- a/tests/manager/api/metadata/test_nyt.py +++ b/tests/manager/api/metadata/test_nyt.py @@ -76,7 +76,6 @@ def nyt_fixture( class TestNYTBestSellerAPI: - """Test the API calls.""" def test_from_config(self, nyt_fixture: NYTBestSellerAPIFixture): @@ -150,7 +149,6 @@ def result_500(*args, **kwargs): class TestNYTBestSellerList: - """Test the NYTBestSellerList object and its ability to be turned into a CustomList. """ diff --git a/tests/manager/api/odl/test_importer.py b/tests/manager/api/odl/test_importer.py index 06b5871d31..46a7565b30 100644 --- a/tests/manager/api/odl/test_importer.py +++ b/tests/manager/api/odl/test_importer.py @@ -423,9 +423,11 @@ def test_import_unlimited_access( ebook_delivery_mechanism = opds2_with_odl_importer_fixture.get_delivery_mechanism_by_drm_scheme_and_content_type( license_pool.delivery_mechanisms, MediaTypes.AUDIOBOOK_MANIFEST_MEDIA_TYPE, - DeliveryMechanism.BEARER_TOKEN - if auth_type == OPDS2AuthType.OAUTH - else None, + ( + DeliveryMechanism.BEARER_TOKEN + if auth_type == OPDS2AuthType.OAUTH + else None + ), ) assert ebook_delivery_mechanism is not None diff --git a/tests/manager/api/saml/configuration/test_validator.py b/tests/manager/api/saml/configuration/test_validator.py index 23e56f63c1..ca9ad1a932 100644 --- a/tests/manager/api/saml/configuration/test_validator.py +++ b/tests/manager/api/saml/configuration/test_validator.py @@ -102,13 +102,13 @@ def test_validate( if sp_xml_metadata is not None: submitted_settings["service_provider_xml_metadata"] = sp_xml_metadata if idp_xml_metadata is not None: - submitted_settings[ - "non_federated_identity_provider_xml_metadata" - ] = idp_xml_metadata + submitted_settings["non_federated_identity_provider_xml_metadata"] = ( + idp_xml_metadata + ) if patron_id_regular_expression is not None: - submitted_settings[ - "patron_id_regular_expression" - ] = patron_id_regular_expression + submitted_settings["patron_id_regular_expression"] = ( + patron_id_regular_expression + ) if expected_validation_result is not None: with pytest.raises(ProblemDetailException) as exception: diff --git a/tests/manager/api/saml/test_controller.py b/tests/manager/api/saml/test_controller.py index 8e9bd22f02..ddd46e6f84 100644 --- a/tests/manager/api/saml/test_controller.py +++ b/tests/manager/api/saml/test_controller.py @@ -413,9 +413,9 @@ def test_saml_authentication_callback( type(integration).parent_id = PropertyMock() authenticator.library_authenticators["default"].register_saml_provider(provider) - authenticator.library_authenticators[ - "default" - ].bearer_token_signing_secret = "test" + authenticator.library_authenticators["default"].bearer_token_signing_secret = ( + "test" + ) authenticator.create_bearer_token = MagicMock(return_value=bearer_token) controller = SAMLController(controller_fixture.app.manager, authenticator) diff --git a/tests/manager/api/sip/test_client.py b/tests/manager/api/sip/test_client.py index f2f48fd165..b0b2320478 100644 --- a/tests/manager/api/sip/test_client.py +++ b/tests/manager/api/sip/test_client.py @@ -1,4 +1,5 @@ """Standalone tests of the SIP2 client.""" + import socket import ssl import tempfile diff --git a/tests/manager/api/test_authenticator.py b/tests/manager/api/test_authenticator.py index 9d5e2c9b6a..6e7d5ab73f 100644 --- a/tests/manager/api/test_authenticator.py +++ b/tests/manager/api/test_authenticator.py @@ -1,6 +1,7 @@ """Test the base authentication framework: that is, the classes that don't interact with any particular source of truth. """ + from __future__ import annotations import datetime diff --git a/tests/manager/api/test_bibliotheca.py b/tests/manager/api/test_bibliotheca.py index aa34d234d6..79c09c1d5c 100644 --- a/tests/manager/api/test_bibliotheca.py +++ b/tests/manager/api/test_bibliotheca.py @@ -1931,7 +1931,6 @@ def test_multiple_contributor_roles( class TestBibliographicCoverageProvider(TestBibliothecaAPI): - """Test the code that looks up bibliographic information from Bibliotheca.""" def test_script_instantiation(self, bibliotheca_fixture: BibliothecaAPITestFixture): diff --git a/tests/manager/api/test_circulationapi.py b/tests/manager/api/test_circulationapi.py index f463f42c33..9a3db75839 100644 --- a/tests/manager/api/test_circulationapi.py +++ b/tests/manager/api/test_circulationapi.py @@ -1,4 +1,5 @@ """Test the CirculationAPI.""" + import datetime from datetime import timedelta from typing import cast diff --git a/tests/manager/api/test_selftest.py b/tests/manager/api/test_selftest.py index c54faef562..8968792ef5 100644 --- a/tests/manager/api/test_selftest.py +++ b/tests/manager/api/test_selftest.py @@ -1,4 +1,5 @@ """Test circulation-specific extensions to the self-test infrastructure.""" + from __future__ import annotations from typing import TYPE_CHECKING diff --git a/tests/manager/customlists/test_importer.py b/tests/manager/customlists/test_importer.py index c7489f8ea6..d9ff1f3045 100644 --- a/tests/manager/customlists/test_importer.py +++ b/tests/manager/customlists/test_importer.py @@ -63,9 +63,9 @@ def test_import_library_nonexistent( """If the target library does not exist, importing fails.""" sign_response = MockAPIServerResponse() sign_response.status_code = 200 - sign_response.headers[ - "Set-Cookie" - ] = "csrf_token=DUZ8inJjpISkyCYjHx7PONZM8354pCu4; HttpOnly; Path=/" + sign_response.headers["Set-Cookie"] = ( + "csrf_token=DUZ8inJjpISkyCYjHx7PONZM8354pCu4; HttpOnly; Path=/" + ) mock_web_server.enqueue_response( "POST", "/admin/sign_in_with_password", sign_response ) @@ -679,9 +679,9 @@ def test_import_updates_and_includes_csrf( """Lists are correctly updated and requests include CSRF tokens.""" sign_response = MockAPIServerResponse() sign_response.status_code = 200 - sign_response.headers[ - "Set-Cookie" - ] = "csrf_token=DUZ8inJjpISkyCYjHx7PONZM8354pCu4; HttpOnly; Path=/" + sign_response.headers["Set-Cookie"] = ( + "csrf_token=DUZ8inJjpISkyCYjHx7PONZM8354pCu4; HttpOnly; Path=/" + ) mock_web_server.enqueue_response( "POST", "/admin/sign_in_with_password", sign_response ) diff --git a/tests/manager/scripts/test_customlist.py b/tests/manager/scripts/test_customlist.py index e6fa8dce16..2aee66db28 100644 --- a/tests/manager/scripts/test_customlist.py +++ b/tests/manager/scripts/test_customlist.py @@ -49,9 +49,9 @@ def _populate_works( db.work(with_license_pool=True, title="Unpopular Book") for _ in range(3) ] # This is for back population only - result.populated_books[0].license_pools[ - 0 - ].availability_time = datetime.datetime(1900, 1, 1) + result.populated_books[0].license_pools[0].availability_time = ( + datetime.datetime(1900, 1, 1) + ) db.session.commit() return result diff --git a/tests/manager/sqlalchemy/test_session.py b/tests/manager/sqlalchemy/test_session.py index 09f1dd333f..350381d6dc 100644 --- a/tests/manager/sqlalchemy/test_session.py +++ b/tests/manager/sqlalchemy/test_session.py @@ -100,8 +100,7 @@ def test_production_session(mock_database_url, mock_session): # production_session can also be called with a class that sets the application name mock_session.reset_mock() - class Mock: - ... + class Mock: ... production_session(Mock) mock_session.assert_called_once_with( diff --git a/tests/manager/util/test_languages.py b/tests/manager/util/test_languages.py index 44634b9863..fe72aa2d98 100644 --- a/tests/manager/util/test_languages.py +++ b/tests/manager/util/test_languages.py @@ -1,4 +1,5 @@ """Test language lookup capabilities.""" + import pytest from palace.manager.util.languages import LanguageCodes, LanguageNames, LookupTable diff --git a/tests/migration/conftest.py b/tests/migration/conftest.py index de1d98020e..a650b733ec 100644 --- a/tests/migration/conftest.py +++ b/tests/migration/conftest.py @@ -47,7 +47,7 @@ def alembic_runner( alembic_config: dict[str, Any] | alembic.config.Config | Config, alembic_engine: Engine, services_fixture: ServicesFixture, -) -> Generator[MigrationContext, None, None]: +) -> Generator[MigrationContext]: """ Override this fixture to make sure that we stamp head. Since this is how out database is initialized. The normal fixtures assume you start from an empty database. @@ -63,8 +63,7 @@ def alembic_runner( class RandomName(Protocol): - def __call__(self, length: int | None = None) -> str: - ... + def __call__(self, length: int | None = None) -> str: ... @pytest.fixture @@ -83,8 +82,7 @@ def __call__( connection: Connection, name: str | None = None, short_name: str | None = None, - ) -> int: - ... + ) -> int: ... @pytest.fixture @@ -131,8 +129,7 @@ def __call__( self, connection: Connection, integration_configuration_id: int | None = None, - ) -> int: - ... + ) -> int: ... @pytest.fixture