Git Product home page Git Product logo

django-modern-rpc's Introduction

alorence - Public profile

Website badge Twitter badge Mastodon badge Linkedin badge StackOverflow badge Blog badge

About me

Hey, I'm Antoine Lorence, Python developer, FOSS enthusiast, software architecture specialist and GNU/Linux fan. I live in France and have 2 children.

I started to work as professional developer after my Master's degrees, in 2010. I first worked on C++ and Java softwares, then I discovered Python. I started to use it for some tasks as a readable replacement for Bash/sh scripts, then I discovered all the incredible things that can be achieved with it. In the next years, I started to build websites with Django and various applications. I work now as a Freelancer and more recently, I extended my knowledge in various fields like frontend development or DevOps.

Notable projects

django-modern-rpc

In 2016, I had to configure an XML-RPC endpoint in a Django project I worked on. At this time RPC4Django was the most used library. Unfortunately, it didn't work with latest Django version, was not updated for a long time and the PRs opened to fix issues remained unanswered. I decided to start my own implementation, with a very similar API, but with a support for recent Python & Django versions.

The project has recently reached its first 1.0.0 stable release and is now downloaded almost 10.000 times / month.

pysvg-py

Unofficial Python 3 portage of well-known PySVG library.

Years ago, while porting a legacy project from python 2 to python 3, I discovered that PySVG library was not compatible with Python 3, and no new release were published since 2012. After quickly checking the source code, I saw that adapting the code shouldn't be a big deal. I forked the project, ran 2to3 and verified that the result worked as expected in my project.

I decided to publish it on pypi with a disclamer explaining this is an unofficial port and I was not the original author. That package seemed to be useful for others, since it is now downloaded about 5.000 times per month.

django-modern-rpc's People

Contributors

adamdonahue avatar alorence avatar atodorov avatar codacy-badger avatar dansan avatar dependabot[bot] avatar diegoduncan21 avatar mfonism avatar sergio-bershadsky avatar washeck avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

django-modern-rpc's Issues

API Change : rename decorator used to mark remote procedures

When the library was launched, the decorator used to indicate which functions are provided via RPC service was @rpc_method. This was chosen to keep an API similar to rpc4django.

Now, the decorator name seems odd and it will renamed to @remote_procedure to be more clear for future users. An alias will be declared to ensure a smooth transition for exsting projcts.

Doc improvement: error handling

Documentation need to be updated to add information on how errors are handled in django-modern-rpc:

  • Explain how exceptions are used internally
  • Explain how to configure logging to get errors from RPC methods
  • Give logging config examples to report errors by email (using django.utils.log.AdminEmailHandler)
  • Give logging config examples to report errors to Sentry (using raven.handlers.logging.SentryHandler)

This enhancement is a direct follow of discussion #13

Improve exception raised when invalid protocol is given to RPCEntryPoint

PR #29 showed that when an invalid protocol string is given to RPCEntryPoint, displayed error is not very useful. It could be interesting to catch the case in RPCEntryPoint.get_handler_classes() and raise a correct exception (to indicate an invalid protocol given (or at least a warning).

In addition, it is strange that importing protocol string using

from modernrpc.handlers import JSONRPC, XMLRPC

raise a ImproperlyConfigured: At least 1 handler must be instantiated instead of ImportError. Must investigate

Silent warning on load

I got this

Warning: Unable to load module "api.rpc_methods" declared in settings.MODERNRPC_METHODS_MODULES. Please ensure it is available and doesn't contain any error

and no trace with logger configured to handle modernrpc.

I believe this should be critical error with trace back and exit, as it would be with bug in Django view. Or even better, such exceptions should not be handled by Django-modern-rpc at all. This is not runtime exception like while calling rpc - where it is ok to intercept exception and return error in json-rpm response. This is start up error, so while developing app I have to immediately know where the bug is.

Access to authenticated user from an RPC method

I am not sure if this is a feature request or a request for an example in the docs?

A typical RPC method looks like this

@rpc_method
@http_basic_auth_login_required
def my_method(x,y):
    return do_something_with(x,y)

But I would like to define do_something_with() as

def do_something_with(x, y, user):
   #blah blah
   return result

There is a utility function in auth.basic
def http_basic_auth_get_user(request), but this needs the Django request, which it seems is not passed
to the RPC method.

Is there a function like modern_rpc.get_current_request() ?
e.g.

@rpc_method
@http_basic_auth_login_required
def my_method(x, y):
    user = http_basic_auth_get_user(get_current_request())
    return do_something_with(x, y, user)

DeprecationWarning somewhere hidden

Hi, I am using your app (love it) for a week or so, however I would really like to get rid of the following message I get as soon as I add the app to my INSTALLED_APPS list:

DeprecationWarning: __class__ not set defining 'AbstractBaseUser' as <class 'django.contrib.auth.base_user.AbstractBaseUser'>. Was __classcell__ propagated to type.__new__?
  class AbstractBaseUser(models.Model):

I have tried to seek for myself where it's coming from but I cannot seem to find it.

My requirements.txt:

appdirs==1.4.0
Django==1.10.5
django-modern-rpc==0.4.2
mysqlclient==1.3.9
packaging==16.8
pyparsing==2.1.10
six==1.10.0

Do you know where it's coming from and how it can be fixed?

Thanks!

Problems with kwargs in method called

I faced conflict with request, entry_point, protocol, handler params name because they are kewords in modernrpc.core

REQUEST_KEY = 'request'
ENTRY_POINT_KEY = 'entry_point'
PROTOCOL_KEY = 'protocol'
HANDLER_KEY = 'handler'

would be handy if there will be some workaround to rename keywords per method or settings level

No way to catch exception

Accroding to https://github.com/alorence/django-modern-rpc/blob/master/modernrpc/views.py#L97
and https://github.com/alorence/django-modern-rpc/blob/master/modernrpc/handlers/jsonhandler.py#L176

Looks like there is no way to raise Exception to top level. So there is no way to log it with django logging module or sentry for instance. In settings.DEBUG=True mode exception must be raised and NOT 'swallowed' or 'silented' by inner try/exception block and returned as normal response output

Serializing datetime.date in Python 2

Is there anyway to make datetime.date object serializable in Python 2 using XML? It keeps throwing a

 <Fault -32603: "Internal error: Unable to serialize result as valid XML: cannot marshal <type 'datetime.date'> objects">

Thanks.

Expose models via RPC?

Hi folks,
I have a decent size project at https://github.com/kiwitcms/Kiwi which does have a custom grown XML-RPC interface (legacy code) pretty much all of which exposes the available models and variations of the filter/get/create and update methods. The underlying methods boil down to performing a query, iterating over it and serializing every object as a dictionary. Then there's a Python API client which duplicates most of this structure in order to read the serialized data and turn it back into something more Pythonic.

How hard would be to expose models over RPC with modernrpc ? If that is doable I'd rather spend my time contributing a PR to you and dropping all the legacy stuff in Kiwi instead of manually going through each of our exposed RPC methods and figuring out of there are duplicates or not.

Session auth

Is there any simple way to use Django builtin session auth ?
I am using it with all url requests, after login so there would be nice to make use of it with rpc without frontend keeping login/password.

My code is using @login_required, @permission_required. Does it should work with django-modern-rpc ?

Maybe another possibility is a way making use of PyJWT ?

Where to start ?

Support params as dict (with keywords)

Currently, the parser (JSON in this case) only allows for list-style params. As the RFC allows for params to be provided by-position (as an array) or by-names (as an object/dict), the following change in views.py would accomplish this:

--- test/python3.4/site-packages/modernrpc/views.py	2017-09-29 17:29:49.783385708 -0400
+++ lib/python3.4/site-packages/modernrpc/views.py	2017-09-29 17:25:58.539645454 -0400
@@ -113,5 +113,8 @@
 
                     # Call the python function associated with the RPC method name
-                    result = rpc_method.execute(*params, **kwargs)
+                    if isinstance(params, list):
+                        result = rpc_method.execute(*params, **kwargs)
+                    else:
+                        result = rpc_method.execute(params, **kwargs)

The parser itself probably does not need to be changed since the default empty params as [] (list) wouldn't affect the method being called.

TypeError: RPC Method is not JSON serializable

Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x7f5c85273510>
Traceback (most recent call last):
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/core/management/commands/runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/utils/autoreload.py", line 249, in raise_last_exception
    six.reraise(*_exception)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/utils/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/utils/autoreload.py", line 226, in wrapper
    fn(*args, **kwargs)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/__init__.py", line 18, in setup
    apps.populate(settings.INSTALLED_APPS)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django/apps/registry.py", line 115, in populate
    app_config.ready()
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/modernrpc/apps.py", line 43, in ready
    registered_name = register_rpc_method(func)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/modernrpc/core.py", line 358, in register_rpc_method
    cache.set(RPC_REGISTRY_KEY, registry, timeout=DEFAULT_REGISTRY_TIMEOUT)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django_redis/cache.py", line 33, in _decorator
    return method(self, *args, **kwargs)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django_redis/cache.py", line 68, in set
    return self.client.set(*args, **kwargs)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django_redis/client/default.py", line 109, in set
    nvalue = self.encode(value)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django_redis/client/default.py", line 329, in encode
    value = self._serializer.dumps(value)
  
File "/home/shaman/Work/envs/smart_house/lib/python3.4/site-packages/django_redis/serializers/json.py", line 14, in dumps
    return force_bytes(json.dumps(value))
  
File "/usr/lib/python3.4/json/__init__.py", line 230, in dumps
    return _default_encoder.encode(obj)
  
File "/usr/lib/python3.4/json/encoder.py", line 192, in encode
    chunks = self.iterencode(o, _one_shot=True)
  
File "/usr/lib/python3.4/json/encoder.py", line 250, in iterencode
    return _iterencode(o, 0)
  
File "/usr/lib/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")

TypeError: RPC Method add is not JSON serializable

Django: 1.9.10
Python: 3.4.2

Example from "Quick start" guide not work.

JSON-RPC batch requests not supported

Sending batch requests causes "Invalid request, Payload object must be a struct" error.

Batch requests feature is part of 2.0 spec, please remove "JSON-RPC 2.0 support" notice in your documentation or implement this feature.

Drop Python 3.3 support

Python 3.3.0 was released on September 29th, 2012 and has now reached its end-of-life. More and more python libraries and packages drop its support. Django requires Python 3.4 since version 1.9, setuptools from version 40.0.0.

It became difficult to maintain support for Python 3.3, so django-modern-rpc will require 3.4.

Implementing a simple rest endpoint; POSTMAN returns no data

Following the documentation, I have implemented a simple rpc method

@rpc_method
def content_type_printer(**kwargs):

    # Get the current request
    request = kwargs.get(REQUEST_KEY)

    # Other available objects are:
    # protocol = kwargs.get(PROTOCOL_KEY)
    # entry_point = kwargs.get(ENTRY_POINT_KEY)
    # handler = kwargs.get(HANDLER_KEY)

    # Return the content-type of the current request
    return request.META.get('Content-Type', '')

However when I try making a POST request to the /rpc endpoint, the request succeeds but nothing is returned. What am I missing here?

enter image description here

Application import symantics hide errors

If there is an import error in rpc_methods.py (or whatever it's called in a given instance) then the current import semantics in modernrpc/apps.py mean the error is ignored. Even worse, it fails to pick up any logger so the actual error just creates the text:
No handlers could be found for logger "modernrpc.apps"
in the django log.
It should at least say something like.
Perhaps there should be a wrapper round getLogger in case the logging is not configured for such an important non-runtime error.

 except ImportError as er:
                    logger.warning('Unable to load module "{}". Please check MODERNRPC_METHODS_MODULES for invalid'
                                   ' names'.format(module_name))
                    print "Error:", module_name, er
                    continue

to repeat:
create and register an rpc_methods.py with the like "import no_such_module" at the top.

Make a new release

Please, make a new release. There was no release in almost a year and main branch contains some unreleased fixes.

Currently, django-modern-rpc is blocking users from testing Django 5.0 RC1, as the released version uses deprecated distutils which incorrectly refuses 5.0rc1 as invalid version specifier.

Missing supported XML-RPC Content-Type

XML request made with Insomnia will send a default application/xml Content-Type, which is currently not supported.

Wikipedia article about XML explicitely list both application/xml and text/xml as valid.

While the original XML-RPC specification stated only text/xml should be supported, maybe application/xml support should be added to allow usage with modern tools

HTTP response code in case of error response

Hi, I skimmed through JSON-RPC specification that it is linked in the docs, but I didn't find anything about HTTP status code in case of error response. I guess the assumption there was that it’s transport layer agnostic, but we use Django and HTTP as transport here and I noticed that the HTTP status code is always 200, even when I raise exception and error response is returned to the client.

So, my question is: should it be this way, or error response should have other status code? The way it is now, the client always has to check the response's body and search for "error" key. Would I break the specification if I changed it to return let’s say 4XX status code?
And the second question: what would be the best way to implement such a change on my side? My first thought is to write a simple middleware that would change the status code in the error response.

Does not install markdown

For some reason, the library does not install Markdown when installed through Pip. I found this out by settign my MODERNRPC_DOC_FORMAT to markdown.

Other than that, great library

RFC: rate limit support

I had the impression that this library supported rate limiting but I can't find anything on that topic. Maybe I am wrong.

In any case has anyone tried other rate-limiting libraries in conjunction with django-modern-rpc?

If not what do people think about adding such support? Any hints to implementation? I can work on a PR sometime in the future as I will probably need such functionality.

How to specify XML Serializer?

I am trying to access Django Model, but it gave me an InternalError. what's happening on server side is simple retrieve a user model and return to the client.

I would like to try using Django XMLSerializer but have no idea how to configure.

  File "/usr/lib64/python3.6/xmlrpc/client.py", line 1112, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib64/python3.6/xmlrpc/client.py", line 1452, in __request
    verbose=self.__verbose
  File "/usr/lib64/python3.6/xmlrpc/client.py", line 1154, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/usr/lib64/python3.6/xmlrpc/client.py", line 1170, in single_request
    return self.parse_response(resp)
  File "/usr/lib64/python3.6/xmlrpc/client.py", line 1342, in parse_response
    return u.close()
  File "/usr/lib64/python3.6/xmlrpc/client.py", line 656, in close
    raise Fault(**self._stack[0])
xmlrpc.client.Fault: <Fault -32603: 'Internal error: Unable to serialize result as valid XML: encode() argument 1 must be string, not None'>
>>> 



Tries to install Django 1.11. Why?

In setup.py:

install_requires=[
        "Django>=1.8.0",
]

In env installed Django 1.10.7. Run pip install django-modern-rpc - tries to install Django 1.11.

Why?

set_authentication_predicate bug

If a user wants to use set_authentication_predicate as decorator, as explained in the tutorial:

https://django-modern-rpc.readthedocs.io/en/latest/advanced/authentication.html#basics

then that function should be like this:

def set_authentication_predicate(predicate, params=None):
    """
    Assign a new authentication predicate to an RPC method.
    This is the most generic decorator used to implement authentication.
    Predicate is a standard function with the following signature:
    .. code:: python
       def my_predicate(request, *params):
           # Inspect request and extract required information
           if <condition>:
               # The condition to execute the method are met
               return True
           return False
    :param predicate:
    :param params:
    :return:
    """
    
    def decorator(rpc_method):
        if hasattr(rpc_method, 'modernrpc_auth_predicates'):
            rpc_method.modernrpc_auth_predicates.append(predicate)
            rpc_method.modernrpc_auth_predicates_params.append(params)

        else:
            rpc_method.modernrpc_auth_predicates = [predicate]
            rpc_method.modernrpc_auth_predicates_params = [params]

        return rpc_method

    return  decorator

xml rpc entity processing issue

Hi, i'm trying to send request in XML format and i need to read methodnames from a dtd file on my host.

the request is

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root SYSTEM "http://myhost.com/methods.dtd">
<root>
    <id>1</id>
    <methodName>&methodName;</methodName>
    <params>
        <user>admin</user>
    </params>
    <jsonrpc>2.0</jsonrpc>
</root>

resone is

<?xml version="1.0"?>
            <methodResponse>
                <fault>
<value><struct>
<member>
<name>faultCode</name>
<value><int>-32600</int></value>
</member>
<member>
<name>faultString</name>
<value><string>Invalid request: Missing methodName. Please provide the name of the procedure you want to call</string></value>
</member>
</struct></value>
</fault>

            </methodResponse>

it seems there is a problem while defining entity and calling them in the request.

PS: it works with calling methodNames directly (like system.listMethods)

Suppress "django-modern-rpc initialized" on django startup

modernrpc.apps loggs the number of RPC methods registered on app registration. While this can provide some debugging info, it is printed every time you run manage.py which is bit annoying and in our case even breaks autocomplete for manage.py.

I suggest to change the log level of the message to DEBUG, making it possible for users to enable it, but making it disabled by default.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.