
New Python REST API and CLI micro-framework - dragonsh
https://github.com/timothycrosley/hug
======
timothycrosley
Author here: I encourage anyone that is curious about the reason for this
framework as opposed to X to read the project's architecture document
[https://github.com/timothycrosley/hug/blob/develop/ARCHITECT...](https://github.com/timothycrosley/hug/blob/develop/ARCHITECTURE.md#the-
guiding-thought-behind-the-architecture). Some highlights: it allows some of
the most concise Python code, produces automatic documentation, supports
annotation based validation and argument transformation, automatically enables
version management, and is way faster then Flask / Django at handling
requests. Also, I'm free to answer any questions you may have :)

~~~
seabrookmx
> produces automatic documentation, supports annotation based validation and
> argument transformation

These aren't new, though the approach to them seems quite clean.

> automatically enables version management

There's syntax sugar in the decorators for supporting versioned api's, sure..
but you still need separate functions for each version. I think the wording
oversells the feature a bit.

> and is way faster then Flask / Django at handling requests

In what configuration? Pretty much anything is faster than Flask's included
development server. Is it faster than Flask configured with nginx over wsgi?
If so, how much faster? The best way to convince people of this is to not only
post benchmark results, but also commit the benchmarks themselves so people
can run them.

Project looks neat but Flask is well though out, well supported, has amazing
documentation, and supports both Python 2.x and 3.x.. which leaves little
reason to switch (with the exception of the CLI interface.. which I can't deny
is pretty darn cool).

~~~
timothycrosley
You can see the performance difference bench-marked by a competing framework
non the less, here: [http://pycnic.nullism.com/](http://pycnic.nullism.com/)
These are done running a standard uwsgi setup for all frameworks (even playing
ground).

> These aren't new, though the approach to them seems quite clean.

This is really the crux of it, nothing is new. That is before Flask etc you
could do everything you can do with Flask now, but the approach was bad and
not clean. Required a lot of duplication of work. Flask helped fix that. You
can do the hug enables through flask now, but the approach isn't clean, they
require a lot of duplication of work. Hug fixes that.

The same reasons people started using Flask are the same reasons they should
start using hug. It provides a cleaner, faster, and better base for the APIs
of the future - just like Flask did when it came along.

~~~
ergo14
I would be interested to see the benchmarks against Pyramid, because it tries
to be really minimal while at same time it is very friendly and flexible if
you want to write REST API's with it.

~~~
zbyte64
Pyramid is included in the benchmarks linked to. Hug is faster then pyramid
but slower then falcon.

------
nathancahill
Neat, but it's almost like Flask/bottle. Wouldn't some of the unique features
be better implemented on top of a well established microframework?

The API versioning bit is interesting, it would work well as a Flask
decorator.

~~~
timothycrosley
author here: This is way more then Flask/Bottle, I understand what would make
you reach that conclusion, but if you look here
[https://github.com/timothycrosley/hug/blob/develop/ARCHITECT...](https://github.com/timothycrosley/hug/blob/develop/ARCHITECTURE.md#the-
guiding-thought-behind-the-architecture) You can see just how much it adds
that really are core concepts that can't be done with simple decorators on-top
of Flask.

Highlights:

\- Automatic documentation \- Type annotation based validation and
transformation of input fields \- Directives to inject more data (like request
data) into existing functions in a safe and reusable way \- It's easily twice
as fast at handling requests as Flask, making Flask a rather horrible base for
any competitor

~~~
gsibble
I would argue that it handles requests twice as fast because it contains about
half as many features. And I've added automatic documentation to many of my
flask projects. Not knocking on your excellent project, just suggesting you
stop knocking on Flask, which is an excellent wsgi server.

~~~
timothycrosley
Hug contains the features flask contains. I haven't and I don't think you will
in this entire thread see a single example of someone actually pointing a
feature missing in hug that is relevant for APIs (not HTML websites like
Jinja)

------
austinjp
This looks very interesting, thanks for posting. I love the simplicity of
adding the CLI, versioning, and web API.

@timothycrosley, if you're still monitoring this thread... :) ... a handful of
questions:

Is HUG "production ready"? Could or should I use this to power a service with
thousands of paying users? Is anyone currently doing this?

Is HUG likely to be around in a couple of years? I'm sure we all _hope_ that
it will be :) I guess I'm curious about how much time and resources you can
dedicate to this.

Perhaps in summary I should just ask: why wouldn't developers just use Django,
for example? While Django may be comparatively complex it also brings a degree
of confidence, being "battle hardened" and having a recent cash injection from
Mozilla. (I'm sure other frameworks may have similar boasts.)

I appreciate that these questions might be seen as cynical or snarky --
they're not intended to be, I'm genuinely curious. There's a huge amount of
frameworks churn at the moment. It seems like a precarious area to be
launching a product, and some confidence-boosting info regarding longevity and
production-suitability would be greatly appreciated.

~~~
timothycrosley
Hi @austinjp,

I would be more then happy to answer your questions!

1) Is HUG "production ready?": YES! Several large companies have emailed me or
chatted with the community for support for their already in production APIs.
Based on my communications for instance, I know for a fact that one API hosted
with hug is leveraged by at least 10 fortune 100 companies.

2) I have several projects, that I continue to support like isort which are
several years old. I don't abondon projects, and hug is already at the point
where it isn't _my_ project but a community project which has upwards of 16
contributors already.

The real reason to use hug instead of Django is because your code and
therefore your liability and maintance cost will be drastically lower. In
every example where I've ported or seen an API ported it's been upwards of 90%
code reduction. In several cases even _if_ hug just all the sudden went away,
your cost for maintaining hug itself would still be smaller then using code
developed on-top of Django. It's a major enough improvement not to be able to
be ignored.

Thanks!

~Timothy

~~~
austinjp
Hi Timothy, reply much appreciated -- sounds good.

------
peletiah
Hmm, does it offer anything over Pyramid/Cornice? Pyramid is also quick and
easy to start (i.e. "Micro") and allows to extend a project to a full
featureset when necessary (Auth, Routing, Model,...).

edit: Sorry I don't add anything more constructive to the discussion. Hope
author does not feel discouraged, writing OSS and then getting asked "What's
the point?" sure is disheartening.

------
Phemist
Thanks! This looks great, will definitely try it out.

One question, what would be the recommended way to define complex data types?
E.g.

    
    
        def stuff(arg1: int, arg2: dict):
            return 'Ok'
    

where arg2 would be a dictionary that should contain specific, predefined
fields? This might also instead be a general question about Python type
hinting

~~~
BrandonHoffman
I'm a contributor to the hug project.

we are currently working on a way of doing this which should be released to
the development version this week and will be released with version 2.0

basically the modification would allow you to create a new type which has
multiple predefined fields. like so:

    
    
        class User(Type):
            username = Chain(text, LongerThan(10))
            password = Chain(text, LongerThan(10))
    

After creating this type you could then use it as a type as normal

    
    
        def stuff(arg1: int, arg2: User):
            return 'Ok'

~~~
kstrauser
May I make a suggestion? Please, _PLEASE_ use a standardized Python modeling
tool like Schematics, Marshmallow, etc. as your description language. Then
your users can use the same models for their REST framework as for their ORM
and everything else.

I'm begging: please do not reinvent this. Just don't.

~~~
timothycrosley
kstrauser: Hug supports marshmallow! Right now, you can use Marshmallow types
out of the box for any API call just set the Marshmallow type as the type
after the annotation and it will work and validate as expected :)

~~~
kstrauser
Excellent, thanks!

------
mixmastamyk
Nice work, I'll have to investigate this as opposed to standard Falcon.

This is generally discouraged, I would change these in the readme:

    
    
        .format(**locals())

~~~
matheist
Interesting; I hadn't seen that before, and as soon as I saw it I thought "ooh
shiny!". Is there a quick reason why I shouldn't use it?

~~~
mixmastamyk
It isn't forbidden, just that it might leak information, doesn't perform well,
and is unsightly. Py 3.6 should have the syntax to simplify, without
locals/globals:

    
    
        f'Hello, {name} {age}'

~~~
dagss
As for leaking info, your Py3.6 example leaks exactly as much (i.e., what is
referenced in the literal). In fact you could consider it syntactic sugar for
the __locals() (although faster I guess).

~~~
jonathan_s
Yes, but it's unsafe for another reason. The new syntax can be verified
statically by tools like Pylint. A call to locals() is hard to verify.

The locals() function itself could for instance have been replaced by
something else. When using locals(), you won't know until execution time if a
local variable, required for the interpolation is missing. Even worse, linter
tools (pylint, pyflakes, jedi, ...) are now going to tell you that certain
variables are not used, and people are going to remove it without thinking
that somewhere a locals() call is going to use it. This is very bad. Actually,
the effects of using locals() cannot be verified statically, even more because
locals() is also a writable dict.

For f-strings, the name bindings are static, and editors are going to
understand it while editing.

~~~
stdbrouw
> This is very bad.

There's no need for hyperbole. The fact that `locals()` doesn't work well with
linters is a bummer, but compared to a multitude of other code smells it's
pretty mild and harmless.

------
w_t_payne
I really like the fact that it allows the program logic to be exposed as
Python, CLI & Web API in one fell swoop.

It makes me think about what other interfaces could be automagically created
at the same time -- C? Simulink?

------
squiguy7
At a quick glance, this reminds me of bottle. The fact that it uses falcon as
a basis for the engine is great too. I get the feeling that you could write up
an API with this in a day and it would perform well.

~~~
pekk
Then show us the data. Feelings don't count for much.

~~~
guscost
Practical programming is still a craft, not a science. Feelings often count
enough to mention.

------
NamTaf
I used web.py to do a similar process about 1.5 years ago. In that, I mapped
the GET and POST elements to functions which then did whatever I needed them
to do.

This makes it even easier and I see it having a good fit in hacking up PoC
APIs. In my case, I was querying some databases and aggregating data for
display in a web page as well as via XML/JSON in a RESTful interface. This
would make the XML/JSON stuff very easy indeed.

------
gifenvy
Honestly I'm mosts impressed that the example gif is only ~480kb despite being
high quality and pretty long! How did you do that, author?

~~~
kseistrup
Asciinema could also be a useful way to present the example.

[https://asciinema.org/](https://asciinema.org/)

~~~
RussianCow
It wouldn't be useful in this particular case because you wouldn't actually
get to see the browser window (I guess you could curl it or something). But
this is a really neat tool, I'll definitely be using it. Thanks for sharing!

------
leehro
Looks nice. I loved the README - good concise examples that illustrate why
each piece is there.

------
cjauvin
While browsing his other repos, I found this tool by the same author, which is
also really great:

[https://github.com/timothycrosley/isort](https://github.com/timothycrosley/isort)

(Emacs integration works very well!)

------
leetrout
This looks neat. I like the 404 handler showing a spec!

The title confused me as I expected something to help me write a CLI app... If
anyone else was thinking that way I highly recommend looking at pyinvoke.org
or Argh.

~~~
timothycrosley
author: Hug actually does make it super easy to write a CLI app, you can see
an example here:
[https://github.com/timothycrosley/hug/blob/develop/examples/...](https://github.com/timothycrosley/hug/blob/develop/examples/cli.py)
and a full explanation of the concept here:
[https://github.com/timothycrosley/hug/blob/develop/ARCHITECT...](https://github.com/timothycrosley/hug/blob/develop/ARCHITECTURE.md#the-
guiding-thought-behind-the-architecture)

------
jdnier
So how would I use Hug as a secure public API -- https, authentication,
authorization? Would I read up on Falcon? Are there any examples you could
point to of how that might be done?

~~~
timothycrosley
[https://github.com/timothycrosley/hug/blob/develop/examples/...](https://github.com/timothycrosley/hug/blob/develop/examples/authentication.py)

~~~
raarts
Is there a https example? Personally I think all examples online should use
ssl by default these days. http should be banned altogether.

~~~
timothycrosley
That's not how things work when using _any_ WSGI based framework, the SSL part
should be handled by either uwsgi / gunicorn or nginx. Development servers
(hug or Flask or any other) should basically never be used directly. Examples
can, and _should_ be done using HTTP to allow local testing.

------
timeu
That looks really cool ! I actually started to use Falcon for a relatively
simple REST only backend (for a py3 project). This might make my life a bit
easier.

------
ipsum2
If it uses Falcon under the hood, why not just use Falcon?

~~~
timothycrosley
It has a way simpler programming interface then Falcon while retaining the
speed benefits: and is really a way more powerful concept as explained here:
[https://github.com/timothycrosley/hug/blob/develop/ARCHITECT...](https://github.com/timothycrosley/hug/blob/develop/ARCHITECTURE.md#the-
guiding-thought-behind-the-architecture)

The real question should be, why take the time to write Falcon when you can
get the same performance and more code-reuse using hug?

~~~
mixmastamyk
Perhaps they will like your simplifications, and could merge them.

~~~
timothycrosley
They really aren't compatible concepts. It's sort of like the difference
between werkzeug and Flask, those projects wouldn't and shouldn't ever be
merged. Falcon is like a much faster werkzeug with a great maintainer, we've
discussed the projects together and both agree that they both should remain
separate and both are mutually beneficial.

------
wantreprenr007
Neat. Swagger and HAL support make APIs easier to digest

------
zbyte64
Reminds me of all the good stuff I liked from node's restify. I've used allot
of python api frameworks and I definitely like the direction.

------
vaulstein
Can we have a benchmarking post done? Flask, Bottle, Django and maybe even
Falcon([http://falconframework.org/](http://falconframework.org/)) ?

------
dwightgunning
Congrats on shipping and taking the time to post and answer questions here.

Looks like a nice step forward. I am looking forward to trying this out!

------
jack_jennings
How could you not like this with that mascot?

------
chowes
How does this help development of a REST API? Seems more like a webserver

------
DannoHung
I didn't know Python 3 supported some of the syntax in use here.

------
akoumjian
Looks mildly inspired by itty!

------
benatkin
I was hoping it would be Pythonic, but it has a "directive" feature which
appears to be an ad hoc extension of the python language.

~~~
rspeer
Are you referring to decorators? Those have been around since Python 2.4, and
have been used for this kind of purpose for over a decade.

