diff --git a/pyproject.toml b/pyproject.toml index a95f1a19..93c807e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,21 @@ target-version = "py310" [tool.ruff.lint] -select = ["ANN", "D", "E", "F", "I", "N", "PGH", "PLC", "PLE", "PLR", "PLW", "W"] +select = [ + "ANN", + "D", + "E", + "F", + "G", + "I", + "N", + "PGH", + "PLC", + "PLE", + "PLR", + "PLW", + "W", +] ignore = [ "ANN101", "ANN102", diff --git a/store/app/crud/base.py b/store/app/crud/base.py index 32b0f8bc..423fd87a 100644 --- a/store/app/crud/base.py +++ b/store/app/crud/base.py @@ -418,8 +418,7 @@ async def _upload_to_s3(self, data: IO[bytes], name: str, filename: str, content ) logger.info("S3 upload successful") except ClientError as e: - logger.error(f"S3 upload failed: {str(e)}") - logger.error(f"Error details: {e.response['Error']}") + logger.exception("S3 upload failed: %s", e) raise async def _download_from_s3(self, filename: str) -> StreamingBody: diff --git a/store/app/crud/listings.py b/store/app/crud/listings.py index a48b78bb..eaa5c05b 100644 --- a/store/app/crud/listings.py +++ b/store/app/crud/listings.py @@ -48,10 +48,10 @@ async def get_listings( sort_key = self._get_sort_key(sort_by) try: listings, has_next = await self._list(Listing, page, sort_key, search_query) - logger.info(f"Retrieved {len(listings)} listings") + logger.info("Retrieved %s listings", len(listings)) return listings, has_next except Exception as e: - logger.error(f"Error in get_listings: {str(e)}") + logger.exception("Error in get_listings: %s", e) raise def _get_sort_key(self, sort_by: SortOption) -> Callable[[Listing], Any]: @@ -90,7 +90,7 @@ async def _list( try: typed_items = [item_class(**item) for item in valid_items] except Exception as e: - logger.error(f"Error creating {item_class.__name__} objects: {str(e)}") + logger.exception("Error creating %s objects: %s", item_class.__name__, e) raise if sort_key: @@ -114,10 +114,10 @@ async def get_user_listings( sort_key = self._get_sort_key(sort_by) try: listings, has_next = await self._list_me(Listing, user_id, page, sort_key) - logger.info(f"Retrieved {len(listings)} listings for user {user_id}") + logger.info("Retrieved %s listings for user %s", len(listings), user_id) return listings, has_next except Exception as e: - logger.error(f"Error in get_user_listings: {str(e)}") + logger.exception("Error in get_user_listings: %s", e) raise async def get_listings_by_ids(self, listing_ids: list[str]) -> list[Listing]: diff --git a/store/app/crud/users.py b/store/app/crud/users.py index 039782b2..9dece317 100644 --- a/store/app/crud/users.py +++ b/store/app/crud/users.py @@ -98,7 +98,7 @@ async def _create_user_from_email(self, email: str, password: str) -> User: await self._add_item(user, unique_fields=["email", "username"]) return user except Exception as e: - logger.error(f"Error in _create_user_from_email: {str(e)}", exc_info=True) + logger.exception("Error in _create_user_from_email: %s", e) raise async def _create_user_from_oauth( @@ -133,7 +133,7 @@ async def _create_user_from_oauth( await self._add_item(oauth_key, unique_fields=["user_token"]) return user except Exception as e: - logger.error(f"Error in _create_user_from_oauth: {str(e)}", exc_info=True) + logger.exception("Error in _create_user_from_oauth: %s", e) raise @overload @@ -162,7 +162,7 @@ async def get_user_from_github_token(self, token: str, email: str) -> User: return user return await self._create_user_from_oauth(email, "github", auth_key) except Exception as e: - logger.error(f"Error in get_user_from_github_token: {str(e)}", exc_info=True) + logger.exception("Error in get_user_from_github_token: %s", e) raise async def delete_github_token(self, github_id: str) -> None: @@ -178,7 +178,7 @@ async def get_user_from_google_token( return user return await self._create_user_from_oauth(email, "google", auth_key, first_name, last_name) except Exception as e: - logger.error(f"Error in get_user_from_google_token: {str(e)}", exc_info=True) + logger.exception("Error in get_user_from_google_token: %s", e) raise async def delete_google_token(self, google_id: str) -> None: @@ -280,9 +280,9 @@ async def set_username(self, user_id: str, new_username: str) -> User: return user async def is_username_taken(self, username: str) -> bool: - logger.info(f"Checking if username {username} is taken") + logger.info("Checking if username %s is taken", username) existing_users = await self._get_items_from_secondary_index("username", username, User) - logger.info(f"existing_users: {existing_users}") + logger.info("existing_users: %s", existing_users) return len(existing_users) > 0 async def generate_unique_username(self, base: str) -> str: diff --git a/store/app/routers/artifacts.py b/store/app/routers/artifacts.py index bdbf1593..0f87f592 100644 --- a/store/app/routers/artifacts.py +++ b/store/app/routers/artifacts.py @@ -91,7 +91,7 @@ def get_artifact_url_response(artifact: Artifact) -> ArtifactUrls: # If in production, sign both URLs if settings.environment != "local": - logger.debug(f"Original URLs for artifact {artifact.id}: {artifact_urls}") + logger.debug("Original URLs for artifact %s: %s", artifact.id, artifact_urls) signer = CloudFrontUrlSigner( key_id=settings.cloudfront.key_id, diff --git a/store/app/routers/listings.py b/store/app/routers/listings.py index df92ec70..e6667eb9 100644 --- a/store/app/routers/listings.py +++ b/store/app/routers/listings.py @@ -162,7 +162,7 @@ async def get_batch_listing_info( user: Annotated[User | None, Depends(maybe_get_user_from_api_key)], ids: list[str] = Query(description="List of part ids"), ) -> GetBatchListingsResponse: - logger.info(f"Fetching batch listing info for ids: {ids}") + logger.info("Fetching batch listing info for ids: %s", ids) listings, artifacts = await asyncio.gather( crud._get_item_batch(ids, Listing), @@ -217,7 +217,7 @@ async def get_batch_listing_info( ) listing_responses.append(listing_response) except Exception as e: - logger.error(f"Error creating ListingInfoResponse for listing {listing.id}: {str(e)}") + logger.exception("Error creating ListingInfoResponse for listing %s: %s", listing.id, e) return GetBatchListingsResponse(listings=listing_responses) @@ -354,10 +354,10 @@ async def add_listing( return NewListingResponse(listing_id=listing.id, username=user.username, slug=slug) except HTTPException as e: - logger.error(f"HTTPException: {e.detail}") + logger.exception("HTTPException: %s", e.detail) raise except Exception as e: - logger.error(f"Unexpected error: {str(e)}") + logger.exception("Unexpected error: %s", e) raise HTTPException(status_code=500, detail="Internal server error") @@ -573,7 +573,7 @@ async def get_listing( if settings.environment != "local": for artifact in response.artifacts: if not any("Key-Pair-Id=" in url for url in [artifact.urls.small, artifact.urls.large] if url is not None): - logger.error(f"Unsigned URLs found for artifact {artifact.artifact_id} in listing {listing_id}") + logger.exception("Unsigned URLs found for artifact %s in listing %s", artifact.artifact_id, listing_id) return response diff --git a/store/app/routers/orders.py b/store/app/routers/orders.py index 4c74768d..acf3b9db 100644 --- a/store/app/routers/orders.py +++ b/store/app/routers/orders.py @@ -69,11 +69,10 @@ async def get_product_info(order: Order) -> OrderWithProduct: return results except OrdersNotFoundError: - logger.info(f"No orders found for user: {user.id}") + logger.info("No orders found for user: %s", user.id) return [] except Exception as e: - logger.error(f"Error fetching orders: {str(e)}", exc_info=True) - print(f"Error fetching orders: {str(e)}") + logger.exception("Error fetching orders: %s", e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Error fetching orders: {str(e)}" ) @@ -169,7 +168,7 @@ async def get_all_orders( ) orders_with_products.append(OrderWithProduct(order=order, product=product_info)) except Exception as e: - logger.error(f"Error getting product info for order {order.id}: {str(e)}") + logger.exception("Error getting product info for order %s: %s", order.id, e) orders_with_products.append(OrderWithProduct(order=order, product=None)) return AdminOrdersResponse(orders=orders_with_products) diff --git a/store/app/routers/stripe.py b/store/app/routers/stripe.py index 06bc790c..693b6aec 100644 --- a/store/app/routers/stripe.py +++ b/store/app/routers/stripe.py @@ -170,11 +170,11 @@ async def stripe_connect_webhook(request: Request, crud: Crud = Depends(Crud.get user_id = account.get("metadata", {}).get("user_id") if user_id: await crud.update_stripe_connect_status(user_id, account["id"], is_completed=True) - logger.info(f"Updated Connect status for user {user_id}") + logger.info("Updated Connect status for user %s", user_id) else: - logger.warning(f"No user_id in metadata for Connect account: {account['id']}") + logger.warning("No user_id in metadata for Connect account: %s", account["id"]) except Exception as e: - logger.error(f"Error updating user Connect status: {str(e)}") + logger.error("Error updating user Connect status: %s", e) elif event["type"] == "checkout.session.completed": session = event["data"]["object"] @@ -196,9 +196,9 @@ async def stripe_connect_webhook(request: Request, crud: Crud = Depends(Crud.get "updated_at": int(time.time()), }, ) - logger.info(f"Final payment processed for order {order_id}") + logger.info("Final payment processed for order %s", order_id) except Exception as e: - logger.error(f"Error processing final payment webhook: {str(e)}") + logger.error("Error processing final payment webhook: %s", e) raise else: # Handle regular checkout completion @@ -313,7 +313,7 @@ async def create_checkout_session( try: listing = await crud.get_listing(request.listing_id) if not listing or not listing.price_amount: - logger.error(f"Listing not found or has no price: {request.listing_id}") + logger.error("Listing not found or has no price: %s", request.listing_id) raise HTTPException(status_code=404, detail="Listing not found or has no price") seller = await crud.get_user(listing.user_id) @@ -450,7 +450,7 @@ async def create_checkout_session( ) except stripe.StripeError as e: - logger.error(f"Stripe error: {str(e)}", exc_info=True) + logger.exception("Stripe error: %s", e) raise HTTPException(status_code=400, detail=str(e)) @@ -486,10 +486,10 @@ async def get_product(product_id: str, crud: Annotated[Crud, Depends(Crud.get)]) active=product.active, ) except stripe.StripeError as e: - logger.error(f"Stripe error retrieving product: {str(e)}") + logger.exception("Stripe error retrieving product: %s", e) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) except Exception as e: - logger.error(f"Error retrieving product: {str(e)}") + logger.exception("Error retrieving product: %s", e) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) @@ -567,7 +567,7 @@ async def create_connect_account_session( logger.info("Successfully created account session for account: %s", account_id) return {"client_secret": account_session.client_secret} except Exception as e: - logger.error("Error creating account session: %s", str(e), exc_info=True) + logger.exception("Error creating account session: %s", e) raise @@ -669,7 +669,7 @@ async def create_listing_product( ) except stripe.StripeError as e: - logger.error(f"Stripe error creating listing product: {str(e)}") + logger.exception("Stripe error creating listing product: %s", e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"Error creating Stripe product: {str(e)}", @@ -781,8 +781,8 @@ async def process_preorder( ) except stripe.StripeError as e: - logger.error(f"Stripe error processing preorder final payment: {str(e)}") + logger.exception("Stripe error processing preorder final payment: %s", e) raise HTTPException(status_code=400, detail=str(e)) except Exception as e: - logger.error(f"Error processing preorder final payment: {str(e)}") + logger.exception("Error processing preorder final payment: %s", e) raise HTTPException(status_code=500, detail=str(e)) diff --git a/store/app/routers/users.py b/store/app/routers/users.py index 5e62feb8..cc05eda7 100644 --- a/store/app/routers/users.py +++ b/store/app/routers/users.py @@ -228,7 +228,7 @@ async def update_profile( except ValueError as e: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) except Exception as e: - logger.error(f"Error updating profile: {str(e)}") + logger.exception("Error updating profile: %s", e) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="An error occurred while updating the profile.", @@ -288,7 +288,7 @@ async def check_username_availability( username: str, crud: Annotated[Crud, Depends(Crud.get)], ) -> dict[str, bool]: - logger.info(f"Checking if username {username} is taken") + logger.info("Checking if username %s is taken", username) is_taken = await crud.is_username_taken(username) return {"available": not is_taken} @@ -313,7 +313,7 @@ async def set_content_manager( updated_user = await crud.set_content_manager(request.user_id, request.is_content_manager) return UserPublic(**updated_user.model_dump()) except Exception as e: - logger.error(f"Error setting content manager status: {str(e)}") + logger.error("Error setting content manager status: %s", e) raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Unable to update content manager status. Please verify the user exists and try again.", diff --git a/store/app/security/requests.py b/store/app/security/requests.py index 28076969..389f836a 100644 --- a/store/app/security/requests.py +++ b/store/app/security/requests.py @@ -18,7 +18,7 @@ async def get_api_key_from_header(headers: Mapping[str, str], require_header: Li async def get_api_key_from_header(headers: Mapping[str, str], require_header: bool) -> str | None: authorization = headers.get("Authorization") or headers.get("authorization") - logger.debug(f"Received authorization header: {authorization}") + logger.debug("Received authorization header: %s", authorization) if not authorization: if require_header: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Not authenticated")