web.py is a web framework for python that is as simple as it is powerful.

Related tags

Web Frameworks webpy
Overview

web.py is a web framework for Python that is as simple as it is powerful.

Visit http://webpy.org/ for more information.

build status Codecov Test Coverage

The latest stable release 0.62 only supports Python >= 3.5. To install it, please run:

# For Python 3
python3 -m pip install web.py==0.62

If you are still using Python 2.7, then please use web.py version 0.51 which is intended to be our last release that supports Python 2.

# For Python 2.7
python2 -m pip install web.py==0.51

You can also download it from GitHub Releases page, then install it manually:

unzip webpy-0.62.zip
cd webpy-0.62/
python3 setup.py install

Note: 0.5x (e.g. 0.50, 0.51) are our last releases which support Python 2. Note: 0.6x (e.g. 0.60, 0.61, 0.62) are our last releases which support Python 3.5.

Issues
  • When should we make the next release to PyPI?

    When should we make the next release to PyPI?

    https://pypi.org/project/web.py#history The last production release to PyPI was made in February 2018 and it does not fully support Python 3. Given that the current code in this repo does support Python 3 and given that Python 2 end of life is in 110 days, it seems like a good time for us to make a new production release to PyPI so that projects that depend on web.py can use a production release.

    1. Are there any objections to making such a release?
    2. Are there any open issues or PRs that are showstoppers to making such a release?
    3. Do we have a documented process for how to make a release to PyPI?
    4. Do we have the access rights (logins, passwords, certs, etc.) to make are release to PyPI?
    py3 
    opened by cclauss 34
  • Release version 0.61

    Release version 0.61

    setup.py: Add python_requires='>=3.5'

    This prevents installation on legacy Python and other versions < Python 3.5 as discussed in https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires

    Tasks for making a new release.

    • [x] Reread Packaging Python Projects to make sure you miss no steps...
    • [x] Bump the version in web/__init__.py
    • [x] Update ChangeLog.txt and mark the release date in ChangeLog.txt
    • [x] Check setup.py and update if necessary
    • [x] Check README.md and update if necessary
    • [x] Check MANIFEST.in and update if necessary #628
    • [x] Tag the version and mark it as a release in GitHub
    • [x] python3 -m pip install --upgrade pip setuptools wheel # Important for PyPI page rendering
    • [x] Run python3 setup.py sdist under webpy source code directory to generate package file used to publish to PyPI
    • [x] Run tar tf dist/web.py-<version>.tar.gz to make sure all required files are included.
    • [x] Publish package on PyPI with command python3 setup.py sdist upload
    • [x] Update the documentation on the website (see webpy.github.com repo) webpy/webpy.github.com#137
    • [ ] Announce it on the mailing list
    • [x] Update the API docs if required (not required)
    opened by cclauss 31
  • No module named `flup.server.fcgi`

    No module named `flup.server.fcgi`

    I am trying to run this old code and there is an error coming from the depths of 0.51 web.py

    ✗ python index.py                
    Traceback (most recent call last):
      File "index.py", line 687, in <module>
        app.run()  # standalone run
      File "/virtualenvs/OpenStreetMap.by-MOXOekcf/lib/python2.7/site-packages/web/application.py", line 375, in run
        return wsgi.runwsgi(self.wsgifunc(*middleware))
      File "index.py", line 685, in <lambda>
        web.wsgi.runwsgi = lambda func, addr=None: web.wsgi.runfcgi(func, addr)
      File "/virtualenvs/OpenStreetMap.by-MOXOekcf/lib/python2.7/site-packages/web/wsgi.py", line 17, in runfcgi
        import flup.server.fcgi as flups
    ImportError: No module named flup.server.fcgi
    
    opened by abitrolly 19
  • PEP8: Remove wildcard imports like

    PEP8: Remove wildcard imports like "from db import *"

    Fixes: #604 This needs careful review because it might have put enough imports in place to pass the tests but other apps might be looking for other imports.

    opened by cclauss 17
  • TypeError: write() argument must be str, not bytes

    TypeError: write() argument must be str, not bytes

    web.py release: 0.40 Python release: 3.7.3 (Debian buster)

    While porting a project from Python 2 to Python 3 (thanks for the 0.40 release!), I immediately encountered a bug in web.input(). Apparently, when a POST is sent by requests (as opposed to a web browser), web.py emits an error:

    TypeError: write() argument must be str, not bytes

    If debug is enabled, the default, then a stream of errors occur with the a similar error. See this issue for more information https://github.com/webpy/webpy/issues/448.

    Sure enough, setting web.config.debug = False will prevent the stream of errors, yet the originating error still exists. (Also, I want error handling, I'll address that later).

    The source of the error is in cgi.py, as it tries and copy the BytesIO object web.py created into a TemporaryFile that was created without wb+.

    Here is the cgi.py write error: https://github.com/python/cpython/blob/ef4ec6ed12d6c6200a85068f60483723298b6ff4/Lib/cgi.py#L704

    Here is the web.py BytesIO creation: https://github.com/webpy/webpy/blob/fa27cc510e39af9c32e015c8daf51023a6e80007/web/webapi.py#L443-L444

    I am able fix this by monkey patching cgi.py, as the source of the error is make_file: https://github.com/python/cpython/blob/ef4ec6ed12d6c6200a85068f60483723298b6ff4/Lib/cgi.py#L814-L842

    Here is a test case:

    import cgi
    import web
    import json
    import tempfile
    
    urls = (
        '/', 'index'
    )
    
    class index:
        def POST(self):
            inputs = web.input()
            data = json.loads(web.data())
            print(inputs, data)
            return "Hello, world!"
    
    def make_file(self):
        return tempfile.TemporaryFile("wb+")
    
    # Comment out this line to reproduce the error                                                                                                                               
    cgi.FieldStorage.make_file = make_file
    
    if __name__ == "__main__":
        # Comment this line to see the stream of errors. Note, make_file
        # also needs to be the default, not patched, version.
        web.config.debug = False
        app = web.application(urls, globals())
        app.run()
    

    You may test this with httpie:

    $ http -v POST localhost:8080 a=b
    

    One last comment, when monkey patching cgi.py, the debugging error page works again.

    Is there anything else I can submit to help solve this?

    opened by kjmph 17
  • len doesn't work on query result

    len doesn't work on query result

    With web.py current master, using len on db results is not working.

    $ git log -n 1 --oneline
    e90573e (HEAD -> master, origin/master, origin/HEAD, anandology/master) Reformat with Black :(
    
    $ python
    Python 3.7.4 (v3.7.4:e09359112e, Jul  8 2019, 14:54:52)
    [Clang 6.0 (clang-600.0.57)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import web
    
    >>>
    >>> db = web.database(dbn="postgres", db="webpy")
    >>>
    >>> len(db.query("SELECT 1"))
    0.0 (1): SELECT 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: object of type 'IterBetter' has no len()
    

    There is already a test for this as part of the test suite, but not sure how Travis is letting it go.

    opened by anandology 15
  • Fix incorrect str/bytes type of session data.

    Fix incorrect str/bytes type of session data.

    Fixes #644

    Works with:

    • MySQL column type TEXT and VARBINARY
    • PostgreSQL column type TEXT and bytea

    py3 code i used for testing:

    import web
    
    web.config.debug = False
    
    urls = (
        "/count", "count",
    )
    
    app = web.application(urls, locals())
    
    conn = web.database(
        dbn='mysql',    # Use `postgres` for PostgreSQL
        host='localhost',
        port=3306,    # Use `5432` for PostgreSQL
        db='<db-name>',
        user='<db-user>',
        pw='<db-password>',
    )
    
    session = web.session.Session(
        app=app,
        store=web.session.DBStore(conn, "sessions"),
        initializer={"count": 0},
    )
    
    class count:
        def GET(self):
            session.count += 1
            return str(session.count)
    
    if __name__ == "__main__":
        app.run()
    
    opened by iredmail 14
  • Pip installs 0.38 but there is a 0.40.dev0 on Pypi

    Pip installs 0.38 but there is a 0.40.dev0 on Pypi

    This installs v0.38 from Pypi:

    $ pip install web.py
    

    However, the latest version on Pypi is 0.40.dev0.

    I don't think it is a good idea to release a .devX version to Pypi. One reason is that apparently, Pip ignores it.

    Note: If you want people to test a particular branch, they can install it (even using Pip) directly from the github repo, so there is no need to release it to Pypi. For example, to install the current state of the master branch:

    $ pip install git+https://https://github.com/webpy/[email protected]
    
    opened by andy-maier 12
  • Make re-compile thread-safe (Issue #214)

    Make re-compile thread-safe (Issue #214)

    Under heavy load, we sometimes see the following error (see issue #214) Exception in thread Thread-328: File "/pkg/lib/python2.7/site-packages/web/utils.py", line 500, in call update(block=True) File "/pkg/lib/python2.7/site-packages/web/utils.py", line 497, in update self.running[key].release() error: release unlocked lock

    This can happen when there is a thread-switch between the test and creation of self.running[key]. In this patch we acquire a lock first to make the test+create atomic.

    opened by HansWeltar 12
  • Validation of forms with value attribute set to an int

    Validation of forms with value attribute set to an int

    If the value attribute of a dropdown or radio button element is set to an integer and validation of the form containing that element fails the element's state is lost in the redisplayed form.

    If the following form was submitted with the textbox left blank and the first radio button selected the form displayed after validation would show an empty textbox and no radio button selected. simple_form = form.Form( form.Textbox('test', form.notnull, ), form.Radio('example', [1,2,3,4], ) )

    I think this happens because the form post is u/str and thus the value checks fail. Maybe this could be fixed by converting the values to strings for the test of equality in the render functions for these elements.

    243c243
    <             if self.value == value: select_p = ' selected="selected"'
    
    ---
    >             if self.value == str(value): select_p = ' selected="selected"'
    266c266
    <             if self.value == arg:
    
    ---
    >             if self.value == str(arg):
    
    wont fix 
    opened by fhsm 12
  • Table name exists injection

    Table name exists injection

    Table name exists injection

    When calling db.multiple_insert to insert data, the internally implemented SQL statement uses the form of splicing as follows

        def multiple_insert(self, tablename, values, seqname=None, _test=False):
            """
            Inserts multiple rows into `tablename`. The `values` must be a list of
            dictionaries, one for each row to be inserted, each with the same set
            of keys. Returns the list of ids of the inserted rows.
            Set `seqname` to the ID if it's not the default, or to `False`
            if there isn't one.
    
                >>> db = DB(None, {})
                >>> db.supports_multiple_insert = True
                >>> values = [{"name": "foo", "email": "[email protected]"}, {"name": "bar", "email": "[email protected]"}]
                >>> db.multiple_insert('person', values=values, _test=True)
                <sql: "INSERT INTO person (email, name) VALUES ('[email protected]', 'foo'), ('[email protected]', 'bar')">
            """
            if not values:
                return []
    
            if not self.supports_multiple_insert:
                out = [
                    self.insert(tablename, seqname=seqname, _test=_test, **v)
                    for v in values
                ]
                if seqname is False:
                    return None
                else:
                    return out
    
            keys = values[0].keys()
            # @@ make sure all keys are valid
    
            for v in values:
                if v.keys() != keys:
                    raise ValueError("Not all rows have the same keys")
    
            # enforce query order for the above doctest compatibility with Py3
            keys = sorted(keys)
    
            sql_query = SQLQuery(
                "INSERT INTO %s (%s) VALUES " % (tablename, ", ".join(keys))
            )
    
            for i, row in enumerate(values):
                if i != 0:
                    sql_query.append(", ")
                SQLQuery.join(
                    [SQLParam(row[k]) for k in keys],
                    sep=", ",
                    target=sql_query,
                    prefix="(",
                    suffix=")",
                )
    
    

    When the values parameter is passed by the front-end combination, the current end passes in a json value like {"title":"admin","content":"admin"} to the text parameterdb.multiple_insert("entries" , [text]). The form of the insert statement is "INSERT INTO %s (%s) VALUES"% (tablename, ", ".join(keys)), which causes injection on the table name. There are special symbol filtering and string conversion on the parameters, but the table name is not processed

    Input parameters:

    {"title": "222222","content)%20VALUES%20('admin'%20or%20updatexml(1,concat(0x7e,(version())),0)%20or%20'')%3b#(": "qweqwe"}
    

    sql_query:

    <class 'tuple'>: (<sql: "INSERT INTO entries (content) VALUES ('admin' or updatexml(1,concat(0x7e,(version())),0) or '');#(, title) VALUES ('qweqwe', '222222')">, <sql: 'SELECT last_insert_id();'>)

    Finally, it will report an error and execute the sql statement:

    pymysql.err.InternalError: (1105, "XPATH syntax error: '~5.7.26'")

    So, is it possible not to use splicing or to filter the table name as well

    opened by MisakiKata 11
  • cgi is deprecated and slated for removal in Python 3.13

    cgi is deprecated and slated for removal in Python 3.13

    Pytest on Python 3.11 pre-release will generate...

    web/webapi.py:6: DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13
        import cgi
    

    https://docs.python.org/3/library/cgi.html

    opened by cclauss 0
  • refactor: run pyupgrade on exists codes

    refactor: run pyupgrade on exists codes

    The command is pyupgrade --keep-percent-format --py3-plus, for we have python 3.5 and upper version support, and I think percent format is not deprecated in near future.

    opened by aisk 4
  • Autoreload breaks sessions

    Autoreload breaks sessions

    I've been using web.py 0.39 for years and decided to try and upgrade to 0.62 - all of my session code immediately broke and web.py stopped sending session cookies. I was using cheroot locally rather than WSGI as this is my development environment.

    I tracked the problem down to this part of the autoreload code in the application object constructor:

        self.add_processor(loadhook(Reloader()))
        if mapping_name and module_name:
            # when app is ran as part of a package, this puts the app into
            # `sys.modules` correctly, otherwise the first change to the
            # app module will not be picked up by Reloader
            reload_mapping()
            self.add_processor(loadhook(reload_mapping))
    

    Specifically, the issue is the line calling reload_mapping(). web.py 0.39 did not do this.

    Calling reload_mapping() here is causing a reload of the application object, which clears and rebuilds the processors list. This removes the processor added by any Session() object and therefore prevents all sessions from working.

    By commenting out the reload_mapping() line, it fixed the issue for me. I have not submitted a patch, because I don't know exactly what it was solving (what's wrong with doing the first reload check on first request as it was doing previously?) and whether it was the solution to another problem.

    For those that don't need the feature, you can also pass autoreload=False when creating your application object to avoid the issue.

    opened by bobintetley 2
Releases(0.62)
  • 0.62(Nov 9, 2020)

    • Fixed: application.load() assumes ctx.path will be a latin1 string #687
    • Fixed: can not reset session data to same value as initialized. #683
    • Fixed: can not set session expire time. #655
    • Fixed: not export session store MemoryStore.
    Source code(tar.gz)
    Source code(zip)
  • 0.61(Jul 25, 2020)

  • 0.60(Jul 23, 2020)

    Changes:

    • Python-2 support has been completely dropped. Welcome to Python 3.
    • Fixed: session store DiskStore doesn't return correctly if session directory doesn't exist. #652
    • Fixed: incorrect str/bytes type of session data. #644 #645
    • Fixed: db.query("insert... returning") fails to commit. #648 #649
    Source code(tar.gz)
    Source code(zip)
  • 0.51(Mar 25, 2020)

  • 0.50(Mar 21, 2020)

    • New session store MemoryStore, used to save a session in memory. Should be useful where there are limited fs writes to the disk, like flash memories. #174
    • Fixed: not support samesite=none. #592
    • Fixed Python-3 compatibility issues: #574, #576.
    • Support tuple and set in sqlquote().
    • Drop support for SQL driver pgdb. It was dead, you cannot even find its website or download link.
    • Drop support for SQL driver psycopg. The latest version was released in 2006 (14 years ago), please use psycopg2 instead.
    • Removed function web.safemarkdown. if it's used in your application, you can install the Markdown module from pypi (https://pypi.org/project/Markdown/), then replace web.safemarkdown() by markdown.markdown().
    Source code(tar.gz)
    Source code(zip)
  • 0.40(Sep 27, 2019)

    Note: 0.40 is the last release which supports Python 2. Future releases will drop support for Python 2.

    • Fixed lots of Python-3 compatibility issues.
    • Drop support for Python < 2.7.
    • Allow to get form data from http PATCH request (fixes #259, tx @kufd)
    • Only store new session data if the data is non-default (fixes #161, tx @shish)
    • Supports SameSite cookie attribute (fixes #61 #99 #337)
    • Cookie expire time is now set to same as session timeout (fixes #409 #410)
    • Supports url for SQLite database like sqlite:///mydb.sqlite, sqlite:////absolute/path/mydb.sqlite (fixes #209, tx @iamFIREcracker)
    • Allow HTML5 form input elements in web.form.Input() (fixes #440, tx @jimgregory)
    • Add more form classes for different types: Email, Url, Number, Range, Color, Search, Telephone and Datalist (fixes #98 #497, tx @faruken @gjdv)
    • Return body for NoMethod error handler (fixes #240, tx @waldhol)
    • Directory experimental/ has been removed, it's not used and out of date.
    • Module web/webopenid.py has been removed, it uses old python-openid module which was released 9 years ago. If you need openid support, consider python-openid2 or other packages available on https://pypi.org/.
    • Fixed unicode in request url (fixes #461, tx @schneidersoft)
    • Fixed inline comment in Templator which leads to unexpected behavior (fixes #432, tx @lucylqe)
    • Fixed missing exception (ValueError) for socket.inet_pton to be compatible with twisted patched socket.inet_pton (fixes #464, tx @tclh123)
    • Fixed incorrect order of arguments for sending email with boto (fixes #204, tx @asldevi)
    • Fixed notfound message is not utf-8 charset (fixes #500, tx @by-z)
    • Fixed error in creating pooled PostgresDB with pgdb driver (fixes #255, tx @PriceChild)
    • Fixed IP address which contains space should not pass validation (fixes #140, tx @chuangbo)
    • Fixed incorrect returned row ids with multiple_insert() (fixes #263 #447)
    • Fixed not correctly render the id attribute after changed (fixes #339, tx @jimgregory)
    • Fixed DiskStore concurrency issue (fixes Fixes #83 #182 #191 #289 #470, tx @skawouter)
    • Fixed app module isn't picked up by Reloader for first code change (fixes #438, tx @jzellman)
    Source code(tar.gz)
    Source code(zip)
Asita is a web application framework for python based on express-js framework.

Asita is a web application framework for python. It is designed to be easy to use and be more easy for javascript users to use python frameworks because it is based on express-js framework.

Mattéo 4 Nov 16, 2021
bottle.py is a fast and simple micro-framework for python web-applications.

Bottle: Python Web Framework Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module a

Bottle Micro Web Framework 7.6k Jun 30, 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
Pyrin is an application framework built on top of Flask micro-framework to make life easier for developers who want to develop an enterprise application using Flask

Pyrin A rich, fast, performant and easy to use application framework to build apps using Flask on top of it. Pyrin is an application framework built o

Mohamad Nobakht 10 Jan 25, 2022
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.2k Jul 1, 2022
Fast, asynchronous and elegant Python web framework.

Warning: This project is being completely re-written. If you're curious about the progress, reach me on Slack. Vibora is a fast, asynchronous and eleg

vibora.io 5.7k Jun 26, 2022
The Python micro framework for building web applications.

Flask Flask is a lightweight WSGI web application framework. It is designed to make getting started quick and easy, with the ability to scale up to co

The Pallets Projects 59.3k Jun 24, 2022
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Tornado Web Server Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking ne

null 20.6k Jun 30, 2022
Async Python 3.6+ web server/framework | Build fast. Run fast.

Sanic | Build fast. Run fast. Build Docs Package Support Stats Sanic is a Python 3.6+ web server and web framework that's written to go fast. It allow

Sanic Community Organization 16.2k Jun 30, 2022
Pyramid - A Python web framework

Pyramid Pyramid is a small, fast, down-to-earth, open source Python web framework. It makes real-world web application development and deployment more

Pylons Project 3.7k Jul 4, 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.8k Jun 27, 2022
Free and open source full-stack enterprise framework for agile development of secure database-driven web-based applications, written and programmable in Python.

Readme web2py is a free open source full-stack framework for rapid development of fast, scalable, secure and portable database-driven web-based applic

null 2k Jun 22, 2022
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. You can develop your web applications with Python, taking advantage of its functionalities and integrating them to the fullest.

null 81 Jun 12, 2022
Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints.

Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints. check parameters and generate API documents automatically. Flask Sugar是一个基于flask,pyddantic,类型注解的API框架, 可以检查参数并自动生成API文档

null 163 Jun 16, 2022
APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects

APIFlask APIFlask is a lightweight Python web API framework based on Flask and marshmallow-code projects. It's easy to use, highly customizable, ORM/O

Grey Li 589 Jul 1, 2022
Chisel is a light-weight Python WSGI application framework built for creating well-documented, schema-validated JSON web APIs

chisel Chisel is a light-weight Python WSGI application framework built for creating well-documented, schema-validated JSON web APIs. Here are its fea

Craig Hobbs 2 Dec 2, 2021
Appier is an object-oriented Python web framework built for super fast app development.

Joyful Python Web App development Appier is an object-oriented Python web framework built for super fast app development. It's as lightweight as possi

Hive Solutions 120 May 19, 2022
Dazzler is a Python async UI/Web framework built with aiohttp and react.

Dazzler is a Python async UI/Web framework built with aiohttp and react. Create dazzling fast pages with a layout of Python components and bindings to update from the backend.

Philippe Duval 15 Dec 6, 2021
A public API written in Python using the Flask web framework to determine the direction of a road sign using AI

python-public-API This repository is a public API for solving the problem of the final of the AIIJC competition. The task is to create an AI for the c

Lev 1 Nov 8, 2021