Skip to content

Commit

Permalink
Merge pull request #89 from wesky93/develop
Browse files Browse the repository at this point in the history
0.1.19 Additions
  • Loading branch information
ViridianForge authored Jul 18, 2024
2 parents 22ca02a + 310228b commit 481e203
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 94 deletions.
7 changes: 5 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ on:
- master

jobs:
deploy:
run_tests:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12' ]
python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -27,6 +27,9 @@ jobs:
run: |
ruff check src/grpc_requests/*.py src/tests/*.py --statistics --config ruff.toml
ruff format src/grpc_requests/*.py src/tests/*.py --check --config ruff.toml
- name: Typecheck with mypy
run: |
mypy src/grpc_requests/*.py
- name: Test with pytest
run: |
pytest --cov-report=xml --cov=src/grpc_requests
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# grpc_requests

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
[![PyPI](https://img.shields.io/pypi/v/grpc-requests?style=flat-square)](https://pypi.org/project/grpc-requests)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/grpc-requests?style=flat-square)](https://pypi.org/project/grpc-requests)
[![PyPI download month](https://img.shields.io/pypi/dm/grpc-requests?style=flat-square)](https://pypi.org/project/grpc-requests)
Expand Down Expand Up @@ -60,7 +61,9 @@ usage scenarioes, and the [unit tests](./src/tests/) are also a useful reference
Contributions from the community are welcomed and greatly appreciated.

Before opening a PR, [tests.sh](./tests.sh) can be used to ensure the contribution passes
linting and unit test checks.
linting and unit test checks. You can also run [complexity.sh](./complexity.sh) to use
[radon](https://pypi.org/project/radon/) to look at the cyclomatic complexity,
maintainability index, and Halstead effort and difficulty of files.

PRs should be targeted to merge with the `develop` branch. When opening a PR,
please assign it to a maintainer for review. The maintainers will take it from
Expand Down
37 changes: 37 additions & 0 deletions complexity.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/bash

# This script generated a simplified complexity report for a given series of
# Python files, or for non-__init__.py files in the src/grpc_requests directory
# if no arguments are provided.

# Radon is used to generate the average Cyclomatic Complexity, Maintainability
# Index, and Halstead difficulty and effort metrics for the given files.

# This report is meant as a quick guide to possible weaknesses in the codebase
# and not meant as a make or break test for work being undertaken.

# Cyclomatic Complexity - Lower is better
# Maintainability Index - Higher is better
# Halstead difficulty - Lower is better
# Halstead effort - Lower is better

if ! command -v radon &> /dev/null; then
echo "radon is not installed. Please make sure you have installed the requirements-dev.txt."
exit 1
fi

if [ "$#" -eq 0 ]; then
TARGETS=$(find src/grpc_requests/ -name "*.py" ! -name "__init__.py")
else
TARGETS="${*}"
fi

for TARGET in $TARGETS; do
echo "Report for $TARGET"
echo "===================="
radon cc "$TARGET" -n F -s --total-average | grep "Average" | sed "s|Average complexity|Cyclomatic Complexity|"
radon mi "$TARGET" -s | sed "s|$TARGET|Maintainability Index|"
radon hal "$TARGET" | grep -E "difficulty|effort" | sed "s/^[ \t]*//"
echo "===================="
echo
done
7 changes: 5 additions & 2 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ pytest-asyncio>=0.15.1
aiounittest>=1.4.2
grpc-interceptor>=0.15.4
ruff>=0.1.7
grpcio-tools>=1.60.0
grpcio-reflection>=1.60.0 # Tests require new enough reflection that supports transitive dependencies
grpcio-tools>=1.60.1
grpc-stubs >= 1.53.0
types-protobuf>=5.26.0
radon>=6.0.1
mypy>=1.10.0
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
grpcio
grpcio-reflection
protobuf>=3.20.3
google-api-core>=2.9.0
cryptography>=39.0.1
grpcio >= 1.60.1
grpcio-reflection >= 1.60.1
protobuf>=3.20.3,<5.0.0dev
google-api-core>=2.11.1
cryptography>=41.0.7
3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ classifiers =
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Expand All @@ -29,7 +28,7 @@ classifiers =
packages = find:
package_dir = = src
include_package_data = true
python_requires = >= 3.7
python_requires = >= 3.8
# Dependencies are in setup.py for GitHub's dependency graph.

[options.packages.find]
Expand Down
58 changes: 19 additions & 39 deletions src/grpc_requests/aio.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import sys
from contextlib import suppress
from enum import Enum
from functools import partial
Expand All @@ -12,11 +11,13 @@
NamedTuple,
Optional,
Tuple,
TypeVar,
Union,
)

import importlib.metadata
from typing import Protocol

import grpc
import warnings
from google.protobuf import (
descriptor_pb2,
message_factory,
Expand All @@ -39,23 +40,9 @@

logger = logging.getLogger(__name__)

if sys.version_info >= (3, 8):
import importlib.metadata
from typing import Protocol

def get_metadata(package_name: str):
return importlib.metadata.version(package_name)
else:
import pkg_resources
from typing_extensions import Protocol

warnings.warn(
"Support for Python 3.7 is deprecated and will be removed in version 0.1.19",
stacklevel=1,
)

def get_metadata(package_name: str):
return pkg_resources.get_distribution(package_name).version
def get_metadata(package_name: str):
return importlib.metadata.version(package_name)


# Import GetMessageClass if protobuf version supports it
Expand Down Expand Up @@ -185,13 +172,13 @@ async def parse_stream_responses(self, responses: AsyncIterable):


class CustomArgumentParsers(MessageParsersProtocol):
_message_to_dict_kwargs: Dict[str, Any]
_parse_dict_kwargs: Dict[str, Any]
_message_to_dict_kwargs: Optional[Dict[str, Any]]
_parse_dict_kwargs: Optional[Dict[str, Any]]

def __init__(
self,
message_to_dict_kwargs: Dict[str, Any] = None,
parse_dict_kwargs: Dict[str, Any] = None,
message_to_dict_kwargs: Optional[Dict[str, Any]] = None,
parse_dict_kwargs: Optional[Dict[str, Any]] = None,
):
self._message_to_dict_kwargs = message_to_dict_kwargs or {}
self._parse_dict_kwargs = parse_dict_kwargs or {}
Expand Down Expand Up @@ -254,10 +241,7 @@ def response_parser(self):
return self.parsers.parse_stream_responses


IS_REQUEST_STREAM = TypeVar("IS_REQUEST_STREAM")
IS_RESPONSE_STREAM = TypeVar("IS_RESPONSE_STREAM")

MethodTypeMatch: Dict[Tuple[IS_REQUEST_STREAM, IS_RESPONSE_STREAM], MethodType] = {
MethodTypeMatch: Dict[Tuple[bool, bool], MethodType] = {
(False, False): MethodType.UNARY_UNARY,
(True, False): MethodType.STREAM_UNARY,
(False, True): MethodType.UNARY_STREAM,
Expand All @@ -275,7 +259,7 @@ def __init__(
ssl=False,
compression=None,
skip_check_method_available=False,
message_parsers: MessageParsersProtocol = None,
message_parsers: Optional[MessageParsersProtocol] = None,
**kwargs,
):
super().__init__(
Expand All @@ -291,14 +275,8 @@ def __init__(
self.has_server_registered = False
self._skip_check_method_available = skip_check_method_available
self._message_parsers = message_parsers if message_parsers else MessageParsers()
self._services_module_name = {}
self._service_methods_meta: Dict[str, Dict[str, MethodMetaData]] = {}

self._unary_unary_handler = {}
self._unary_stream_handler = {}
self._stream_unary_handler = {}
self._stream_stream_handler = {}

@classmethod
async def create(cls, endpoint: str, **kwargs) -> "BaseAsyncGrpcClient":
self = cls(endpoint, lazy=False, **kwargs)
Expand All @@ -309,7 +287,7 @@ async def _get_service_names(self):
raise NotImplementedError()

async def check_method_available(
self, service: str, method: str, method_type: MethodType = None
self, service: str, method: str, method_type: Optional[MethodType] = None
):
if self._skip_check_method_available:
return True
Expand Down Expand Up @@ -353,7 +331,7 @@ def _register_methods(
input_type = GetMessageClass(method_desc.input_type)
output_type = GetMessageClass(method_desc.output_type)
else:
msg_factory = message_factory.MessageFactory(method_proto)
msg_factory = message_factory.MessageFactory(self._desc_pool)
input_type = msg_factory.GetPrototype(method_desc.input_type)
output_type = msg_factory.GetPrototype(method_desc.output_type)

Expand Down Expand Up @@ -511,7 +489,7 @@ def __init__(
lazy=True,
ssl=False,
compression=None,
message_parsers: MessageParsersProtocol = None,
message_parsers: Optional[MessageParsersProtocol] = None,
**kwargs,
):
super().__init__(
Expand Down Expand Up @@ -694,7 +672,9 @@ def methods_meta(self):

AsyncClient = ReflectionAsyncClient

_cached_clients = {} # Dict[str, AsyncClient] type (for 3.6,3.7 compatibility https://bugs.python.org/issue34939)
_cached_clients: Dict[
str, Union[BaseAsyncClient, StubAsyncClient, ReflectionAsyncClient]
] = {}


def get_by_endpoint(endpoint, service_descriptors=None, **kwargs) -> AsyncClient:
Expand All @@ -706,7 +686,7 @@ def get_by_endpoint(endpoint, service_descriptors=None, **kwargs) -> AsyncClient
)
else:
_cached_clients[endpoint] = AsyncClient(endpoint, **kwargs)
return _cached_clients[endpoint]
return _cached_clients[endpoint] # type: ignore[return-value]


def reset_cached_async_client(endpoint=None):
Expand Down
Loading

0 comments on commit 481e203

Please sign in to comment.