summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2023-04-12 02:09:02 +0000
committerCoprDistGit <infra@openeuler.org>2023-04-12 02:09:02 +0000
commit1c66b64133ddbb15d1d8f262289e56553dabe513 (patch)
tree49b15f46e83e7cf5736af7c1e870c22b86ab67c5
parentdc0a064d1dfaabd28cfdf410191c6fe6f9379174 (diff)
automatic import of python-django-grpc
-rw-r--r--.gitignore1
-rw-r--r--python-django-grpc.spec613
-rw-r--r--sources1
3 files changed, 615 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..0784578 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1 @@
+/django-grpc-1.0.19.tar.gz
diff --git a/python-django-grpc.spec b/python-django-grpc.spec
new file mode 100644
index 0000000..751641c
--- /dev/null
+++ b/python-django-grpc.spec
@@ -0,0 +1,613 @@
+%global _empty_manifest_terminate_build 0
+Name: python-django-grpc
+Version: 1.0.19
+Release: 1
+Summary: Easy Django based gRPC service
+License: MIT
+URL: https://github.com/gluk-w/django-grpc
+Source0: https://mirrors.nju.edu.cn/pypi/web/packages/e4/14/ee38b1398d47697425c3d4396705fc83bdfdb0fb34d06891ea6bf6d7a54a/django-grpc-1.0.19.tar.gz
+BuildArch: noarch
+
+Requires: python3-setuptools
+
+%description
+# django-grpc
+
+[![CircleCI](https://circleci.com/gh/gluk-w/django-grpc.svg?style=svg)](https://circleci.com/gh/gluk-w/django-grpc)
+
+
+Easy way to launch gRPC server with access to Django ORM and other handy stuff.
+gRPC calls are much faster that traditional HTTP requests because communicate over
+persistent connection and are compressed. Underlying gRPC library is written in C which
+makes it work faster than any RESTful framework where a lot of time is spent on serialization/deserialization.
+
+Note that you need this project only if you want to use Django functionality in gRPC service.
+For pure python implementation [read this](https://grpc.io/docs/languages/python/quickstart/)
+
+* Supported Python: 3.4+
+* Supported Django: 2.X and 3.X
+
+## Installation
+
+```bash
+pip install django-grpc
+```
+
+Update settings.py
+```python
+INSTALLED_APPS = [
+ # ...
+ 'django_grpc',
+]
+
+GRPCSERVER = {
+ 'servicers': ['dotted.path.to.callback.eg.grpc_hook'], # see `grpc_hook()` below
+ 'interceptors': ['dotted.path.to.interceptor_class',], # optional, interceprots are similar to middleware in Django
+ 'maximum_concurrent_rpcs': None,
+ 'options': [("grpc.max_receive_message_length", 1024 * 1024 * 100)], # optional, list of key-value pairs to configure the channel. The full list of available channel arguments: https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
+ 'credentials': [{
+ 'private_key': 'private_key.pem',
+ 'certificate_chain': 'certificate_chain.pem'
+ }], # required only if SSL/TLS support is required to be enabled
+ 'async': False # Default: False, if True then gRPC server will start in ASYNC mode
+}
+```
+
+The callback that initializes "servicer" must look like following:
+```python
+import my_pb2
+import my_pb2_grpc
+
+def grpc_hook(server):
+ my_pb2_grpc.add_MYServicer_to_server(MYServicer(), server)
+
+...
+class MYServicer(my_pb2_grpc.MYServicer):
+
+ def GetPage(self, request, context):
+ response = my_pb2.PageResponse(title="Demo object")
+ return response
+```
+
+## Usage
+```bash
+python manage.py grpcserver
+```
+
+For developer's convenience add `--autoreload` flag during development.
+
+
+## Signals
+The package uses Django signals to allow decoupled applications get notified when some actions occur:
+* `django_grpc.signals.grpc_request_started` - sent before gRPC server begins processing a request
+* `django_grpc.signals.grpc_request_finished` - sent when gRPC server finishes delivering response to the client
+* `django_grpc.signals.grpc_got_request_exception` - this signal is sent whenever RPC encounters an exception while
+processing an incoming request.
+
+Note that signal names are similar to Django's built-in signals, but have "grpc_" prefix.
+
+
+## Serializers
+There is an easy way to serialize django model to gRPC message using `django_grpc.serializers.serialize_model`.
+
+## Helpers
+
+### Ratelimits
+
+You can limit number of requests to your procedures by using decorator `django_grpc.helpers.ratelimit.ratelimit`.
+
+```python
+from tests.sampleapp import helloworld_pb2_grpc, helloworld_pb2
+from django_grpc.helpers import ratelimit
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ @ratelimit(max_calls=10, time_period=60)
+ def SayHello(self, request, context):
+ return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
+```
+> When limit is reached for given time period decorator will abort with status `grpc.StatusCode.RESOURCE_EXHAUSTED`
+
+As storage for state of calls [Django's cache framework](https://docs.djangoproject.com/en/4.0/topics/cache/#django-s-cache-framework)
+is used. By default `"default"` cache system is used but you can specify any other in settings `RATELIMIT_USE_CACHE`
+
+#### Advanced usage
+
+Using groups
+```python
+@ratelimit(max_calls=10, time_period=60, group="main")
+def foo(request, context):
+ ...
+
+@ratelimit(max_calls=5, time_period=60, group="main")
+def bar(request, context):
+ ...
+```
+`foo` and `bar` will share the same counter because they are in the same group
+
+Using keys
+```python
+@ratelimit(max_calls=5, time_period=10, keys=["request:dot.path.to.field"])
+@ratelimit(max_calls=5, time_period=10, keys=["metadata:user-agent"])
+@ratelimit(max_calls=5, time_period=10, keys=[lambda request, context: context.peer()])
+```
+Right now 3 type of keys are supported with prefixes `"request:"`, `"metadata:"` and as callable.
+
+- `"request:"` allows to extract request's field value by doted path
+- `"metadata:"` allows to extract metadata from `context.invocation_metadata()`
+- callable function that takes request and context and returns string
+
+> NOTE: if value of key is empty string it still will be considered a valid value
+> and can cause sharing of ratelimits between different RPCs in the same group
+
+> TIP: To use the same configuration for different RPCs use dict variable
+> ```python
+> MAIN_GROUP = {"max_calls": 5, "time_period": 60, "group": "main"}
+>
+> @ratelimit(**MAIN_GROUP)
+> def foo(request, context):
+> ...
+>
+> @ratelimit(**MAIN_GROUP)
+> def bar(request, context):
+> ...
+> ```
+
+
+## Testing
+Test your RPCs just like regular python methods which return some
+structure or generator. You need to provide them with only 2 parameters:
+request (protobuf structure or generator) and context (use `FakeServicerContext` from the example below).
+
+### Fake Context
+You can pass instance of `django_grpc_testtools.context.FakeServicerContext` to your gRPC method
+to verify how it works with context (aborts, metadata and etc.).
+```python
+import grpc
+from django_grpc_testtools.context import FakeServicerContext
+from tests.sampleapp.servicer import Greeter
+from tests.sampleapp.helloworld_pb2 import HelloRequest
+
+servicer = Greeter()
+context = FakeServicerContext()
+request = HelloRequest(name='Tester')
+
+# To check metadata set by RPC
+response = servicer.SayHello(request, context)
+assert context.get_trailing_metadata("Header1") == '...'
+
+# To check status code
+try:
+ servicer.SayHello(request, context)
+except Exception:
+ pass
+
+assert context.abort_status == grpc.StatusCode.INVALID_ARGUMENT
+assert context.abort_message == 'Cannot say hello to John'
+```
+
+In addition to standard gRPC context methods, FakeServicerContext provides:
+ * `.set_invocation_metadata()` allows to simulate metadata from client to server.
+ * `.get_trailing_metadata()` to get metadata set by your server
+ * `.abort_status` and `.abort_message` to check if `.abort()` was called
+
+
+%package -n python3-django-grpc
+Summary: Easy Django based gRPC service
+Provides: python-django-grpc
+BuildRequires: python3-devel
+BuildRequires: python3-setuptools
+BuildRequires: python3-pip
+%description -n python3-django-grpc
+# django-grpc
+
+[![CircleCI](https://circleci.com/gh/gluk-w/django-grpc.svg?style=svg)](https://circleci.com/gh/gluk-w/django-grpc)
+
+
+Easy way to launch gRPC server with access to Django ORM and other handy stuff.
+gRPC calls are much faster that traditional HTTP requests because communicate over
+persistent connection and are compressed. Underlying gRPC library is written in C which
+makes it work faster than any RESTful framework where a lot of time is spent on serialization/deserialization.
+
+Note that you need this project only if you want to use Django functionality in gRPC service.
+For pure python implementation [read this](https://grpc.io/docs/languages/python/quickstart/)
+
+* Supported Python: 3.4+
+* Supported Django: 2.X and 3.X
+
+## Installation
+
+```bash
+pip install django-grpc
+```
+
+Update settings.py
+```python
+INSTALLED_APPS = [
+ # ...
+ 'django_grpc',
+]
+
+GRPCSERVER = {
+ 'servicers': ['dotted.path.to.callback.eg.grpc_hook'], # see `grpc_hook()` below
+ 'interceptors': ['dotted.path.to.interceptor_class',], # optional, interceprots are similar to middleware in Django
+ 'maximum_concurrent_rpcs': None,
+ 'options': [("grpc.max_receive_message_length", 1024 * 1024 * 100)], # optional, list of key-value pairs to configure the channel. The full list of available channel arguments: https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
+ 'credentials': [{
+ 'private_key': 'private_key.pem',
+ 'certificate_chain': 'certificate_chain.pem'
+ }], # required only if SSL/TLS support is required to be enabled
+ 'async': False # Default: False, if True then gRPC server will start in ASYNC mode
+}
+```
+
+The callback that initializes "servicer" must look like following:
+```python
+import my_pb2
+import my_pb2_grpc
+
+def grpc_hook(server):
+ my_pb2_grpc.add_MYServicer_to_server(MYServicer(), server)
+
+...
+class MYServicer(my_pb2_grpc.MYServicer):
+
+ def GetPage(self, request, context):
+ response = my_pb2.PageResponse(title="Demo object")
+ return response
+```
+
+## Usage
+```bash
+python manage.py grpcserver
+```
+
+For developer's convenience add `--autoreload` flag during development.
+
+
+## Signals
+The package uses Django signals to allow decoupled applications get notified when some actions occur:
+* `django_grpc.signals.grpc_request_started` - sent before gRPC server begins processing a request
+* `django_grpc.signals.grpc_request_finished` - sent when gRPC server finishes delivering response to the client
+* `django_grpc.signals.grpc_got_request_exception` - this signal is sent whenever RPC encounters an exception while
+processing an incoming request.
+
+Note that signal names are similar to Django's built-in signals, but have "grpc_" prefix.
+
+
+## Serializers
+There is an easy way to serialize django model to gRPC message using `django_grpc.serializers.serialize_model`.
+
+## Helpers
+
+### Ratelimits
+
+You can limit number of requests to your procedures by using decorator `django_grpc.helpers.ratelimit.ratelimit`.
+
+```python
+from tests.sampleapp import helloworld_pb2_grpc, helloworld_pb2
+from django_grpc.helpers import ratelimit
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ @ratelimit(max_calls=10, time_period=60)
+ def SayHello(self, request, context):
+ return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
+```
+> When limit is reached for given time period decorator will abort with status `grpc.StatusCode.RESOURCE_EXHAUSTED`
+
+As storage for state of calls [Django's cache framework](https://docs.djangoproject.com/en/4.0/topics/cache/#django-s-cache-framework)
+is used. By default `"default"` cache system is used but you can specify any other in settings `RATELIMIT_USE_CACHE`
+
+#### Advanced usage
+
+Using groups
+```python
+@ratelimit(max_calls=10, time_period=60, group="main")
+def foo(request, context):
+ ...
+
+@ratelimit(max_calls=5, time_period=60, group="main")
+def bar(request, context):
+ ...
+```
+`foo` and `bar` will share the same counter because they are in the same group
+
+Using keys
+```python
+@ratelimit(max_calls=5, time_period=10, keys=["request:dot.path.to.field"])
+@ratelimit(max_calls=5, time_period=10, keys=["metadata:user-agent"])
+@ratelimit(max_calls=5, time_period=10, keys=[lambda request, context: context.peer()])
+```
+Right now 3 type of keys are supported with prefixes `"request:"`, `"metadata:"` and as callable.
+
+- `"request:"` allows to extract request's field value by doted path
+- `"metadata:"` allows to extract metadata from `context.invocation_metadata()`
+- callable function that takes request and context and returns string
+
+> NOTE: if value of key is empty string it still will be considered a valid value
+> and can cause sharing of ratelimits between different RPCs in the same group
+
+> TIP: To use the same configuration for different RPCs use dict variable
+> ```python
+> MAIN_GROUP = {"max_calls": 5, "time_period": 60, "group": "main"}
+>
+> @ratelimit(**MAIN_GROUP)
+> def foo(request, context):
+> ...
+>
+> @ratelimit(**MAIN_GROUP)
+> def bar(request, context):
+> ...
+> ```
+
+
+## Testing
+Test your RPCs just like regular python methods which return some
+structure or generator. You need to provide them with only 2 parameters:
+request (protobuf structure or generator) and context (use `FakeServicerContext` from the example below).
+
+### Fake Context
+You can pass instance of `django_grpc_testtools.context.FakeServicerContext` to your gRPC method
+to verify how it works with context (aborts, metadata and etc.).
+```python
+import grpc
+from django_grpc_testtools.context import FakeServicerContext
+from tests.sampleapp.servicer import Greeter
+from tests.sampleapp.helloworld_pb2 import HelloRequest
+
+servicer = Greeter()
+context = FakeServicerContext()
+request = HelloRequest(name='Tester')
+
+# To check metadata set by RPC
+response = servicer.SayHello(request, context)
+assert context.get_trailing_metadata("Header1") == '...'
+
+# To check status code
+try:
+ servicer.SayHello(request, context)
+except Exception:
+ pass
+
+assert context.abort_status == grpc.StatusCode.INVALID_ARGUMENT
+assert context.abort_message == 'Cannot say hello to John'
+```
+
+In addition to standard gRPC context methods, FakeServicerContext provides:
+ * `.set_invocation_metadata()` allows to simulate metadata from client to server.
+ * `.get_trailing_metadata()` to get metadata set by your server
+ * `.abort_status` and `.abort_message` to check if `.abort()` was called
+
+
+%package help
+Summary: Development documents and examples for django-grpc
+Provides: python3-django-grpc-doc
+%description help
+# django-grpc
+
+[![CircleCI](https://circleci.com/gh/gluk-w/django-grpc.svg?style=svg)](https://circleci.com/gh/gluk-w/django-grpc)
+
+
+Easy way to launch gRPC server with access to Django ORM and other handy stuff.
+gRPC calls are much faster that traditional HTTP requests because communicate over
+persistent connection and are compressed. Underlying gRPC library is written in C which
+makes it work faster than any RESTful framework where a lot of time is spent on serialization/deserialization.
+
+Note that you need this project only if you want to use Django functionality in gRPC service.
+For pure python implementation [read this](https://grpc.io/docs/languages/python/quickstart/)
+
+* Supported Python: 3.4+
+* Supported Django: 2.X and 3.X
+
+## Installation
+
+```bash
+pip install django-grpc
+```
+
+Update settings.py
+```python
+INSTALLED_APPS = [
+ # ...
+ 'django_grpc',
+]
+
+GRPCSERVER = {
+ 'servicers': ['dotted.path.to.callback.eg.grpc_hook'], # see `grpc_hook()` below
+ 'interceptors': ['dotted.path.to.interceptor_class',], # optional, interceprots are similar to middleware in Django
+ 'maximum_concurrent_rpcs': None,
+ 'options': [("grpc.max_receive_message_length", 1024 * 1024 * 100)], # optional, list of key-value pairs to configure the channel. The full list of available channel arguments: https://grpc.github.io/grpc/core/group__grpc__arg__keys.html
+ 'credentials': [{
+ 'private_key': 'private_key.pem',
+ 'certificate_chain': 'certificate_chain.pem'
+ }], # required only if SSL/TLS support is required to be enabled
+ 'async': False # Default: False, if True then gRPC server will start in ASYNC mode
+}
+```
+
+The callback that initializes "servicer" must look like following:
+```python
+import my_pb2
+import my_pb2_grpc
+
+def grpc_hook(server):
+ my_pb2_grpc.add_MYServicer_to_server(MYServicer(), server)
+
+...
+class MYServicer(my_pb2_grpc.MYServicer):
+
+ def GetPage(self, request, context):
+ response = my_pb2.PageResponse(title="Demo object")
+ return response
+```
+
+## Usage
+```bash
+python manage.py grpcserver
+```
+
+For developer's convenience add `--autoreload` flag during development.
+
+
+## Signals
+The package uses Django signals to allow decoupled applications get notified when some actions occur:
+* `django_grpc.signals.grpc_request_started` - sent before gRPC server begins processing a request
+* `django_grpc.signals.grpc_request_finished` - sent when gRPC server finishes delivering response to the client
+* `django_grpc.signals.grpc_got_request_exception` - this signal is sent whenever RPC encounters an exception while
+processing an incoming request.
+
+Note that signal names are similar to Django's built-in signals, but have "grpc_" prefix.
+
+
+## Serializers
+There is an easy way to serialize django model to gRPC message using `django_grpc.serializers.serialize_model`.
+
+## Helpers
+
+### Ratelimits
+
+You can limit number of requests to your procedures by using decorator `django_grpc.helpers.ratelimit.ratelimit`.
+
+```python
+from tests.sampleapp import helloworld_pb2_grpc, helloworld_pb2
+from django_grpc.helpers import ratelimit
+
+
+class Greeter(helloworld_pb2_grpc.GreeterServicer):
+
+ @ratelimit(max_calls=10, time_period=60)
+ def SayHello(self, request, context):
+ return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)
+```
+> When limit is reached for given time period decorator will abort with status `grpc.StatusCode.RESOURCE_EXHAUSTED`
+
+As storage for state of calls [Django's cache framework](https://docs.djangoproject.com/en/4.0/topics/cache/#django-s-cache-framework)
+is used. By default `"default"` cache system is used but you can specify any other in settings `RATELIMIT_USE_CACHE`
+
+#### Advanced usage
+
+Using groups
+```python
+@ratelimit(max_calls=10, time_period=60, group="main")
+def foo(request, context):
+ ...
+
+@ratelimit(max_calls=5, time_period=60, group="main")
+def bar(request, context):
+ ...
+```
+`foo` and `bar` will share the same counter because they are in the same group
+
+Using keys
+```python
+@ratelimit(max_calls=5, time_period=10, keys=["request:dot.path.to.field"])
+@ratelimit(max_calls=5, time_period=10, keys=["metadata:user-agent"])
+@ratelimit(max_calls=5, time_period=10, keys=[lambda request, context: context.peer()])
+```
+Right now 3 type of keys are supported with prefixes `"request:"`, `"metadata:"` and as callable.
+
+- `"request:"` allows to extract request's field value by doted path
+- `"metadata:"` allows to extract metadata from `context.invocation_metadata()`
+- callable function that takes request and context and returns string
+
+> NOTE: if value of key is empty string it still will be considered a valid value
+> and can cause sharing of ratelimits between different RPCs in the same group
+
+> TIP: To use the same configuration for different RPCs use dict variable
+> ```python
+> MAIN_GROUP = {"max_calls": 5, "time_period": 60, "group": "main"}
+>
+> @ratelimit(**MAIN_GROUP)
+> def foo(request, context):
+> ...
+>
+> @ratelimit(**MAIN_GROUP)
+> def bar(request, context):
+> ...
+> ```
+
+
+## Testing
+Test your RPCs just like regular python methods which return some
+structure or generator. You need to provide them with only 2 parameters:
+request (protobuf structure or generator) and context (use `FakeServicerContext` from the example below).
+
+### Fake Context
+You can pass instance of `django_grpc_testtools.context.FakeServicerContext` to your gRPC method
+to verify how it works with context (aborts, metadata and etc.).
+```python
+import grpc
+from django_grpc_testtools.context import FakeServicerContext
+from tests.sampleapp.servicer import Greeter
+from tests.sampleapp.helloworld_pb2 import HelloRequest
+
+servicer = Greeter()
+context = FakeServicerContext()
+request = HelloRequest(name='Tester')
+
+# To check metadata set by RPC
+response = servicer.SayHello(request, context)
+assert context.get_trailing_metadata("Header1") == '...'
+
+# To check status code
+try:
+ servicer.SayHello(request, context)
+except Exception:
+ pass
+
+assert context.abort_status == grpc.StatusCode.INVALID_ARGUMENT
+assert context.abort_message == 'Cannot say hello to John'
+```
+
+In addition to standard gRPC context methods, FakeServicerContext provides:
+ * `.set_invocation_metadata()` allows to simulate metadata from client to server.
+ * `.get_trailing_metadata()` to get metadata set by your server
+ * `.abort_status` and `.abort_message` to check if `.abort()` was called
+
+
+%prep
+%autosetup -n django-grpc-1.0.19
+
+%build
+%py3_build
+
+%install
+%py3_install
+install -d -m755 %{buildroot}/%{_pkgdocdir}
+if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
+if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
+if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
+if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
+pushd %{buildroot}
+if [ -d usr/lib ]; then
+ find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/lib64 ]; then
+ find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/bin ]; then
+ find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+if [ -d usr/sbin ]; then
+ find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
+fi
+touch doclist.lst
+if [ -d usr/share/man ]; then
+ find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
+fi
+popd
+mv %{buildroot}/filelist.lst .
+mv %{buildroot}/doclist.lst .
+
+%files -n python3-django-grpc -f filelist.lst
+%dir %{python3_sitelib}/*
+
+%files help -f doclist.lst
+%{_docdir}/*
+
+%changelog
+* Wed Apr 12 2023 Python_Bot <Python_Bot@openeuler.org> - 1.0.19-1
+- Package Spec generated
diff --git a/sources b/sources
new file mode 100644
index 0000000..7310224
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+36f7f56ac14710ce07d95eddefc42a13 django-grpc-1.0.19.tar.gz