Embrace the APIs of the future. Hug aims to make developing APIs as simple as possible, but no simpler.

Overview

HUG

PyPI version Build Status Windows Build Status Coverage Status License Join the chat at https://gitter.im/timothycrosley/hug


Read Latest Documentation - Browse GitHub Code Repository


hug aims to make developing Python driven APIs as simple as possible, but no simpler. As a result, it drastically simplifies Python API development.

hug's Design Objectives:

  • Make developing a Python driven API as succinct as a written definition.
  • The framework should encourage code that self-documents.
  • It should be fast. A developer should never feel the need to look somewhere else for performance reasons.
  • Writing tests for APIs written on-top of hug should be easy and intuitive.
  • Magic done once, in an API framework, is better than pushing the problem set to the user of the API framework.
  • Be the basis for next generation Python APIs, embracing the latest technology.

As a result of these goals, hug is Python 3+ only and built upon Falcon's high performance HTTP library

HUG Hello World Example

Supporting hug development

Get professionally supported hug with the Tidelift Subscription

Professional support for hug is available as part of the Tidelift Subscription. Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.

Installing hug

Installing hug is as simple as:

pip3 install hug --upgrade

Ideally, within a virtual environment.

Getting Started

Build an example API with a simple endpoint in just a few lines.

# filename: happy_birthday.py
"""A basic (single function) API written using hug"""
import hug


@hug.get('/happy_birthday')
def happy_birthday(name, age:hug.types.number=1):
    """Says happy birthday to a user"""
    return "Happy {age} Birthday {name}!".format(**locals())

To run, from the command line type:

hug -f happy_birthday.py

You can access the example in your browser at: localhost:8000/happy_birthday?name=hug&age=1. Then check out the documentation for your API at localhost:8000/documentation

Parameters can also be encoded in the URL (check out happy_birthday.py for the whole example).

@hug.get('/greet/{event}')
def greet(event: str):
    """Greets appropriately (from http://blog.ketchum.com/how-to-write-10-common-holiday-greetings/)  """
    greetings = "Happy"
    if event == "Christmas":
        greetings = "Merry"
    if event == "Kwanzaa":
        greetings = "Joyous"
    if event == "wishes":
        greetings = "Warm"

    return "{greetings} {event}!".format(**locals())

Which, once you are running the server as above, you can use this way:

curl http://localhost:8000/greet/wishes
"Warm wishes!"

Versioning with hug

# filename: versioning_example.py
"""A simple example of a hug API call with versioning"""
import hug

@hug.get('/echo', versions=1)
def echo(text):
    return text


@hug.get('/echo', versions=range(2, 5))
def echo(text):
    return "Echo: {text}".format(**locals())

To run the example:

hug -f versioning_example.py

Then you can access the example from localhost:8000/v1/echo?text=Hi / localhost:8000/v2/echo?text=Hi Or access the documentation for your API from localhost:8000

Note: versioning in hug automatically supports both the version header as well as direct URL based specification.

Testing hug APIs

hug's http method decorators don't modify your original functions. This makes testing hug APIs as simple as testing any other Python functions. Additionally, this means interacting with your API functions in other Python code is as straight forward as calling Python only API functions. hug makes it easy to test the full Python stack of your API by using the hug.test module:

import hug
import happy_birthday

hug.test.get(happy_birthday, 'happy_birthday', {'name': 'Timothy', 'age': 25}) # Returns a Response object

You can use this Response object for test assertions (check out test_happy_birthday.py ):

def tests_happy_birthday():
    response = hug.test.get(happy_birthday, 'happy_birthday', {'name': 'Timothy', 'age': 25})
    assert response.status == HTTP_200
    assert response.data is not None

Running hug with other WSGI based servers

hug exposes a __hug_wsgi__ magic method on every API module automatically. Running your hug based API on any standard wsgi server should be as simple as pointing it to module_name: __hug_wsgi__.

For Example:

uwsgi --http 0.0.0.0:8000 --wsgi-file examples/hello_world.py --callable __hug_wsgi__

To run the hello world hug example API.

Building Blocks of a hug API

When building an API using the hug framework you'll use the following concepts:

METHOD Decorators get, post, update, etc HTTP method decorators that expose your Python function as an API while keeping your Python method unchanged

@hug.get() # <- Is the hug METHOD decorator
def hello_world():
    return "Hello"

hug uses the structure of the function you decorate to automatically generate documentation for users of your API. hug always passes a request, response, and api_version variable to your function if they are defined params in your function definition.

Type Annotations functions that optionally are attached to your methods arguments to specify how the argument is validated and converted into a Python type

@hug.get()
def math(number_1:int, number_2:int): #The :int after both arguments is the Type Annotation
    return number_1 + number_2

Type annotations also feed into hug's automatic documentation generation to let users of your API know what data to supply.

Directives functions that get executed with the request / response data based on being requested as an argument in your api_function. These apply as input parameters only, and can not be applied currently as output formats or transformations.

@hug.get()
def test_time(hug_timer):
    return {'time_taken': float(hug_timer)}

Directives may be accessed via an argument with a hug_ prefix, or by using Python 3 type annotations. The latter is the more modern approach, and is recommended. Directives declared in a module can be accessed by using their fully qualified name as the type annotation (ex: module.directive_name).

Aside from the obvious input transformation use case, directives can be used to pipe data into your API functions, even if they are not present in the request query string, POST body, etc. For an example of how to use directives in this way, see the authentication example in the examples folder.

Adding your own directives is straight forward:

@hug.directive()
def square(value=1, **kwargs):
    '''Returns passed in parameter multiplied by itself'''
    return value * value

@hug.get()
@hug.local()
def tester(value: square=10):
    return value

tester() == 100

For completeness, here is an example of accessing the directive via the magic name approach:

@hug.directive()
def multiply(value=1, **kwargs):
    '''Returns passed in parameter multiplied by itself'''
    return value * value

@hug.get()
@hug.local()
def tester(hug_multiply=10):
    return hug_multiply

tester() == 100

Output Formatters a function that takes the output of your API function and formats it for transport to the user of the API.

@hug.default_output_format()
def my_output_formatter(data):
    return "STRING:{0}".format(data)

@hug.get(output=hug.output_format.json)
def hello():
    return {'hello': 'world'}

as shown, you can easily change the output format for both an entire API as well as an individual API call

Input Formatters a function that takes the body of data given from a user of your API and formats it for handling.

@hug.default_input_format("application/json")
def my_input_formatter(data):
    return ('Results', hug.input_format.json(data))

Input formatters are mapped based on the content_type of the request data, and only perform basic parsing. More detailed parsing should be done by the Type Annotations present on your api_function

Middleware functions that get called for every request a hug API processes

@hug.request_middleware()
def process_data(request, response):
    request.env['SERVER_NAME'] = 'changed'

@hug.response_middleware()
def process_data(request, response, resource):
    response.set_header('MyHeader', 'Value')

You can also easily add any Falcon style middleware using:

__hug__.http.add_middleware(MiddlewareObject())

Parameter mapping can be used to override inferred parameter names, eg. for reserved keywords:

import marshmallow.fields as fields
...

@hug.get('/foo', map_params={'from': 'from_date'})  # API call uses 'from'
def get_foo_by_date(from_date: fields.DateTime()):
    return find_foo(from_date)

Input formatters are mapped based on the content_type of the request data, and only perform basic parsing. More detailed parsing should be done by the Type Annotations present on your api_function

Splitting APIs over multiple files

hug enables you to organize large projects in any manner you see fit. You can import any module that contains hug decorated functions (request handling, directives, type handlers, etc) and extend your base API with that module.

For example:

something.py

import hug

@hug.get('/')
def say_hi():
    return 'hello from something'

Can be imported into the main API file:

__init__.py

import hug
from . import something

@hug.get('/')
def say_hi():
    return "Hi from root"

@hug.extend_api('/something')
def something_api():
    return [something]

Or alternatively - for cases like this - where only one module is being included per a URL route:

#alternatively
hug.API(__name__).extend(something, '/something')

Configuring hug 404

By default, hug returns an auto generated API spec when a user tries to access an endpoint that isn't defined. If you would not like to return this spec you can turn off 404 documentation:

From the command line application:

hug -nd -f {file} #nd flag tells hug not to generate documentation on 404

Additionally, you can easily create a custom 404 handler using the hug.not_found decorator:

@hug.not_found()
def not_found_handler():
    return "Not Found"

This decorator works in the same manner as the hug HTTP method decorators, and is even version aware:

@hug.not_found(versions=1)
def not_found_handler():
    return ""

@hug.not_found(versions=2)
def not_found_handler():
    return "Not Found"

Asyncio support

When using the get and cli method decorator on coroutines, hug will schedule the execution of the coroutine.

Using asyncio coroutine decorator

@hug.get()
@asyncio.coroutine
def hello_world():
    return "Hello"

Using Python 3.5 async keyword.

@hug.get()
async def hello_world():
    return "Hello"

NOTE: Hug is running on top Falcon which is not an asynchronous server. Even if using asyncio, requests will still be processed synchronously.

Using Docker

If you like to develop in Docker and keep your system clean, you can do that but you'll need to first install Docker Compose.

Once you've done that, you'll need to cd into the docker directory and run the web server (Gunicorn) specified in ./docker/gunicorn/Dockerfile, after which you can preview the output of your API in the browser on your host machine.

$ cd ./docker
# This will run Gunicorn on port 8000 of the Docker container.
$ docker-compose up gunicorn

# From the host machine, find your Dockers IP address.
# For Windows & Mac:
$ docker-machine ip default

# For Linux:
$ ifconfig docker0 | grep 'inet' | cut -d: -f2 | awk '{ print $1}' | head -n1

By default, the IP is 172.17.0.1. Assuming that's the IP you see, as well, you would then go to http://172.17.0.1:8000/ in your browser to view your API.

You can also log into a Docker container that you can consider your work space. This workspace has Python and Pip installed so you can use those tools within Docker. If you need to test the CLI interface, for example, you would use this.

$ docker-compose run workspace bash

On your Docker workspace container, the ./docker/templates directory on your host computer is mounted to /src in the Docker container. This is specified under services > app of ./docker/docker-compose.yml.

bash-4.3# cd /src
bash-4.3# tree
.
├── __init__.py
└── handlers
    ├── birthday.py
    └── hello.py

1 directory, 3 files

Security contact information

hug takes security and quality seriously. This focus is why we depend only on thoroughly tested components and utilize static analysis tools (such as bandit and safety) to verify the security of our code base. If you find or encounter any potential security issues, please let us know right away so we can resolve them.

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Why hug?

HUG simply stands for Hopefully Useful Guide. This represents the project's goal to help guide developers into creating well written and intuitive APIs.


Thanks and I hope you find this hug helpful as you develop your next Python API!

~Timothy Crosley

Comments
  • Running Dev server on Windows

    Running Dev server on Windows

    Hi,

    I love this project by the way - it made my life so much simpler!

    I just upgraded to 2.01 and now my Dev server won't start. I'm probably doing it all wrong anyway, so I hope someone will steer me right.

    I have a small 'run.py' script that sits outside the API package I wrote, and it calls __hug__.serve()

    This worked on 1.9.9, but after upgrading to 2.0.1 it throws this error:

      File "U:\API\.env\lib\site-packages\hug\use.py", line 171, in Socket
        'unix_stream': (socket.AF_UNIX, socket.SOCK_STREAM),
    AttributeError: 'module' object has no attribute 'AF_UNIX'
    

    I tried switching to use hug.API(api).http.server(), and even a crude call(["hug", "api"]), all with the same error.

    Am I being dumb? or was there a change that broke Windows?

    Thanks!

    Geoff

    bug 
    opened by geoffjukes 13
  • Use of output formatter seems to affect required parameters

    Use of output formatter seems to affect required parameters

    I don't know why the presence of an output formatter would affect making sure required parameters are present...

    
    '''
    Both of these have a single parameter named "data".
    If you call the one without the output formatter, it correctly notices the missing parameter.
    If you call the one with the output formatter, it raises a server error.
    
    '''
    import hug
    
    @hug.get('/without_output_formatter')
    def with_output_formatter(data):
        ''' 
        If called without the required parameter, gives you ...
    HTTP/1.0 400 Bad Request
    Date: Mon, 01 Feb 2016 04:09:15 GMT
    Server: WSGIServer/0.2 CPython/3.4.3+
    content-length: 55
    content-type: application/json
    
    {
        "errors": {
            "data": "Required parameter not supplied"
        }
    }
    
        '''
        return 'Without Output Formatter'
    
    @hug.get('/with_output_formatter',output=hug.output_format.svg_xml_image)
    def without_output_formatter(data):
        ''' 
        If called without the required parameter, gives you ...
    HTTP/1.0 500 Internal Server Error
    Content-Length: 59
    Content-Type: text/plain
    Date: Mon, 01 Feb 2016 04:09:09 GMT
    Server: WSGIServer/0.2 CPython/3.4.3+
    
    A server error occurred.  Please contact the administrator.
    
    
        ''' 
        return 'With Output Formatter'
    
    
    
    question 
    opened by horvathcom 11
  • Python 3.7 compatibility

    Python 3.7 compatibility

    Due to possible changes with asyncio, it appears hug may have a problem with python 3.7.x. Tested using Python 3.7.0beta2.

    Traceback (most recent call last):
      File "/usr/local/bin/hug", line 7, in <module>
        from hug import development_runner
      File "/usr/local/lib/python3.7/site-packages/hug/__init__.py", line 36, in <module>
        from hug import (authentication, directives, exceptions, format, input_format, introspect,
      File "/usr/local/lib/python3.7/site-packages/hug/route.py", line 29, in <module>
        import hug.api
      File "/usr/local/lib/python3.7/site-packages/hug/api.py", line 37, in <module>
        from hug._async import asyncio, ensure_future
      File "/usr/local/lib/python3.7/site-packages/hug/_async.py", line 30
        ensure_future = asyncio.async  # pragma: no cover
                                    ^
    SyntaxError: invalid syntax```
    
    
    opened by swilcox 10
  • Minimal hug program not working on Win10

    Minimal hug program not working on Win10

    I am trying to execute the following program:

    import hug
    
    @hug.get('/')
    def root():
        return 'hello'
    

    This is the error, that I'm getting:

    >hug -f main.py
    
    Traceback (most recent call last):
      File "c:\users\simon\appdata\local\programs\python\python36\lib\runpy.py", line 193, in _run_module_as_main
        "__main__", mod_spec)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "C:\Users\Simon\AppData\Local\Programs\Python\Python36\Scripts\hug.exe\__main__.py", line 9, in <module>
      File "hug\interface.py", line 454, in hug.interface.CLI.__call__ (hug\interface.c:12894)
      File "hug\interface.py", line 99, in hug.interface.Interfaces.__call__ (hug\interface.c:3672)
      File "hug\development_runner.py", line 82, in hug.development_runner.hug (hug\development_runner.c:2605)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\process.py", line 105, in start
        self._popen = self._Popen(self)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\context.py", line 223, in _Popen
        return _default_context.get_context().Process._Popen(process_obj)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\context.py", line 322, in _Popen
        return Popen(process_obj)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\popen_spawn_win32.py", line 65, in __init__
        reduction.dump(process_obj, to_child)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\reduction.py", line 60, in dump
        ForkingPickler(file, protocol).dump(obj)
    TypeError: can't pickle module objects
    
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\spawn.py", line 99, in spawn_main
        new_handle = reduction.steal_handle(parent_pid, pipe_handle)
      File "c:\users\simon\appdata\local\programs\python\python36\lib\multiprocessing\reduction.py", line 82, in steal_handle
        _winapi.PROCESS_DUP_HANDLE, False, source_pid)
    OSError: [WinError 87] Wrong parameter
    

    I even deleted python and reinstalled everything. Any ideas?

    help wanted question 
    opened by sonovice 10
  • TypeError in development_runner.py

    TypeError in development_runner.py

    With 2.4.1 on 3.7.0, you can reproduce this by just running hug -f t.py over the following script:

    import hug
    
    @hug.get("/test")
    def test_func(r: dict):
        print(r)
        return {"r": r}
    

    and gives you this (I guess it behaves the same with any kind of run, even the --module one):

    $ hug -f t.py
    Unhandled exception in thread started by <function reload_checker at 0x10324e0d0>
    Traceback (most recent call last):
      File "/usr/local/lib/python3.7/site-packages/hug/development_runner.py", line 108, in reload_checker
        if path[-4:] in ('.pyo', '.pyc'):
    TypeError: 'NoneType' object is not subscriptable
    

    L.E.: the problem doesn't seem to appear if you also supply the --manual_reload True parameter.

    bug 
    opened by cmin764 9
  • Feature: Support ujson if installed

    Feature: Support ujson if installed

    If installed but no wish to use it set HUG_USE_UJSON=0 environmental variable. This is for the sake of people not wanting to use ujson even when installed in the python environment.

    This would increase the performance dramatically for those microservices that are basically JSON loaders/dumpers endpoints.

    opened by danigosa 9
  • How to serve static files in a directory

    How to serve static files in a directory

    It would be nice if there was an example how to serve static files from a directory from within hug, so that other hug mechanisms, like authentication work. This can be needed to load a single page web application. (For example I am using hug as a prototyp serving backend in https://github.com/Intevation/intelmq-fody where it would be useful to serve the static files.)

    In https://github.com/timothycrosley/hug/issues/43#issuecomment-197343923 the need for this can be seen. (There not solved by hug, but by pecan using static..)

    question 
    opened by bernhardreiter 9
  • Support async / await

    Support async / await

    It would be nice if you could register coroutines or async functions as api endpoints. Currently I am using async but each endpoint is responsible for managing the event loop. So for now I have something like:

    loop = asyncio.get_event_loop()
    
    @hug.post('/')
    def spinup_service():
        future1 = asyncio.ensure_future(call_asynchronous_provisioner())
        loop.run_until_complete(future1)
        future2 = asyncio.ensure_future(call_another_async(future1.result())
        loop.run_until_complete(future2)
        return future2.result()
    

    Instead I would prefer the following to be allowed:

    @hug.post('/')
    async def spinup_service():
        result1 = await call_asynchronous_provisioner()
        return await call_another_async(result1)
    
    enhancement 
    opened by zbyte64 9
  • How to use Class based routing

    How to use Class based routing

    After reading up on #162

    I am curious how I would use this, along with further routing.

    so if I have the class from the above:

    class class_1:
        pass
    

    how would I route the HTTP verbs to given methods. Ideally, I would like to do something like:

    class User:
        @hug.get('/')
        def get(self):
            return {[...], [...]}
    
        @hug.get('/{id}')
        def get_by_id(self, id: int):
            return {...}
    

    which means that get_by_id() method would route to `/user/{id}' if I mounted the class per above:

    import hug
    import library
    
    route = hug.route.API(__name__)
    route.object('/user')(library.User)
    

    One purpose for this is that I would like to use something like the remodel module for interacting with rethinkdb, and it requires setting up your models/resources/documents based on classes which inherit from its own Model class. So I am trying to see if there is a way I can get them to play together nicely without having to write my own wrapper either around, or to replace remodel.

    The other option would be to do the normal method based routing, but then have a class next to them that is the actual DB model. The methods then interact with that class. But seeing some issues like #211 makes me think that would go against the grain with getting auto generated docs would work.

    question 
    opened by autoferrit 9
  • More authorization scaffolding or access to request object?

    More authorization scaffolding or access to request object?

    I am writing an API that needs to change output based on which user is logged in. I really like what I've been able to do with hug so far, but I'm not really seeing a clean way to do this at this point. Ideally, the functions would be able to access some kind of session information.

    I know auth is implemented as nicely wrapped falcon middleware at the moment, so this may be rather tricky to pull off plumbing wise. If you arrive at a high-levl solution and are open to contributions, I'd be happy to contribute, as I do have a pressing use case for this.

    enhancement 
    opened by ianthetechie 9
  • Making hug a no-op when running in python2?

    Making hug a no-op when running in python2?

    Hug is great. I'd love to take advantage of it in my code when I'm using python3, e.g. to provide a CLI interface.

    But I'd also like my code to run under python2.

    Can I special-case the import of hug itself, then somehow mock out the decorators, so they just don't get in the way if the code is run via python2?

    question 
    opened by nealmcb 8
  • Bump wheel from 0.33.4 to 0.38.1 in /requirements

    Bump wheel from 0.33.4 to 0.38.1 in /requirements

    Bumps wheel from 0.33.4 to 0.38.1.

    Changelog

    Sourced from wheel's changelog.

    Release Notes

    UNRELEASED

    • Updated vendored packaging to 22.0

    0.38.4 (2022-11-09)

    • Fixed PKG-INFO conversion in bdist_wheel mangling UTF-8 header values in METADATA (PR by Anderson Bravalheri)

    0.38.3 (2022-11-08)

    • Fixed install failure when used with --no-binary, reported on Ubuntu 20.04, by removing setup_requires from setup.cfg

    0.38.2 (2022-11-05)

    • Fixed regression introduced in v0.38.1 which broke parsing of wheel file names with multiple platform tags

    0.38.1 (2022-11-04)

    • Removed install dependency on setuptools
    • The future-proof fix in 0.36.0 for converting PyPy's SOABI into a abi tag was faulty. Fixed so that future changes in the SOABI will not change the tag.

    0.38.0 (2022-10-21)

    • Dropped support for Python < 3.7
    • Updated vendored packaging to 21.3
    • Replaced all uses of distutils with setuptools
    • The handling of license_files (including glob patterns and default values) is now delegated to setuptools>=57.0.0 (#466). The package dependencies were updated to reflect this change.
    • Fixed potential DoS attack via the WHEEL_INFO_RE regular expression
    • Fixed ValueError: ZIP does not support timestamps before 1980 when using SOURCE_DATE_EPOCH=0 or when on-disk timestamps are earlier than 1980-01-01. Such timestamps are now changed to the minimum value before packaging.

    0.37.1 (2021-12-22)

    • Fixed wheel pack duplicating the WHEEL contents when the build number has changed (#415)
    • Fixed parsing of file names containing commas in RECORD (PR by Hood Chatham)

    0.37.0 (2021-08-09)

    • Added official Python 3.10 support
    • Updated vendored packaging library to v20.9

    ... (truncated)

    Commits
    • 6f1608d Created a new release
    • cf8f5ef Moved news item from PR #484 to its proper place
    • 9ec2016 Removed install dependency on setuptools (#483)
    • 747e1f6 Fixed PyPy SOABI parsing (#484)
    • 7627548 [pre-commit.ci] pre-commit autoupdate (#480)
    • 7b9e8e1 Test on Python 3.11 final
    • a04dfef Updated the pypi-publish action
    • 94bb62c Fixed docs not building due to code style changes
    • d635664 Updated the codecov action to the latest version
    • fcb94cd Updated version to match the release
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Addressing issue commented in #599

    Addressing issue commented in #599

    Contrary to the documentation the parse_body and private arguments would only be checked for presence, although it is their value that matters.


    I had to locally patch hug for the parse_body issue, because otherwise it misbehaved.

    opened by exoosh 0
  • Could you please clarify this deprecation warning?!

    Could you please clarify this deprecation warning?!

    .local/lib/python3.9/site-packages/hug/api.py:500: DeprecatedWarning: Call to deprecated function __init__(...). API >
      module.__hug_wsgi__ = module.__hug__.http.server()
    

    I was starting the app with Gunicorn and the wsgi_app for Gunicorn was set to app:__hug_wsgi__.

    I should mention that I do have the following in my .py file such that I can start it standalone:

    if __name__ == "__main__":
        hug.API(__name__).http.serve()
    

    Thanks.

    opened by exoosh 0
  • FYI: cgi module is deprecated in Python 3.11, will be removed in 3.13

    FYI: cgi module is deprecated in Python 3.11, will be removed in 3.13

    Source for the information: https://docs.python.org/3/library/cgi.html

    cgi — Common Gateway Interface support

    Source code: Lib/cgi.py

    Deprecated since version 3.11, will be removed in version 3.13: The cgi module is deprecated (see PEP 594 for details and alternatives).

    cgi.parse_multipart() is currently used in input_format.py, for example.

    As a side note, this use also causes issues if you are trying to upload several GiB of data through a POST. The documentation for the method says:

    This is easy to use but not much good if you are expecting megabytes to be uploaded — in that case, use the FieldStorage class instead which is much more flexible.

    For hug the best option seems to be to use email.message instead.

    opened by exoosh 0
  • Implementation bugs for exception catching!

    Implementation bugs for exception catching!

    https://github.com/hugapi/hug/blob/8b5ac00632543addfdcecc326d0475a685a0cba7/hug/interface.py#L941

    https://github.com/hugapi/hug/blob/8b5ac00632543addfdcecc326d0475a685a0cba7/hug/interface.py#L910

    https://github.com/hugapi/hug/blob/8b5ac00632543addfdcecc326d0475a685a0cba7/hug/interface.py#L273

    https://github.com/hugapi/hug/blob/8b5ac00632543addfdcecc326d0475a685a0cba7/hug/interface.py#L359

    https://github.com/hugapi/hug/blob/8b5ac00632543addfdcecc326d0475a685a0cba7/hug/interface.py#L363

    exception handler must trigger by bind exception raise and the handler func args(exception) type hints is bind exception

    initialize_handler re-instantiate the custom Exception and pass in the first kwargs(exception), which is actually an instance of the custom Exception.Step 5 above is equivalent to --> CustomException(CustomException()) This is a contradiction and a serious error. Excuse me, what was the purpose of designing this initialize_handler function at that time?

    reproduce:

    # bug.py
    import hug
    import time
    import hug.development_runner
    
    
    class UserError(Exception):
        code = 500
        message = "Invalid username"
    
        def __init__(self):
            ...
    
    
    api = hug.API(__name__)
    
    
    @hug.exception(UserError, api=api)
    def handler_user_error(request, response, exception: UserError):
        response.status = hug.falcon.HTTP_200
        data = dict(data=None, msg=exception.message, timestamp=time.time(), code=exception.code)
        response.body = hug.output_format.json(data)
    
    
    route = hug.http(api=api)
    
    
    @route.get("/test")
    def get_data(**kwargs):
        print("GET data")
        raise UserError()
    
    
    # run-bug-server.py
    import hug.development_runner
    hug.development_runner.hug("bug.py", port=5000)
    
    curl --location --request GET 'localhost:5000/test'
    {"errors": {"exception": "__init__() takes 1 positional argument but 2 were given"}}
    
    
    
    {
        "errors": {
            "exception": "__init__() takes 1 positional argument but 2 were given"
        }
    }
    
    
    opened by Panlq 0
Releases(2.6.0)
  • 2.6.0(Sep 14, 2019)

    2.6.0 - August 29, 2019

    • Improved CLI multiple behaviour with empty defaults
    • Improved CLI type output for built-in types
    • Improved MultiCLI base documentation
    Source code(tar.gz)
    Source code(zip)
  • 2.5.6(Jun 21, 2019)

    2.5.6 - June 20, 2019

    • Fixed issue #815: map_params() causes api documentation to lose param type information
    • Improved project testing: restoring 100% coverage
    Source code(tar.gz)
    Source code(zip)
  • 2.5.5(Jun 14, 2019)

    • Fixed issue #808: Problems with command line invocation via hug CLI
    • Fixed issue #647: Support for arbitrary URL complexity when using CORS middleware
    • Fixed issue #805: Added documentation for map_params feature
    • Added initial automated code cleaning and linting partially satisfying HOPE-8 -- Style Guideline for Hug
    • Implemented HOPE-20 -- The Zen of Hug
    Source code(tar.gz)
    Source code(zip)
  • 2.5.4(May 20, 2019)

  • 2.5.2(May 11, 2019)

    2.5.2 hotfix - May 10, 2019

    • Fixed issue #790 - Set Falcon defaults to pre 2.0.0 version to avoid breaking changes for Hug users until a Hug 3.0.0 release. The new default Falcon behaviour can be defaulted before hand by setting __hug__.future = True.
    Source code(tar.gz)
    Source code(zip)
  • 2.5.1(May 9, 2019)

    2.5.1 hotfix - May 9, 2019

    • Fixed issue #784 - POST requests broken on 2.5.0
    • Optimizations and simplification of async support, taking advantadge of Python3.4 deprecation.
    • Fix issue #785: Empty query params are not ignored on 2.5.0
    • Added support for modifying falcon API directly on startup
    • Initial black formatting of code base, in preperation for CI enforced code formatting
    Source code(tar.gz)
    Source code(zip)
  • 2.4.8(Apr 7, 2019)

    • Fixed issue #762 - HTTP errors crash with selectable output types
    • Fixed MacOS testing via Travis - added testing across all the same Python versions tested on Linux
    Source code(tar.gz)
    Source code(zip)
  • 2.4.7(Mar 28, 2019)

  • 2.4.6(Mar 26, 2019)

    2.4.6 - March 25, 2019

    • Fixed issue #753 - 404 not found does not respect default output format.
    • Documented the --without-cython option in CONTRIBUTING.md
    • Extended documentation for output formats
    Source code(tar.gz)
    Source code(zip)
  • 2.4.3(Mar 17, 2019)

  • 2.4.2(Mar 17, 2019)

    2.4.2 - March 16, 2019

    • Python 3.7 support improvements
    • No longer test against Python 3.4 - aimed for full deprecation in Hug 3.0.0
    • Improved interoperability with the latest Falcon release
    • Documentation improvements
    • Fixed bug in auto reload
    Source code(tar.gz)
    Source code(zip)
  • 2.4.1(Sep 18, 2018)

    • Fixed issue #631: Added support for Python 3.7
    • Fixed issue #665: Fixed problem with hug.types.json
    • Fixed issue #679: Return docs for marshmallow schema instead of for dump method
    Source code(tar.gz)
    Source code(zip)
  • 2.4.0(Sep 18, 2018)

    • Updated Falcon requirement to 1.4.1
    • Fixed issue #590: Textual output formats should have explicitly defined charsets by default
    • Fixed issue #596: Host argument for development runner
    • Fixed issue #563: Added middleware to handle CORS requests
    • Implemented issue #612: Add support for numpy types in JSON output by default
    • Implemented improved class based directives with cleanup support (see: https://github.com/timothycrosley/hug/pull/603)
    • Support ujson if installed
    • Implement issue #579: Allow silencing intro message when running hug from command line
    • Implemented issue #531: Allow exit value to alter status code for CLI tools
    • Updated documentation generation to use hug's JSON outputter for consistency
    Source code(tar.gz)
    Source code(zip)
Owner
Hug API Framework
Embrace the APIs of the future. Hug aims to make developing APIs as simple as possible, but no simpler.
Hug API Framework
Web APIs for Django. 🎸

Django REST framework Awesome web-browsable Web APIs. Full documentation for the project is available at https://www.django-rest-framework.org/. Fundi

Encode 24.7k Jan 4, 2023
Creating delicious APIs for Django apps since 2010.

django-tastypie Creating delicious APIs for Django apps since 2010. Currently in beta but being used actively in production on several sites. Requirem

null 3.8k Dec 30, 2022
Django Ninja is a web framework for building APIs with Django and Python 3.6+ type hints.

?? Fast, Async-ready, Openapi, type hints based framework for building APIs

Vitaliy Kucheryaviy 3.8k Jan 4, 2023
A small repository of projects built in my course, REST APIs with Flask and Python.

A small repository of projects built in my course, REST APIs with Flask and Python.

Teclado 1k Jan 5, 2023
RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

Microsoft 1.8k Jan 4, 2023
Scaffold django rest apis like a champion 🚀

scaffold django rest apis like a champion ??

Abdenasser Elidrissi 133 Jan 5, 2023
Document Web APIs made with Django Rest Framework

DRF Docs Document Web APIs made with Django Rest Framework. View Demo Contributors Wanted: Do you like this project? Using it? Let's make it better! S

Manos Konstantinidis 626 Nov 20, 2022
Sanic-RESTPlus is an extension for Sanic that adds support for quickly building REST APIs.

Sanic RestPlus Sanic-RESTPlus is an extension for Sanic that adds support for quickly building REST APIs. Sanic-RESTPlus encourages best practices wit

Ashley Sommer 106 Oct 14, 2022
simple api build with django rest framework

Django Rest API django-rest-framework Employees management simple API in this project wrote test suites for endpoints wrote simple doc string for clas

OMAR.A 1 Mar 31, 2022
Simple Crud Api With Django Rest Framework

SIMPLE CRUD API WITH DJANGO REST FRAMEWORK Django REST framework is a powerful and flexible toolkit for building Web APIs. Requirements Python 3.6 Dja

kibet hillary 1 May 3, 2022
A simple API example in Python (Flask framework)

API-Example A simple API in Python(Flask) ✨ Features An API i guess? ??‍♀️ How to use first download the main.py install python then install flask fra

Portgas D Ace 2 Jan 6, 2022
Eazytraining - Simple application to show how to query API from webapp

student-list Eazytraining - Simple application to show how to query API from webapp This repo is a simple application to list student with a webserver

⚡Christophe FREIJANES 2 Nov 15, 2021
Embrace the APIs of the future. Hug aims to make developing APIs as simple as possible, but no simpler.

Read Latest Documentation - Browse GitHub Code Repository hug aims to make developing Python driven APIs as simple as possible, but no simpler. As a r

Hug API Framework 6.7k Dec 27, 2022
A Raspberry Pi Pico powered Macro board, like a Streamdeck but cheaper and simpler.

Env-MCRO A Raspberry Pi Pico powered Macro board, like a Streamdeck but cheaper and simpler. (btw this image is a bit outdated, some of the silkscreen

EnviousData 68 Oct 14, 2022
Yoloxkeypointsegment - An anchor-free version of YOLO, with a simpler design but better performance

Introduction 关键点版本:已完成 全景分割版本:已完成 实例分割版本:已完成 YOLOX is an anchor-free version of

null 23 Oct 20, 2022
A community-driven python bot that aims to be as simple as possible to serve humans with their everyday tasks

JARVIS on Messenger Just A Rather Very Intelligent System, now on Messenger! Messenger is now used by 1.2 billion people every month. With the launch

Swapnil Agarwal 1.3k Jan 7, 2023
Autodrive is designed to make it as easy as possible to interact with the Google Drive and Sheets APIs via Python

Autodrive Autodrive is designed to make it as easy as possible to interact with the Google Drive and Sheets APIs via Python. It is especially designed

Chris Larabee 1 Oct 2, 2021
Real-ESRGAN aims at developing Practical Algorithms for General Image Restoration.

Real-ESRGAN Colab Demo for Real-ESRGAN . Portable Windows executable file. You can find more information here. Real-ESRGAN aims at developing Practica

Xintao 17.2k Jan 2, 2023
This is a repository to learn and get more computer vision skills, make robotics projects integrating the computer vision as a perception tool and create a lot of awesome advanced controllers for the robots of the future.

This is a repository to learn and get more computer vision skills, make robotics projects integrating the computer vision as a perception tool and create a lot of awesome advanced controllers for the robots of the future.

Elkin Javier Guerra Galeano 17 Nov 3, 2022