From 3c5923776d7d7a6bf80f11efa6afc210df0daadf Mon Sep 17 00:00:00 2001 From: Faizan Azim Date: Thu, 16 Oct 2025 18:36:47 +0000 Subject: [PATCH] refactor(proto): replace google.protobuf.Empty with custom RefreshResponse --- .github/copilot-instructions.md | 9 ++++++++ protos/google/protobuf/empty.proto | 21 ------------------- protos/refresh.proto | 8 ++++--- pyproject.toml | 2 +- .../core/handler/refresh_handler.py | 9 ++++---- src/tp_auth_serverside/pb/refresh_pb2.py | 12 ++++++----- src/tp_auth_serverside/pb/refresh_pb2_grpc.py | 9 ++++---- 7 files changed, 30 insertions(+), 40 deletions(-) delete mode 100644 protos/google/protobuf/empty.proto diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 387423e..a5f48c2 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -6,7 +6,14 @@ Always reference these instructions first and fallback to search or bash command ## Working Effectively +### Environment Manager: +- **Package Manager**: Uses `uv` for dependency and virtual environment management +- **Activate Environment**: Always use `source .venv/bin/activate` before running any Python commands +- **Install Dependencies**: `uv pip install -e .` or `pip install -e .` (within activated venv) +- **All Python/pip commands must be run within activated venv** + ### Bootstrap, Build, and Test Repository: +- `source .venv/bin/activate` -- activate the uv-managed virtual environment FIRST - `pip install -e .` -- installs the package in development mode. NEVER CANCEL: Takes 10-60 seconds, may timeout due to network issues. Set timeout to 120+ seconds (extra margin for slow mirrors or network issues). - `pip install coverage pre-commit pytest pytest-cov pytest-dotenv ruff grpcio-tools` -- installs development dependencies. NEVER CANCEL: Takes 30-120 seconds. Set timeout to 180+ seconds (extra margin for slow mirrors or network issues). - `python -m pytest tests/ -v` -- runs unit tests (when tests are available) @@ -121,10 +128,12 @@ tp-auth-serverside/ ### gRPC and Protocol Buffer Development: - **Protobuf Compilation**: `python -m grpc_tools.protoc --proto_path=protos --python_out=src/tp_auth_serverside/pb --grpc_python_out=src/tp_auth_serverside/pb protos/refresh.proto` +- **After Generation**: Manually fix the import in `refresh_pb2_grpc.py` to use absolute import: `from tp_auth_serverside.pb import refresh_pb2 as refresh__pb2` - **Generated Files**: Located in `src/tp_auth_serverside/pb/` (refresh_pb2.py, refresh_pb2_grpc.py) - **Service Implementation**: `RefreshHandler` class in `src/tp_auth_serverside/core/handler/refresh_handler.py` - **Testing gRPC**: Requires starting both Redis and gRPC server for integration tests - **Proto Schema**: `protos/refresh.proto` defines the RefreshService interface +- **No External Proto Dependencies**: Package uses custom `RefreshResponse` message instead of `google.protobuf.Empty` to avoid external dependencies ## Database Types and Testing diff --git a/protos/google/protobuf/empty.proto b/protos/google/protobuf/empty.proto deleted file mode 100644 index 833c090..0000000 --- a/protos/google/protobuf/empty.proto +++ /dev/null @@ -1,21 +0,0 @@ -syntax = "proto3"; - -package google.protobuf; - -option go_package = "google.golang.org/protobuf/types/known/emptypb"; -option java_package = "com.google.protobuf"; -option java_outer_classname = "EmptyProto"; -option java_multiple_files = true; -option objc_class_prefix = "GPB"; -option csharp_namespace = "Google.Protobuf.WellKnownTypes"; -option cc_enable_arenas = true; - -// A generic empty message that you can re-use to avoid defining duplicated -// empty messages in your APIs. A typical example is to use it as the request -// or the response type of an API method. For instance: -// -// service Foo { -// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); -// } -// -message Empty {} diff --git a/protos/refresh.proto b/protos/refresh.proto index e9b9f23..c1cf8c3 100644 --- a/protos/refresh.proto +++ b/protos/refresh.proto @@ -1,7 +1,5 @@ syntax = "proto3"; -import "google/protobuf/empty.proto"; - package refresh; message RefreshRequest { @@ -9,6 +7,10 @@ message RefreshRequest { string token = 2; } +message RefreshResponse { + // Empty response - no fields needed +} + service RefreshService { - rpc RefreshToken (RefreshRequest) returns (google.protobuf.Empty); + rpc RefreshToken (RefreshRequest) returns (RefreshResponse); } diff --git a/pyproject.toml b/pyproject.toml index 397839e..371b9fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "tp-auth-serverside" -version = "0.1.3" +version = "0.1.4" description = "A server side authentication utility which stores session tokens in memory db." readme = "README.md" requires-python = ">=3.13" diff --git a/src/tp_auth_serverside/core/handler/refresh_handler.py b/src/tp_auth_serverside/core/handler/refresh_handler.py index bc5a6df..a631ae0 100644 --- a/src/tp_auth_serverside/core/handler/refresh_handler.py +++ b/src/tp_auth_serverside/core/handler/refresh_handler.py @@ -1,9 +1,8 @@ import logging -from google.protobuf import empty_pb2 - from tp_auth_serverside.db.memorydb.login import get_token, set_token from tp_auth_serverside.db.memorydb.refresh import is_refresh_restricted, set_restrict_refresh +from tp_auth_serverside.pb import refresh_pb2 from tp_auth_serverside.pb.refresh_pb2_grpc import RefreshServiceServicer from tp_auth_serverside.utilities.jwt_util import JWTUtil @@ -14,10 +13,10 @@ async def RefreshToken(self, request, context): token = request.token if await is_refresh_restricted(user_id, token): logging.warning(f"Refresh token is restricted for user_id: {user_id}, token: {token}") - return empty_pb2.Empty() + return refresh_pb2.RefreshResponse() jwt_token = await get_token(user_id, token) if not jwt_token: - return empty_pb2.Empty() + return refresh_pb2.RefreshResponse() jwt_util = JWTUtil() try: logging.info(f"Refreshing token for user_id: {user_id}, token: {token}") @@ -27,4 +26,4 @@ async def RefreshToken(self, request, context): await set_restrict_refresh(user_id, token) except Exception as e: logging.error(f"Error refreshing token for user_id: {user_id}, token: {token}, error: {e}") - return empty_pb2.Empty() + return refresh_pb2.RefreshResponse() diff --git a/src/tp_auth_serverside/pb/refresh_pb2.py b/src/tp_auth_serverside/pb/refresh_pb2.py index 48767d9..27c60e8 100644 --- a/src/tp_auth_serverside/pb/refresh_pb2.py +++ b/src/tp_auth_serverside/pb/refresh_pb2.py @@ -18,7 +18,7 @@ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n\rrefresh.proto\x12\x07refresh\x1a\x1bgoogle/protobuf/empty.proto"0\n\x0eRefreshRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t2Q\n\x0eRefreshService\x12?\n\x0cRefreshToken\x12\x17.refresh.RefreshRequest\x1a\x16.google.protobuf.Emptyb\x06proto3' + b'\n\rrefresh.proto\x12\x07refresh"0\n\x0eRefreshRequest\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\r\n\x05token\x18\x02 \x01(\t"\x11\n\x0fRefreshResponse2S\n\x0eRefreshService\x12\x41\n\x0cRefreshToken\x12\x17.refresh.RefreshRequest\x1a\x18.refresh.RefreshResponseb\x06proto3' ) _globals = globals() @@ -26,8 +26,10 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, "refresh_pb2", _globals) if not _descriptor._USE_C_DESCRIPTORS: DESCRIPTOR._loaded_options = None - _globals["_REFRESHREQUEST"]._serialized_start = 55 - _globals["_REFRESHREQUEST"]._serialized_end = 103 - _globals["_REFRESHSERVICE"]._serialized_start = 105 - _globals["_REFRESHSERVICE"]._serialized_end = 186 + _globals["_REFRESHREQUEST"]._serialized_start = 26 + _globals["_REFRESHREQUEST"]._serialized_end = 74 + _globals["_REFRESHRESPONSE"]._serialized_start = 76 + _globals["_REFRESHRESPONSE"]._serialized_end = 93 + _globals["_REFRESHSERVICE"]._serialized_start = 95 + _globals["_REFRESHSERVICE"]._serialized_end = 178 # @@protoc_insertion_point(module_scope) diff --git a/src/tp_auth_serverside/pb/refresh_pb2_grpc.py b/src/tp_auth_serverside/pb/refresh_pb2_grpc.py index d5cd4b9..84353c9 100644 --- a/src/tp_auth_serverside/pb/refresh_pb2_grpc.py +++ b/src/tp_auth_serverside/pb/refresh_pb2_grpc.py @@ -2,9 +2,8 @@ """Client and server classes corresponding to protobuf-defined services.""" import grpc -from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2 -import tp_auth_serverside.pb.refresh_pb2 as refresh__pb2 +from tp_auth_serverside.pb import refresh_pb2 as refresh__pb2 GRPC_GENERATED_VERSION = "1.75.1" GRPC_VERSION = grpc.__version__ @@ -39,7 +38,7 @@ def __init__(self, channel): self.RefreshToken = channel.unary_unary( "/refresh.RefreshService/RefreshToken", request_serializer=refresh__pb2.RefreshRequest.SerializeToString, - response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString, + response_deserializer=refresh__pb2.RefreshResponse.FromString, _registered_method=True, ) @@ -59,7 +58,7 @@ def add_RefreshServiceServicer_to_server(servicer, server): "RefreshToken": grpc.unary_unary_rpc_method_handler( servicer.RefreshToken, request_deserializer=refresh__pb2.RefreshRequest.FromString, - response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString, + response_serializer=refresh__pb2.RefreshResponse.SerializeToString, ), } generic_handler = grpc.method_handlers_generic_handler("refresh.RefreshService", rpc_method_handlers) @@ -89,7 +88,7 @@ def RefreshToken( target, "/refresh.RefreshService/RefreshToken", refresh__pb2.RefreshRequest.SerializeToString, - google_dot_protobuf_dot_empty__pb2.Empty.FromString, + refresh__pb2.RefreshResponse.FromString, options, channel_credentials, insecure,