The comprehensive WSGI web application library.

Overview

Werkzeug

werkzeug German noun: "tool". Etymology: werk ("work"), zeug ("stuff")

Werkzeug is a comprehensive WSGI web application library. It began as a simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility libraries.

It includes:

  • An interactive debugger that allows inspecting stack traces and source code in the browser with an interactive interpreter for any frame in the stack.
  • A full-featured request object with objects to interact with headers, query args, form data, files, and cookies.
  • A response object that can wrap other WSGI applications and handle streaming data.
  • A routing system for matching URLs to endpoints and generating URLs for endpoints, with an extensible system for capturing variables from URLs.
  • HTTP utilities to handle entity tags, cache control, dates, user agents, cookies, files, and more.
  • A threaded WSGI server for use while developing applications locally.
  • A test client for simulating HTTP requests during testing without requiring running a server.

Werkzeug doesn't enforce any dependencies. It is up to the developer to choose a template engine, database adapter, and even how to handle requests. It can be used to build all sorts of end user applications such as blogs, wikis, or bulletin boards.

Flask wraps Werkzeug, using it to handle the details of WSGI while providing more structure and patterns for defining powerful applications.

Installing

Install and update using pip:

pip install -U Werkzeug

A Simple Example

from werkzeug.wrappers import Request, Response

@Request.application
def application(request):
    return Response('Hello, World!')

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4000, application)

Links

Comments
  • Werkzeug crashes after writing to closed pipe

    Werkzeug crashes after writing to closed pipe

    I have a Werkzeug server running behind NGINX. When a client disconnects while waiting for the Werkzeug server to respond, NGINX closes the pipe to Werkzeug. When the python program writes the response to Werkzeug, the following exception occurs and Werkzeug crashes:

    Traceback (most recent call last): File "server.py", line 81, in app.run(host=args.host, port=args.port, debug=False) File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 843, in run run_simple(host, port, self, **options) File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 694, in run_simple inner() File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 659, in inner srv.serve_forever() File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 499, in serve_forever HTTPServer.serve_forever(self) File "/usr/lib/python2.7/SocketServer.py", line 238, in serve_forever self._handle_request_noblock() File "/usr/lib/python2.7/SocketServer.py", line 297, in _handle_request_noblock self.handle_error(request, client_address) File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock self.process_request(request, client_address) File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request self.finish_request(request, client_address) File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request self.RequestHandlerClass(request, client_address, self) File "/usr/lib/python2.7/SocketServer.py", line 651, in init self.finish() File "/usr/lib/python2.7/SocketServer.py", line 710, in finish self.wfile.close() File "/usr/lib/python2.7/socket.py", line 279, in close self.flush() File "/usr/lib/python2.7/socket.py", line 303, in flush self._sock.sendall(view[write_offset:write_offset+buffer_size]) socket.error: [Errno 32] Broken pipe

    Is there some configuration option I'm missing to keep it from crashing? Normally all exceptions are caught and a 500 error returned, with the server remaining alive.

    opened by alexandres 41
  • Werkzeug stat reloader problems

    Werkzeug stat reloader problems

    So far two people have run into serious performance issues with the stat reloader. Anybody who has those, the fix is to install watchdog from pypi.

    If you're interested in fixing this issue, uninstall watchdog again and:

    • How does setting reloader_interval on werkzeug.run_simple or app.run affect performance? Try various values:

      app.run(reloader_interval=1)  # the default
      
    • Run this code inside your virtualenv, post the returned number:

      from werkzeug._reloader import _iter_module_files
      print(len(list(_iter_module_files())))
      
    bug 
    opened by untitaker 37
  • werkzeug.formparser is really slow with large binary uploads

    werkzeug.formparser is really slow with large binary uploads

    When I perform a multipart/form-data upload of any large binary file in Flask, those uploads are very easily CPU bound (with Python consuming 100% CPU) instead of I/O bound on any reasonably fast network connection.

    A little bit of CPU profiling reveals that almost all CPU time during these uploads is spent in werkzeug.formparser.MultiPartParser.parse_parts(). The reason this that the method parse_lines() yields a lot of very small chunks, sometimes even just single bytes:

    # we have something in the buffer from the last iteration.
    # this is usually a newline delimiter.
    if buf:
        yield _cont, buf
        buf = b''
    

    So parse_parts() goes through a lot of small iterations (more than 2 million for a 100 MB file) processing single "lines", always writing just very short chunks or even single bytes into the output stream. This adds a lot of overhead slowing down those whole process and making it CPU bound very quickly.

    A quick test shows that a speed-up is very easily possible by first collecting the data in a bytearray in parse_lines() and only yielding that data back into parse_parts() when self.buffer_size is exceeded. Something like this:

    buf = b''
    collect = bytearray()
    for line in iterator:
        if not line:
            self.fail('unexpected end of stream')
    
        if line[:2] == b'--':
            terminator = line.rstrip()
            if terminator in (next_part, last_part):
                # yield remaining collected data
                if collect:
                    yield _cont, collect
                break
    
        if transfer_encoding is not None:
            if transfer_encoding == 'base64':
                transfer_encoding = 'base64_codec'
            try:
                line = codecs.decode(line, transfer_encoding)
            except Exception:
                self.fail('could not decode transfer encoded chunk')
    
        # we have something in the buffer from the last iteration.
        # this is usually a newline delimiter.
        if buf:
            collect += buf
            buf = b''
    
        # If the line ends with windows CRLF we write everything except
        # the last two bytes.  In all other cases however we write
        # everything except the last byte.  If it was a newline, that's
        # fine, otherwise it does not matter because we will write it
        # the next iteration.  this ensures we do not write the
        # final newline into the stream.  That way we do not have to
        # truncate the stream.  However we do have to make sure that
        # if something else than a newline is in there we write it
        # out.
        if line[-2:] == b'\r\n':
            buf = b'\r\n'
            cutoff = -2
        else:
            buf = line[-1:]
            cutoff = -1
    
        collect += line[:cutoff]
    
        if len(collect) >= self.buffer_size:
            yield _cont, collect
            collect.clear()
    

    This change alone reduces the upload time for my 34 MB test file from 4200 ms to around 1100 ms over localhost on my machine, that's almost a 4X increase in performance. All tests are done on Windows (64-bit Python 3.4), I'm not sure if it's as much of a problem on Linux.

    It's still mostly CPU bound, so I'm sure there is even more potential for optimization. I think I'll look into it when I find a bit more time.

    bug 
    opened by sekrause 33
  • Switch locals to be based on ContextVars

    Switch locals to be based on ContextVars

    ContextVar was introduced in Python 3.7 and is effectively the same as Local in Werkzeug (although a different API). They should work in Greenlet and threading contexts as before but also now in asyncio or other async/await contexts.

    The __storage__ attribute has been kept for backwards compatibility (even though it is a dunder it seems it is used, e.g. in tests).

    The ident_func though must be deprecated as this is now handled by the ContextVar. This may cause some backwards incompatibility.

    opened by pgjones 32
  • Add uWSGI caching backend

    Add uWSGI caching backend

    Since version 1.9 uWSGI includes an in-memory cache. Documentation on that can be found at the uWSGI docs.

    This PR contains a new UwsgiCache class using uWSGI's uwsgi.cache_* functions.

    I'm not sure yet about a few things:

    1. testing; as import uwsgi only works when the app is actually run by uwsgi, writing tests with the actual uwsgi module is basically impossible to my knowledge. Does anyone have an idea on how this could be done?

    2. uWSGI also has cache_inc and cache_dec functions since 1.9.9, but they are not documented, so I'm a bit hesitant on adding them.

    3. Naming; is the convention here to use uWSGICache, or UwsgiCache?

    4. Documentation; because I check for the existance of the uwsgi module and only define the actual UwsgiCache class when it exists, sphinx's automodule does not pick up on the "real" UwsgiCache class. What's the best way of handling this?

    opened by jaapz 32
  • now works with 2to3, passes all the tests in py25-27,31,32

    now works with 2to3, passes all the tests in py25-27,31,32

    This branch enables Werkzeug to work with 2to3, passing all the tests in py25-27 and py31-32. (The Werkzeug's web page says it supports Python 2.4, but it depends on newer libraries like hashlib already, so I thought 2.5 would be fair.)

    Small incompatibilities that might affect Python 2 users:

    • MapAdapter.match() and MapAdapter.dispatch() now has separate arguments for path: path and path_info.
      • This is due to the newer WSGI standard for Python 3. the WSGI servers give environ['PATH_INFO'] to applications as bytestrings decoded in latin1 (hence unicode strings) . On the other hand, web applications, internally, would just use "strings" (which are also unicode strings) to pass around their path informations. So we use two kinds of (unicode) strings to specify web locations, one is in bytes-like representation and another one is a normal form. To distinguish them, we name them path_info and path respectively.
      • There should be no problem for average cases, since many codes (including tutorials) have used the library with path_info (in older sense) as a positional argument, and path_info (in newer sense) is almost used internally in Werkzeug codes only.
    • Some functions could be more grumpy about passing str and unicode to their arguments.
    opened by puzzlet 30
  • Hook for a setup function when using run_simple and autoreloader

    Hook for a setup function when using run_simple and autoreloader

    Hi,

    I want to be able to run some arbitrary code everytime the werkzeug reloader decides to reload my application such that if that code fails, all I have to do is change the code and it will auto reload and try it again.

    As far as I can tell, the nicest way to achieve this is to run that code before the make_server().serve_forever() call in the inner() function in run_simple.

    So, for example, add a setup_func argument to run_simple and call it in the inner() function.

    So, in werkzeug/serving.py

    def run_simple(hostname, port, application, setup_func=None, [..]):
        [..]
    
        def inner():
            if setup_func:
                setup_func()
            make_server(hostname, port, application, threaded,
                        processes, request_handler,
                        passthrough_errors, ssl_context).serve_forever()
    
        [..]
    
    opened by delfick 26
  • Change to cache expiration

    Change to cache expiration

    I made these changes in response to a stackoverflow question where a user wanted to be able to have a non expiring cache: http://stackoverflow.com/questions/29561011/how-to-disable-memcached-timeout-in-werkzeug

    In the process I also fixed a potential Redis bug that was highlighted in issue #550

    opened by lionbee 25
  • regex URL converter matches incorrect value

    regex URL converter matches incorrect value

    I have the following code in a Flask App using Werkzeug

    
    # Redirect requests for the older image URLs to new URLs
    @app.route(
        '/static/images/2019/<regex("(privacy|jamstack|capabilities)"):folder>/<image>'
    )
    def redirect_old_hero_images(folder, image):
        return redirect("/static/images/2020/%s/%s" % (folder, image)), 301
    

    prior to 2.2.0 this would allow the following redirect:

    /static/images/2019/jamstack/random.png
    

    to

    /static/images/2020/jamstack/random.png
    

    Now however it incorrectly sends us to:

    /static/images/2020/jamstack/jamstack
    

    Pinning werkzeug to 2.1.2 fixes the issue.

    Environment:

    • Python version: 3.8
    • Werkzeug version: 2.2.0 and 2.2.1
    docs routing 
    opened by tunetheweb 22
  • Version 1.0.0 removed previously deprecated code

    Version 1.0.0 removed previously deprecated code

    The 1.0.0 release that was pushed 2 hours ago published breaking changes for people using flask. Not sure if it was a desired effect and flask should pin their version or if changes in this project need to happen.

    opened by evanlurvey 22
  • Reloader doesn't add

    Reloader doesn't add ".exe" to file on Windows

    if I run a flask app under 0.15.5 with FLASK_ENV=development the dev server throws an error.

    With FLASK_ENV=production the server starts ok

    After reinstalling 0.15.4 the same app works ok (both in dev and prod mode).

    Windows/py3.6.7/pipenv

    Kind regards

    reloader 
    opened by peppobon 22
  • added support for io.BufferedIOBase

    added support for io.BufferedIOBase

    Added support for already open file when using send_file, there was missing a check for io.BufferedIOBase to correctly set the attribute size. This will enable support for request 'Range' headers and correct response headers with 'Accept-Ranges' and 'Content-Range'

    • fixes #2566

    This is my first pull request, so a bit unsure about the unchecked in below checklist.

    Checklist:

    • [x] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
    • [x] Add or update relevant docs, in the docs folder and in code.
    • [ ] Add an entry in CHANGES.rst summarizing the change and linking to the issue.
    • [ ] Add .. versionchanged:: entries in any relevant code docs.
    • [x] Run pre-commit hooks and fix any issues.
    • [x] Run pytest and tox, no tests failed.
    opened by kwismann 0
  • send_file should support range request with io.BufferedReader

    send_file should support range request with io.BufferedReader

    When using send_file, passing an open file path as io.BufferedReader, range headers are not supported. Do you see this as a possible feature?

    Using below code, will show Range request in the http header is ignored:

    file = open(filename, "rb")
    return send_file(file, download_name=filename, as_attachment=True)
    

    This is due to the below code. https://github.com/pallets/werkzeug/blob/3115aa6a6276939f5fd6efa46282e0256ff21f1a/src/werkzeug/utils.py#L428-L444

    When size is not set (line 441) the following line 504, rv.content_length, is skipped and range is not reported back to the browser as being supported and the complete file is send https://github.com/pallets/werkzeug/blob/3115aa6a6276939f5fd6efa46282e0256ff21f1a/src/werkzeug/utils.py#L503-L504

    My suggestion would be to add something like this:

            stat = os.stat(path)
            size = stat.st_size
            mtime = stat.st_mtime
        else:
            file = path_or_file
            stat = os.fstat(file.fileno())
            size = stat.st_size
            mtime = stat.st_mtime
    

    I have done some testing with above code and it seems to work fine. NB! This is obviously not a complete test and the added code would need to be refactored properly into utils.py.

    Environment:

    • Python version: 3.8.10
    • Werkzeug version: 2.1.2
    opened by kwismann 1
  • reloader exlude_patterns behavior differs for WatchdogReloaderLoop and StatReloaderLoop

    reloader exlude_patterns behavior differs for WatchdogReloaderLoop and StatReloaderLoop

    Setting exclude_patterns to an absolute path, e.g. /home/me/bar/*, works fine with StatReloaderLoop, and fails to exclude paths with WatchdogReloaderLoop. The root cause is that WatchdogReloaderLoop uses watchdog which relies on pathlib.PurePath.match and StatReloaderLoop relies on `fnmatch. Here's a simple demonstration:

    import fnmatch
    assert fnmatch.fnmatch("/foo/bar/baz", "/foo/*")
    
    import pathlib
    assert pathlib.PurePosixPath("/foo/bar/baz").match("/foo/*"), "FAIL"
    

    Pathlib's behavior is too strict for this particularly problem, since it matches from the right for relative paths and exact matches for absolute paths. fnmatch finds first match from the left.

    The workaround is to disable the watchdog by passing reloader_type="stat" to run_simple.

    Environment:

    • Python version: 3.7.2
    • Werkzeug version: 2.0.3
    opened by robnagler 0
  • fix LimitedStream.read method to work with raw IO streams

    fix LimitedStream.read method to work with raw IO streams

    This PR adds a test and fix for LimitedStream to work with raw IO streams. Raw IO streams can return fewer bytes than passed to size in a read call, and previously LimitedStream.read was not equipped to handle these cases. I had to

    • add a method to deal with cases where LimitedStream.read(-1) is called, that would exhaust the remainder of the stream and actually return the result. It uses a common "read into buffer" pattern.
    • change the condition on what the read method considers as a client disconnect. The added tests should clarify further what is considered a disconnect and what isn't.
    • fixes #2558

    Checklist:

    • [X] Add tests that demonstrate the correct behavior of the change. Tests should fail without the change.
    • [X] Add or update relevant docs, in the docs folder and in code.
    • [ ] Add an entry in CHANGES.rst summarizing the change and linking to the issue.
    • [ ] Add .. versionchanged:: entries in any relevant code docs.
    • [X] Run pre-commit hooks and fix any issues.
    • [ ] Run pytest and tox, no tests failed.
    opened by thrau 1
  • LimitedStream not respecting `read` contract of RawIOBase.

    LimitedStream not respecting `read` contract of RawIOBase.

    In the read implementation of LimitedStream, self._read refers to a read method of an underlying RawIOBase stream, and is called here: https://github.com/pallets/werkzeug/blob/3115aa6a6276939f5fd6efa46282e0256ff21f1a/src/werkzeug/wsgi.py#L957-L963

    According to the contract of RawIOBase, read can return fewer bytes than passed in the size argument:

    Fewer than size bytes may be returned if the operating system call returns fewer than size bytes.

    This does not however mean that the underlying stream won't return more bytes when read is called again (size is an upper bound). Raising an error on the condition in line 962if to_read and len(read) != to_read breaks the contract of IO.read.

    To add some context: This is a pretty significant problem for our server implementation in LocalStack that builds on Hypercorn, where we expose an ASGIReceiveCallable as a readable stream and plug it into Werkzeug. Our stream behaves according to IO.read, but Werkzeug will raise unexpected ClientDisconnect errors, even though there is still data in the stream.

    It seems that the condition could be safely removed, or at least weakened to if to_read and not len(read), which would indicate an unexpected EOF.

    Environment:

    • Python version: 3.10
    • Werkzeug version: 2.2.2, but the code has been affected for a while: https://github.com/pallets/werkzeug/commit/b677ecc9e089a2251f800d9ff26548eb3040d884
    opened by thrau 0
  • The existing means of obtaining docker container IDs no longer valid

    The existing means of obtaining docker container IDs no longer valid

    The default use of cgroups v2 in new kernels and new versions of docker makes the existing means of obtaining container IDs no longer valid

    /proc/self/cgoups now in my docker container:

    [email protected]:/proc/self# cat /proc/self/cgroup 
    0::/
    [email protected]:/proc/self# 
    
    opened by mrjesen 0
Releases(2.2.2)
  • 2.2.2(Aug 8, 2022)

    This is a fix release for the 2.2.0 feature release.

    • Changes: https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-2-2
    • Milestone: https://github.com/pallets/werkzeug/milestone/25?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.2.1(Jul 27, 2022)

    This is a fix release for the 2.2.0 feature release.

    • Changes: https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-2-1
    • Milestone: https://github.com/pallets/werkzeug/milestone/24?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.2.0(Jul 23, 2022)

    This is a feature release, which includes new features and removes previously deprecated features. The 2.2.x branch is now the supported bugfix branch, the 2.1.x branch will become a tag marking the end of support for that branch. We encourage everyone to upgrade, and to use a tool such as pip-tools to pin all dependencies and control upgrades.

    • Changes: https://werkzeug.palletsprojects.com/en/2.2.x/changes/#version-2-2-0
    • Milestone: https://github.com/pallets/werkzeug/milestone/20?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.1.2(Apr 28, 2022)

    This is a fix release for the 2.1.0 feature release.

    • Changes: https://werkzeug.palletsprojects.com/en/2.1.x/changes/#version-2-1-2
    • Milestone: https://github.com/pallets/werkzeug/milestone/22?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.1.1(Apr 1, 2022)

    This is a fix release for the 2.1.0 feature release.

    • Changes: https://werkzeug.palletsprojects.com/en/2.1.x/changes/#version-2-1-1
    • Milestone: https://github.com/pallets/werkzeug/milestone/19?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.1.0(Mar 28, 2022)

    This is a feature release, which includes new features and removes previously deprecated features. The 2.1.x branch is now the supported bugfix branch, the 2.0.x branch will become a tag marking the end of support for that branch. We encourage everyone to upgrade, and to use a tool such as pip-tools to pin all dependencies and control upgrades.

    • Changes: https://werkzeug.palletsprojects.com/en/2.1.x/changes/#version-2-1-0
    • Milestone: https://github.com/pallets/werkzeug/milestone/16?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.0.3(Feb 7, 2022)

    • Changes: https://werkzeug.palletsprojects.com/en/2.0.x/changes/#version-2-0-3
    • Milestone: https://github.com/pallets/werkzeug/milestone/18?closed=1
    Source code(tar.gz)
    Source code(zip)
  • 2.0.2(Oct 6, 2021)

  • 2.0.1(May 17, 2021)

  • 2.0.0(May 12, 2021)

    New major versions of all the core Pallets libraries, including Werkzeug 2.0, have been released! :tada:

    • Read the announcement on our blog: https://palletsprojects.com/blog/flask-2-0-released/
    • Read the full list of changes: https://werkzeug.palletsprojects.com/changes/#version-2-0-0
    • Retweet the announcement on Twitter: https://twitter.com/PalletsTeam/status/1392266507296514048
    • Follow our blog, Twitter, or GitHub to see future announcements.

    This represents a significant amount of work, and there are quite a few changes. Be sure to carefully read the changelog, and use tools such as pip-compile and Dependabot to pin your dependencies and control your updates.

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0rc5(May 3, 2021)

  • 2.0.0rc4(Apr 16, 2021)

  • 2.0.0rc3(Mar 17, 2021)

    • Changes: https://werkzeug.palletsprojects.com/en/master/changes/#version-2-0-0

    Use the --pre flag to install this pre-release:

    pip install --pre Werkzeug==2.0.0rc3
    
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0rc2(Mar 3, 2021)

    • Changes: https://werkzeug.palletsprojects.com/en/master/changes/#version-2-0-0

    Use the --pre flag to install this pre-release:

    pip install --pre Werkzeug==2.0.0rc2
    
    Source code(tar.gz)
    Source code(zip)
  • 2.0.0rc1(Feb 9, 2021)

    • Changes: https://werkzeug.palletsprojects.com/en/master/changes/#version-2-0-0

    Use the --pre flag to install this pre-release:

    pip install --pre Werkzeug==2.0.0rc1
    
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Mar 31, 2020)

  • 1.0.0(Mar 31, 2020)

    After 13 years of development, we're finally 1.0!

    Note that previously deprecated code has been removed in this release. Use 0.16.1 as an intermediate step to see deprecation warnings and upgrade.

    • Blog: https://palletsprojects.com/blog/werkzeug-1-0-0-released
    • Changelog: https://werkzeug.palletsprojects.com/en/1.0.x/changes/#version-1-0-0
    • Twitter: https://twitter.com/PalletsTeam/status/1225561504004689920
    Source code(tar.gz)
    Source code(zip)
  • 1.0.0rc1(Jan 31, 2020)

    • Changes: https://werkzeug.palletsprojects.com/en/master/changes/#version-1-0-0

    Use the --pre flag to install this pre-release:

    pip install --pre Werkzeug==1.0.0rc1
    
    Source code(tar.gz)
    Source code(zip)
  • 0.16.1(Jan 27, 2020)

  • 0.16.0(Sep 19, 2019)

    Most of the top-level attributes in the werkzeug module are now deprecated, and will be removed in 1.0.0.

    For example, instead of import werkzeug; werkzeug.url_quote, do from werkzeug.urls import url_quote. A deprecation warning will show the correct import to use. werkzeug.exceptions and werkzeug.routing should also be imported instead of accessed, but for technical reasons can’t show a warning.

    • Blog: https://palletsprojects.com/blog/werkzeug-0-16-0-released
    • Changelog: https://werkzeug.palletsprojects.com/en/0.16.x/changes/#version-0-16-0
    Source code(tar.gz)
    Source code(zip)
  • 0.15.6(Sep 4, 2019)

    The issue causing the reloader to fail when running from a setuptools entry point (like flask run) on Windows has been fixed.

    • Changelog: http://werkzeug.palletsprojects.com/en/0.15.x/changes/#version-0-15-6
    Source code(tar.gz)
    Source code(zip)
  • 0.15.5(Jul 17, 2019)

  • 0.15.4(May 15, 2019)

    • Blog: https://palletsprojects.com/blog/werkzeug-0-15-3-released/
    • Changes: https://werkzeug.palletsprojects.com/en/0.15.x/changes/#version-0-15-4
    Source code(tar.gz)
    Source code(zip)
  • 0.15.3(May 15, 2019)

    • Blog: https://palletsprojects.com/blog/werkzeug-0-15-3-released/
    • Changes: https://werkzeug.palletsprojects.com/en/0.15.x/changes/#version-0-15-3
    Source code(tar.gz)
    Source code(zip)
  • 0.15.2(Apr 2, 2019)

    • Blog: https://palletsprojects.com/blog/werkzeug-0-15-2-released/
    • Changes: https://werkzeug.palletsprojects.com/en/0.15.x/changes/#version-0-15-2
    Source code(tar.gz)
    Source code(zip)
  • 0.15.1(Mar 21, 2019)

  • 0.15.0(Mar 19, 2019)

The Web framework for perfectionists with deadlines.

Django Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Thanks for checking it out. All docu

Django 67.9k Dec 29, 2022
Lemon is an async and lightweight API framework for python

Lemon is an async and lightweight API framework for python . Inspired by Koa and Sanic .

Joway 29 Nov 20, 2022
Pulumi-checkly - Checkly Pulumi Provider With Python

🚨 This project is still in very early stages and is not stable, use at your own

Checkly 16 Dec 15, 2022
Bromelia-hss implements an HSS by using the Python micro framework Bromélia.

Bromélia HSS bromelia-hss is the second official implementation of a Diameter-based protocol application by using the Python micro framework Bromélia.

henriquemr 7 Nov 02, 2022
aiohttp-ratelimiter is a rate limiter for the aiohttp.web framework.

aiohttp-ratelimiter aiohttp-ratelimiter is a rate limiter for the aiohttp.web fr

JGL Technologies 4 Dec 11, 2022
Bablyon 🐍 A small ASGI web framework

A small ASGI web framework that you can make asynchronous web applications using uvicorn with using few lines of code

xArty 8 Dec 07, 2021
Light, Flexible and Extensible ASGI API framework

Starlite Starlite is a light, opinionated and flexible ASGI API framework built on top of pydantic and Starlette. Check out the Starlite documentation

Na'aman Hirschfeld 1.6k Jan 09, 2023
A simple todo app using flask and sqlachemy

TODO app This is a simple TODO app made using Flask. Packages used: DoodleCSS Special thanks to Chris McCormick (@mccrmx) :) Flask Flask-SQLAlchemy Fl

Lenin 1 Dec 26, 2021
Sierra is a lightweight Python framework for building and integrating web applications

A lightweight Python framework for building and Integrating Web Applications. Sierra is a Python3 library for building and integrating web applications with HTML and CSS using simple enough syntax. Y

83 Sep 23, 2022
A proof-of-concept CherryPy inspired Python micro framework

Varmkorv Varmkorv is a CherryPy inspired micro framework using Werkzeug. This is just a proof of concept. You are free to use it if you like, or find

Magnus Karlsson 1 Nov 22, 2021
Free & open source Rest API for YTDislike

RestAPI Free & open source Rest API for YTDislike, read docs.ytdislike.com for implementing. Todo Add websockets Installation Git clone git clone http

1 Nov 25, 2021
A familiar HTTP Service Framework for Python.

Responder: a familiar HTTP Service Framework for Python Powered by Starlette. That async declaration is optional. View documentation. This gets you a

Taoufik 3.6k Dec 27, 2022
A shopping list and kitchen inventory management app.

Flask React Project This is the backend for the Flask React project. Getting started Clone this repository (only this branch) git clone https://github

11 Jun 03, 2022
Full duplex RESTful API for your asyncio web apps

TBone TBone makes it easy to develop full-duplex RESTful APIs on top of your asyncio web application or webservice. It uses a nonblocking asynchronous

TBone Framework 37 Aug 07, 2022
The Modern And Developer Centric Python Web Framework. Be sure to read the documentation and join the Slack channel questions: http://slack.masoniteproject.com

NOTE: Masonite 2.3 is no longer compatible with the masonite-cli tool. Please uninstall that by running pip uninstall masonite-cli. If you do not unin

Masonite 1.9k Jan 04, 2023
An easy-to-use high-performance asynchronous web framework.

An easy-to-use high-performance asynchronous web framework.

Aber 264 Dec 31, 2022
Trame let you weave various components and technologies into a Web Application solely written in Python.

Trame Trame aims to be a framework for building interactive applications using a web front-end in plain Python. Such applications can be used locally

Kitware, Inc. 85 Dec 29, 2022
The lightning-fast ASGI server. ?

The lightning-fast ASGI server. Documentation: https://www.uvicorn.org Community: https://discuss.encode.io/c/uvicorn Requirements: Python 3.6+ (For P

Encode 6k Jan 03, 2023
easyopt is a super simple yet super powerful optuna-based Hyperparameters Optimization Framework that requires no coding.

easyopt is a super simple yet super powerful optuna-based Hyperparameters Optimization Framework that requires no coding.

Federico Galatolo 9 Feb 04, 2022
Fast⚡, simple and light💡weight ASGI micro🔬 web🌏-framework for Python🐍.

NanoASGI Asynchronous Python Web Framework NanoASGI is a fast ⚡ , simple and light 💡 weight ASGI micro 🔬 web 🌏 -framework for Python 🐍 . It is dis

Kavindu Santhusa 8 Jun 16, 2022